From 45982a9894c5bff60ff494a0f82865ec267d52f7 Mon Sep 17 00:00:00 2001 From: lordhavoc Date: Tue, 4 Dec 2001 13:28:29 +0000 Subject: [PATCH] rewrote RecursiveHullCheck, no longer gets stuck on angle changes, and is generally more correct all the time (no longer uses PointContents checks either) added content value to RecursiveHullCheck and TraceLine, they can now treat any content change as an impact TraceLine now can take NULL impact and normal if they are not desired TraceLine now sets trace_endcontents to the impacted content value rewrote nehahra/rogue/hipnotic/standard_quake variables to be gamemode (GAME_NORMAL, GAME_HIPNOTIC, GAME_ROGUE, GAME_NEHAHRA, etc) unfinished code for directional static lighting on models (CL_ParseEntityLump) game now uses current mode as title everywhere (window title, server title, etc), so it would say 'DarkPlaces-Hipnotic' for example added Draw_AdditiveString variant of Draw_String, switchs to additive blending and back to alpha afterward engineversion string is now generated in sys_shared major rewrite of transpolyrender, now uses glDrawElements (with batching of same texture/mode) and array locking transpolyparticle added to quickly add particles to transpoly list (30% or so savings) split wallpolyrender into two pieces, first renders walls, second renders fog over them, decals are rendered between the two, so decals are now fogged added field of vision distortion when underwater (in MYgluPerspective) changed gl_lightmapalign to align to the specified byte boundary instead of pixel boundary, and removed NVIDIA mentions (it is not their problem, it is a matter of the texture unpack alignment, but I stuck with 4 byte alignment because it is likely faster for most people) fixed animating textures rearranged a little bmodel code (probably no effect) got rid of r_solidworldnode and r_pvsworldnode cvars (only the fastest choices are available now) screenshots are now corrected to match lighthalf if it is being done using hardware gamma removed some old unused cruft from host.c added RGB gamma correction code to image.c added VectorRandom to mathlib.h model skins are no longer mipmapped by default (r_mipskins 0, but this is saved in configs so most people might not notice) because quake skins were not designed for it, and it is a 25% texture memory use increase on model skins removed old unused Mod_FloodFillSkin code transparent textures no longer clip other geometry in the hidden surface removal (ouch this was a bug) maps should be able to use engine fields without the mod knowing about them now (alpha, etc), engine fields are appended to the list of progs fields particle and decal textures are now all stored in one 'particle font' texture, for a rather hefty speed gain (no texture switchs) all particles are now alpha blended (additive wasn't necessary on them, but is still available), to kill off state changes new splash effect from raindrops added a few bithacking float optimizations here and there (most with alternates if you define SLOWMATH) new explosion effect (on by default, but a major speed drain, turn off with r_particles_explosions 0) particle textures are now all in one image (a 'particle font'), massive speed gains with mixed particle types all particles are alpha blend now (additive still supported, just not used), for more speed gains particles now use 24bit RGB colors, rather than palette colors (the quake palette has been included however, because many particles still use it) a lot of old cruft has been removed from r_part ui items can now be strings rather than pics (actually they can be both, but I have not found a real use for this, perhaps a second draw location needs to be added for the string, so a button could have a label centered on it) unfinished X11 gamma ramp support (need to allocate colors before setting them, haven't figured this out yet) changed pitch range in GLX to let you look straight up and down, like in wgl version mostly redesigned animation interpolation management code (R_LerpUpdate is now CL_LerpUpdate and performed on all network entities, R_LerpAnimation has been tweaked to not crash on bmodels and is now automatically used on all visible entities in the renderer, lerping info has has been split out of entity_render_t into entity_persistent_t so that entity_render_t contains no persistent data) renderer now only uses entity_render_t structures renderer now uses only currentrenderentity, and rarely passes individual properties around cleaned out some old global variables relating to rendering moved most of glquake.h to render.h envmap is now actually a vaguely useful command (renders cubic environment map images of the current scene, changed to write tga images rather than raw rgba, and take a basename to use, and name them like skyboxes expect, and place them in the env directory) many things that should be private to a particular file have been marked static models now contain a SERAddEntity function (to add themselves to the SER clipping list to verify visibility) models now contain DrawEarly and DrawLate functions (to render before and after wallpoly/decals/skypoly/etc, respectively) dlight management functions moved out of cl_main and into cl_light rewrote RelinkStaticEntities (does the same, just cleaner) renamed RelinkEntities to RelinkNetworkEntities, split out LerpPlayerVelocity, and made a RelinkEntities function which calls the various functions rewrote or altered portions of RelinkNetworkEntities relating to origin muzzleflash lights are now clipped to keep them out of walls fixed up code relating to vid.conwidth/height and vid.width/height (which is now gone, converted to vid.conwidth/height) and renamed glx/gly/glwidth/glheight to vid.realx/y/width/height (updated each frame using GL_BeginRendering) rewrote most (all?) code relating to r_refdef, it is now always recalculated as well dynamic lights will only update a lightmap if they actually alter it (optimization) models now have 3 bounding boxes, used depending on angles (normal, yaw rotation only, and full rotation) bmodel bounding boxes are recalculated from vertices server now uses model bounding box instead of entity bounding box for visibility testing (since entity bounding box is often smaller) server no longer portal-visibility checks entities because it was FAR too slow (sv_vischeckentities is still available though) gl_rsurf code now relies on there being a currentrenderentity (even if it is cl.worldent.render), R_SetupWorldEnt added to avoid duplicate code for this engine no longer has a version number, only build number makefile now uses buildnum (as was originally intended) to increment build number every time it is compiled, build numbers will be rising rapidly from now on timedemos will now force up console instantly rocket trails are more dense renamed VectorMA (function) to VectorMASlow, renamed VectorMAQuick (#define) to VectorMA, don't know why I had changed it before, had already cleaned up the parameter issues where it is used converted most of lighting in decal code to integer added support for all sprite types (untested) git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@1185 d7cf8633-e32d-0410-b094-e92efae38249 --- buildnumber.c | 2 +- chase.c | 24 +- cl_demo.c | 9 +- cl_effects.c | 62 ++-- cl_light.c | 99 ++++++ cl_light.h | 21 ++ cl_main.c | 287 ++++++++-------- cl_parse.c | 338 +++++++++++++++++-- cl_tent.c | 2 +- client.h | 5 +- common.c | 102 ++++-- common.h | 10 +- console.c | 2 +- draw.h | 1 + gl_draw.c | 44 +-- gl_models.c | 230 +++++++------ gl_poly.c | 616 ++++++++++++++++++++++------------- gl_poly.h | 8 +- gl_rmain.c | 437 +++++++------------------ gl_rmisc.c | 144 ++++---- gl_rsurf.c | 684 +++++++++++++------------------------- gl_screen.c | 167 ++++------ glquake.h | 50 --- host.c | 12 - host_cmd.c | 143 ++++---- image.c | 12 + image.h | 1 + keys.c | 6 +- makefile | 14 +- mathlib.c | 2 +- mathlib.h | 9 +- menu.c | 106 +++--- model_alias.c | 210 ++++++------ model_brush.c | 235 +++++++------ model_brush.h | 1 - model_shared.h | 15 +- model_sprite.c | 83 +++-- portals.c | 14 +- pr_cmds.c | 13 +- pr_edict.c | 112 +++++-- quakedef.h | 2 - r_clip.c | 12 +- r_crosshairs.c | 3 +- r_decals.c | 203 ++++++++---- r_decals.h | 2 +- r_explosion.c | 176 ++++++++-- r_lerpanim.c | 254 +++++++-------- r_lerpanim.h | 9 +- r_light.c | 249 ++++++++------ r_light.h | 19 +- r_part.c | 869 +++++++++++++++++++++++++------------------------ r_sprites.c | 168 +++++----- render.h | 124 +++++-- sbar.c | 227 +++++-------- sv_main.c | 86 +++-- sv_phys.c | 2 + sv_user.c | 4 +- sys.h | 4 + sys_linux.c | 4 +- sys_shared.c | 25 +- sys_win.c | 11 +- transform.c | 14 +- transform.h | 4 +- ui.c | 84 +++-- ui.h | 3 +- vid.h | 18 +- vid_3dfxsvga.c | 4 +- vid_glx.c | 227 +++++++++---- vid_wgl.c | 16 +- view.c | 16 +- view.h | 1 + world.c | 452 +++++++++++++++---------- world.h | 23 +- 73 files changed, 4253 insertions(+), 3394 deletions(-) create mode 100644 cl_light.c create mode 100644 cl_light.h diff --git a/buildnumber.c b/buildnumber.c index 93dd2d40..9bbf28af 100644 --- a/buildnumber.c +++ b/buildnumber.c @@ -1,4 +1,4 @@ -#define BUILDNUMBER 105 +#define BUILDNUMBER 253 int buildnumber = BUILDNUMBER; diff --git a/chase.c b/chase.c index 4633565e..f4ee5b96 100644 --- a/chase.c +++ b/chase.c @@ -8,7 +8,7 @@ of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. @@ -38,16 +38,26 @@ void Chase_Reset (void) // start position 12 units behind head } -float TraceLine (vec3_t start, vec3_t end, vec3_t impact, vec3_t normal) +int traceline_endcontents; + +float TraceLine (vec3_t start, vec3_t end, vec3_t impact, vec3_t normal, int contents) { - trace_t trace; + trace_t trace; memset (&trace, 0, sizeof(trace)); VectorCopy (end, trace.endpos); trace.fraction = 1; - SV_RecursiveHullCheck (cl.worldmodel->hulls, 0, 0, 1, start, end, &trace); - VectorCopy (trace.endpos, impact); - VectorCopy (trace.plane.normal, normal); + trace.startcontents = contents; + VectorCopy(start, RecursiveHullCheckInfo.start); + VectorSubtract(end, start, RecursiveHullCheckInfo.dist); + RecursiveHullCheckInfo.hull = cl.worldmodel->hulls; + RecursiveHullCheckInfo.trace = &trace; + SV_RecursiveHullCheck (0, 0, 1, start, end); + if (impact) + VectorCopy (trace.endpos, impact); + if (normal) + VectorCopy (trace.plane.normal, normal); + traceline_endcontents = trace.endcontents; return trace.fraction; } @@ -66,7 +76,7 @@ void Chase_Update (void) chase_dest[1] = r_refdef.vieworg[1] + forward[1] * dist; chase_dest[2] = r_refdef.vieworg[2] + forward[2] * dist + chase_up.value; - TraceLine (r_refdef.vieworg, chase_dest, stop, normal); + TraceLine (r_refdef.vieworg, chase_dest, stop, normal, 0); chase_dest[0] = stop[0] + forward[0] * 8 + normal[0] * 4; chase_dest[1] = stop[1] + forward[1] * 8 + normal[1] * 4; chase_dest[2] = stop[2] + forward[2] * 8 + normal[2] * 4; diff --git a/cl_demo.c b/cl_demo.c index 34c875ea..ee61e500 100644 --- a/cl_demo.c +++ b/cl_demo.c @@ -365,10 +365,15 @@ void CL_TimeDemo_f (void) } CL_PlayDemo_f (); - + // cls.td_starttime will be grabbed at the second frame of the demo, so // all the loading time doesn't get counted - + + // instantly hide console and deactivate it + key_dest = key_game; + scr_conlines = 0; + scr_con_current = 0; + cls.timedemo = true; cls.td_startframe = host_framecount; cls.td_lastframe = -1; // get a new message this frame diff --git a/cl_effects.c b/cl_effects.c index 42341f0e..5020aaa4 100644 --- a/cl_effects.c +++ b/cl_effects.c @@ -33,25 +33,25 @@ typedef struct effect_s int endframe; // these are for interpolation int frame; - double frame1start; - double frame2start; + double frame1time; + double frame2time; } effect_t; -effect_t effect[MAX_EFFECTS]; +static effect_t effect[MAX_EFFECTS]; -cvar_t r_draweffects = {0, "r_draweffects", "1"}; +static cvar_t r_draweffects = {0, "r_draweffects", "1"}; -void r_effects_start(void) +static void r_effects_start(void) { memset(effect, 0, sizeof(effect)); } -void r_effects_shutdown(void) +static void r_effects_shutdown(void) { } -void r_effects_newmap(void) +static void r_effects_newmap(void) { memset(effect, 0, sizeof(effect)); } @@ -82,12 +82,14 @@ void CL_Effect(vec3_t org, int modelindex, int startframe, int framecount, float e->framerate = framerate; e->frame = 0; - e->frame1start = cl.time; - e->frame2start = cl.time; + e->frame1time = cl.time; + e->frame2time = cl.time; break; } } +extern void CL_LerpAnimation(entity_t *e); + void CL_DoEffects() { int i, intframe; @@ -111,28 +113,30 @@ void CL_DoEffects() if (intframe != e->frame) { e->frame = intframe; - e->frame1start = e->frame2start; - e->frame2start = cl.time; + e->frame1time = e->frame2time; + e->frame2time = cl.time; } - vis = CL_NewTempEntity(); - if (!vis) - continue; - VectorCopy(e->origin, vis->render.origin); - vis->render.lerp_model = vis->render.model = cl.model_precache[e->modelindex]; - vis->render.frame1 = e->frame; - vis->render.frame2 = e->frame + 1; - if (vis->render.frame2 >= e->endframe) - vis->render.frame2 = -1; // disappear - vis->render.frame = vis->render.frame2; - vis->render.framelerp = frame - vis->render.frame1; - vis->render.frame1start = e->frame1start; - vis->render.frame2start = e->frame2start; - vis->render.lerp_starttime = -1; - vis->render.colormap = -1; // no special coloring - vis->render.scale = 1; - vis->render.alpha = 1; - vis->render.colormod[0] = vis->render.colormod[1] = vis->render.colormod[2] = 1; + if ((vis = CL_NewTempEntity())) + { + // interpolation stuff + vis->render.frame1 = intframe; + vis->render.frame2 = intframe + 1; + if (vis->render.frame2 >= e->endframe) + vis->render.frame2 = -1; // disappear + vis->render.framelerp = frame - intframe; + vis->render.frame1time = e->frame1time; + vis->render.frame2time = e->frame2time; + + // normal stuff + VectorCopy(e->origin, vis->render.origin); + vis->render.model = cl.model_precache[e->modelindex]; + vis->render.frame = vis->render.frame2; + vis->render.colormap = -1; // no special coloring + vis->render.scale = 1; + vis->render.alpha = 1; + vis->render.colormod[0] = vis->render.colormod[1] = vis->render.colormod[2] = 1; + } } } } diff --git a/cl_light.c b/cl_light.c new file mode 100644 index 00000000..e4b9d4bb --- /dev/null +++ b/cl_light.c @@ -0,0 +1,99 @@ +#include "quakedef.h" + +dlight_t cl_dlights[MAX_DLIGHTS]; + +void cl_light_start(void) +{ +} + +void cl_light_shutdown(void) +{ +} + +void cl_light_newmap(void) +{ + memset (cl_dlights, 0, sizeof(cl_dlights)); +} + +void CL_Light_Init(void) +{ + R_RegisterModule("CL_Light", cl_light_start, cl_light_shutdown, cl_light_newmap); +} + +/* +=============== +CL_AllocDlight + +=============== +*/ +void CL_AllocDlight (entity_render_t *ent, vec3_t org, float radius, float red, float green, float blue, float decay, float lifetime) +{ + int i; + dlight_t *dl; + +// first look for an exact key match + if (ent) + { + dl = cl_dlights; + for (i = 0;i < MAX_DLIGHTS;i++, dl++) + if (dl->ent == ent) + goto dlightsetup; + } + +// then look for anything else + dl = cl_dlights; + for (i = 0;i < MAX_DLIGHTS;i++, dl++) + if (!dl->radius) + goto dlightsetup; + + // unable to find one + return; + +dlightsetup: + memset (dl, 0, sizeof(*dl)); + dl->ent = ent; + VectorCopy(org, dl->origin); + dl->radius = radius; + dl->color[0] = red; + dl->color[1] = green; + dl->color[2] = blue; + dl->decay = decay; + dl->die = cl.time + lifetime; +} + + +/* +=============== +CL_DecayLights + +=============== +*/ +void CL_DecayLights (void) +{ + int i; + dlight_t *dl; + float time; + + time = cl.time - cl.oldtime; + + c_dlights = 0; + dl = cl_dlights; + for (i=0 ; iradius) + continue; + if (dl->die < cl.time) + { + dl->radius = 0; + continue; + } + + c_dlights++; // count every dlight in use + + dl->radius -= time*dl->decay; + if (dl->radius < 0) + dl->radius = 0; + } +} + + diff --git a/cl_light.h b/cl_light.h new file mode 100644 index 00000000..38430655 --- /dev/null +++ b/cl_light.h @@ -0,0 +1,21 @@ + +// LordHavoc: 256 dynamic lights +#define MAX_DLIGHTS 256 +typedef struct +{ + vec3_t origin; + float radius; + float die; // stop lighting after this time + float decay; // drop this each second + entity_render_t *ent; // the entity that spawned this light (can be NULL if it will never be replaced) + vec3_t color; // LordHavoc: colored lighting +} dlight_t; + +// LordHavoc: this affects the lighting scale of the whole game +#define LIGHTOFFSET 4096.0f + +extern dlight_t cl_dlights[MAX_DLIGHTS]; + +extern void CL_AllocDlight (entity_render_t *ent, vec3_t org, float radius, float red, float green, float blue, float decay, float lifetime); +extern void CL_DecayLights (void); + diff --git a/cl_main.c b/cl_main.c index a938d12d..26b78cff 100644 --- a/cl_main.c +++ b/cl_main.c @@ -49,7 +49,6 @@ client_state_t cl; entity_t cl_entities[MAX_EDICTS]; entity_t cl_static_entities[MAX_STATIC_ENTITIES]; lightstyle_t cl_lightstyle[MAX_LIGHTSTYLES]; -dlight_t cl_dlights[MAX_DLIGHTS]; int cl_numvisedicts; entity_t *cl_visedicts[MAX_VISEDICTS]; @@ -72,9 +71,8 @@ void CL_ClearState (void) SZ_Clear (&cls.message); -// clear other arrays +// clear other arrays memset (cl_entities, 0, sizeof(cl_entities)); - memset (cl_dlights, 0, sizeof(cl_dlights)); memset (cl_lightstyle, 0, sizeof(cl_lightstyle)); memset (cl_temp_entities, 0, sizeof(cl_temp_entities)); memset (cl_beams, 0, sizeof(cl_beams)); @@ -87,6 +85,44 @@ void CL_ClearState (void) } } +void CL_LerpUpdate(entity_t *e, int frame, int modelindex) +{ + entity_persistent_t *p; + entity_render_t *r; + p = &e->persistent; + r = &e->render; + + if (p->modelindex != modelindex) + { + // reset all interpolation information + p->modelindex = modelindex; + p->frame1 = p->frame2 = frame; + p->frame1time = p->frame2time = cl.time; + p->framelerp = 1; + } + else if (p->frame2 != frame) + { + // transition to new frame + p->frame1 = p->frame2; + p->frame1time = p->frame2time; + p->frame2 = frame; + p->frame2time = cl.time; + p->framelerp = 0; + } + else + { + // update transition + p->framelerp = (cl.time - p->frame2time) * 10; + p->framelerp = bound(0, p->framelerp, 1); + } + + r->frame1 = p->frame1; + r->frame2 = p->frame2; + r->framelerp = p->framelerp; + r->frame1time = p->frame1time; + r->frame2time = p->frame2time; +} + /* ===================== CL_Disconnect @@ -186,7 +222,7 @@ Con_DPrintf ("CL_SignonReply: %i\n", cls.signon); MSG_WriteByte (&cls.message, clc_stringcmd); MSG_WriteString (&cls.message, "prespawn"); break; - + case 2: MSG_WriteByte (&cls.message, clc_stringcmd); MSG_WriteString (&cls.message, va("name \"%s\"\n", cl_name.string)); @@ -283,83 +319,6 @@ void CL_PrintEntities_f (void) } -/* -=============== -CL_AllocDlight - -=============== -*/ -void CL_AllocDlight (entity_t *ent, vec3_t org, float radius, float red, float green, float blue, float decay, float lifetime) -{ - int i; - dlight_t *dl; - -// first look for an exact key match - if (ent) - { - dl = cl_dlights; - for (i = 0;i < MAX_DLIGHTS;i++, dl++) - if (dl->ent == ent) - goto dlightsetup; - } - -// then look for anything else - dl = cl_dlights; - for (i = 0;i < MAX_DLIGHTS;i++, dl++) - if (!dl->radius) - goto dlightsetup; - - // unable to find one - return; - -dlightsetup: - memset (dl, 0, sizeof(*dl)); - dl->ent = ent; - VectorCopy(org, dl->origin); - dl->radius = radius; - dl->color[0] = red; - dl->color[1] = green; - dl->color[2] = blue; - dl->decay = decay; - dl->die = cl.time + lifetime; -} - - -/* -=============== -CL_DecayLights - -=============== -*/ -void CL_DecayLights (void) -{ - int i; - dlight_t *dl; - float time; - - time = cl.time - cl.oldtime; - - c_dlights = 0; - dl = cl_dlights; - for (i=0 ; iradius) - continue; - if (dl->die < cl.time) - { - dl->radius = 0; - continue; - } - - c_dlights++; // count every dlight in use - - dl->radius -= time*dl->decay; - if (dl->radius < 0) - dl->radius = 0; - } -} - - /* =============== CL_LerpPoint @@ -432,14 +391,9 @@ float CL_EntityLerpPoint (entity_t *ent) void CL_RelinkStaticEntities(void) { - entity_t *ent, *endent; - if (cl.num_statics > MAX_VISEDICTS) - Host_Error("CL_RelinkStaticEntities: cl.num_statics > MAX_VISEDICTS??\n"); - - ent = cl_static_entities; - endent = ent + cl.num_statics; - for (;ent < endent;ent++) - cl_visedicts[cl_numvisedicts++] = ent; + int i; + for (i = 0;i < cl.num_statics && cl_numvisedicts < MAX_VISEDICTS;i++) + cl_visedicts[cl_numvisedicts++] = &cl_static_entities[i]; } /* @@ -448,43 +402,18 @@ CL_RelinkEntities =============== */ void R_RocketTrail2 (vec3_t start, vec3_t end, int color, entity_t *ent); -void CL_RelinkEntities (void) +void CL_RelinkNetworkEntities() { entity_t *ent; int i, j, glowcolor, effects; - float frac, f, d, bobjrotate/*, bobjoffset*/, dlightradius, glowsize; - vec3_t oldorg, delta, dlightcolor; - -// determine partial update time - frac = CL_LerpPoint (); + float f, d, bobjrotate/*, bobjoffset*/, dlightradius, glowsize; + vec3_t oldorg, neworg, delta, dlightcolor; - cl_numvisedicts = 0; + bobjrotate = ANGLEMOD(100*cl.time); +// bobjoffset = cos(180 * cl.time * M_PI / 180) * 4.0f + 4.0f; CL_RelinkStaticEntities(); -// -// interpolate player info -// - for (i = 0;i < 3;i++) - cl.velocity[i] = cl.mvelocity[1][i] + frac * (cl.mvelocity[0][i] - cl.mvelocity[1][i]); - - if (cls.demoplayback) - { - // interpolate the angles - for (j = 0;j < 3;j++) - { - d = cl.mviewangles[0][j] - cl.mviewangles[1][j]; - if (d > 180) - d -= 360; - else if (d < -180) - d += 360; - cl.viewangles[j] = cl.mviewangles[1][j] + frac*d; - } - } - - bobjrotate = ANGLEMOD(100*cl.time); -// bobjoffset = cos(180 * cl.time * M_PI / 180) * 4.0f + 4.0f; - // start on the entity after the world for (i = 1, ent = cl_entities + 1;i < MAX_EDICTS /*cl.num_entities*/;i++, ent++) { @@ -492,33 +421,27 @@ void CL_RelinkEntities (void) if (!ent->state_current.active) continue; - VectorCopy (ent->render.origin, oldorg); + VectorCopy(ent->persistent.trail_origin, oldorg); if (!ent->state_previous.active) { // only one state available - VectorCopy (ent->state_current.origin, ent->render.origin); + VectorCopy (ent->state_current.origin, neworg); VectorCopy (ent->state_current.angles, ent->render.angles); -// Con_Printf(" %i", i); } else { // if the delta is large, assume a teleport and don't lerp - f = CL_EntityLerpPoint(ent); - if (f < 1) - { - for (j = 0;j < 3;j++) - { - delta[j] = ent->state_current.origin[j] - ent->state_previous.origin[j]; - // LordHavoc: increased lerp tolerance from 100 to 200 - if (delta[j] > 200 || delta[j] < -200) - f = 1; - } - } + VectorSubtract(ent->state_current.origin, ent->state_previous.origin, delta); + // LordHavoc: increased tolerance from 100 to 200 + if (DotProduct(delta, delta) > 200*200) + f = 1; + else + f = CL_EntityLerpPoint(ent); if (f >= 1) { // no interpolation - VectorCopy (ent->state_current.origin, ent->render.origin); + VectorCopy (ent->state_current.origin, neworg); VectorCopy (ent->state_current.angles, ent->render.angles); } else @@ -526,7 +449,7 @@ void CL_RelinkEntities (void) // interpolate the origin and angles for (j = 0;j < 3;j++) { - ent->render.origin[j] = ent->state_previous.origin[j] + f*delta[j]; + neworg[j] = ent->state_previous.origin[j] + f*delta[j]; d = ent->state_current.angles[j] - ent->state_previous.angles[j]; if (d > 180) @@ -538,6 +461,12 @@ void CL_RelinkEntities (void) } } + VectorCopy (neworg, ent->persistent.trail_origin); + // persistent.modelindex will be updated by CL_LerpUpdate + if (ent->state_current.modelindex != ent->persistent.modelindex) + VectorCopy(neworg, oldorg); + + VectorCopy (neworg, ent->render.origin); ent->render.flags = ent->state_current.flags; ent->render.effects = effects = ent->state_current.effects; ent->render.model = cl.model_precache[ent->state_current.modelindex]; @@ -555,6 +484,10 @@ void CL_RelinkEntities (void) ent->render.colormod[1] = (float) ((ent->state_current.colormod >> 2) & 7) * (1.0f / 7.0f); ent->render.colormod[2] = (float) (ent->state_current.colormod & 3) * (1.0f / 3.0f); + // update interpolation info + CL_LerpUpdate(ent, ent->state_current.frame, ent->state_current.modelindex); + + // handle effects now... dlightradius = 0; dlightcolor[0] = 0; dlightcolor[1] = 0; @@ -567,13 +500,14 @@ void CL_RelinkEntities (void) R_EntityParticles (ent); if (effects & EF_MUZZLEFLASH) { - vec3_t v; + vec3_t v, v2; AngleVectors (ent->render.angles, v, NULL, NULL); - v[0] = v[0] * 18 + ent->render.origin[0]; - v[1] = v[1] * 18 + ent->render.origin[1]; - v[2] = v[2] * 18 + ent->render.origin[2] + 16; + v2[0] = v[0] * 18 + neworg[0]; + v2[1] = v[1] * 18 + neworg[1]; + v2[2] = v[2] * 18 + neworg[2] + 16; + TraceLine(neworg, v2, v, NULL, 0); CL_AllocDlight (NULL, v, 100, 1, 1, 1, 0, 0.1); } @@ -602,14 +536,27 @@ void CL_RelinkEntities (void) dlightcolor[1] += 20.0f; dlightcolor[2] += 200.0f; } - else if (effects & EF_FLAME) + if (effects & EF_FLAME) { if (ent->render.model) { vec3_t mins, maxs; int temp; - VectorAdd(ent->render.origin, ent->render.model->mins, mins); - VectorAdd(ent->render.origin, ent->render.model->maxs, maxs); + if (ent->render.angles[0] || ent->render.angles[2]) + { + VectorAdd(neworg, ent->render.model->rotatedmins, mins); + VectorAdd(neworg, ent->render.model->rotatedmaxs, maxs); + } + else if (ent->render.angles[1]) + { + VectorAdd(neworg, ent->render.model->yawmins, mins); + VectorAdd(neworg, ent->render.model->yawmaxs, maxs); + } + else + { + VectorAdd(neworg, ent->render.model->normalmins, mins); + VectorAdd(neworg, ent->render.model->normalmaxs, maxs); + } // how many flames to make temp = (int) (cl.time * 300) - (int) (cl.oldtime * 300); R_FlameCube(mins, maxs, temp); @@ -633,13 +580,13 @@ void CL_RelinkEntities (void) if (ent->state_previous.active) { if (ent->render.model->flags & EF_GIB) - R_RocketTrail (oldorg, ent->render.origin, 2, ent); + R_RocketTrail (oldorg, neworg, 2, ent); else if (ent->render.model->flags & EF_ZOMGIB) - R_RocketTrail (oldorg, ent->render.origin, 4, ent); + R_RocketTrail (oldorg, neworg, 4, ent); else if (ent->render.model->flags & EF_TRACER) - R_RocketTrail (oldorg, ent->render.origin, 3, ent); + R_RocketTrail (oldorg, neworg, 3, ent); else if (ent->render.model->flags & EF_TRACER2) - R_RocketTrail (oldorg, ent->render.origin, 5, ent); + R_RocketTrail (oldorg, neworg, 5, ent); else if (ent->render.model->flags & EF_ROCKET) { R_RocketTrail (oldorg, ent->render.origin, 0, ent); @@ -650,12 +597,12 @@ void CL_RelinkEntities (void) else if (ent->render.model->flags & EF_GRENADE) { if (ent->render.alpha == -1) // LordHavoc: Nehahra dem compatibility - R_RocketTrail (oldorg, ent->render.origin, 7, ent); + R_RocketTrail (oldorg, neworg, 7, ent); else - R_RocketTrail (oldorg, ent->render.origin, 1, ent); + R_RocketTrail (oldorg, neworg, 1, ent); } else if (ent->render.model->flags & EF_TRACER3) - R_RocketTrail (oldorg, ent->render.origin, 6, ent); + R_RocketTrail (oldorg, neworg, 6, ent); } } // LordHavoc: customizable glow @@ -668,17 +615,18 @@ void CL_RelinkEntities (void) } // LordHavoc: customizable trail if (ent->render.flags & RENDER_GLOWTRAIL) - R_RocketTrail2 (oldorg, ent->render.origin, glowcolor, ent); + R_RocketTrail2 (oldorg, neworg, glowcolor, ent); if (dlightcolor[0] || dlightcolor[1] || dlightcolor[2]) { vec3_t vec; dlightradius = VectorLength(dlightcolor); d = 1.0f / dlightradius; - VectorCopy(ent->render.origin, vec); + VectorCopy(neworg, vec); + // hack to make glowing player light shine on their gun if (i == cl.viewentity && !chase_active.value) vec[2] += 30; - CL_AllocDlight (ent, vec, dlightradius, dlightcolor[0] * d, dlightcolor[1] * d, dlightcolor[2] * d, 0, 0); + CL_AllocDlight (&ent->render, vec, dlightradius, dlightcolor[0] * d, dlightcolor[1] * d, dlightcolor[2] * d, 0, 0); } if (chase_active.value) @@ -699,7 +647,40 @@ void CL_RelinkEntities (void) if (cl_numvisedicts < MAX_VISEDICTS) cl_visedicts[cl_numvisedicts++] = ent; } -// Con_Printf("\n"); +} + +void CL_LerpPlayerVelocity (void) +{ + int i; + float frac, d; + + // fraction from previous network update to current + frac = CL_LerpPoint (); + + for (i = 0;i < 3;i++) + cl.velocity[i] = cl.mvelocity[1][i] + frac * (cl.mvelocity[0][i] - cl.mvelocity[1][i]); + + if (cls.demoplayback) + { + // interpolate the angles + for (i = 0;i < 3;i++) + { + d = cl.mviewangles[0][i] - cl.mviewangles[1][i]; + if (d > 180) + d -= 360; + else if (d < -180) + d += 360; + cl.viewangles[i] = cl.mviewangles[1][i] + frac*d; + } + } +} + +void CL_RelinkEntities (void) +{ + cl_numvisedicts = 0; + + CL_LerpPlayerVelocity(); + CL_RelinkNetworkEntities(); } diff --git a/cl_parse.c b/cl_parse.c index f2c704f2..ec3d3d59 100644 --- a/cl_parse.c +++ b/cl_parse.c @@ -35,7 +35,7 @@ char *svc_strings[128] = "svc_stufftext", // [string] stuffed into client's console buffer // the string should be \n terminated "svc_setangle", // [vec3] set the view angle to this absolute value - + "svc_serverinfo", // [long] version // [string] signon string // [string]..[0]model cache [string]...[0]sounds cache @@ -94,7 +94,7 @@ void CL_Parse_Init(void) { // LordHavoc: added demo_nehahra cvar Cvar_RegisterVariable (&demo_nehahra); - if (nehahra) + if (gamemode == GAME_NEHAHRA) Cvar_SetValue("demo_nehahra", 1); } @@ -174,7 +174,7 @@ void CL_ParseStartSoundPacket(int largesoundindex) for (i=0 ; i<3 ; i++) pos[i] = MSG_ReadCoord (); - + S_StartSound (ent, channel, cl.sound_precache[sound_num], pos, volume/255.0, attenuation); } @@ -239,31 +239,90 @@ void CL_KeepaliveMessage (void) SZ_Clear (&cls.message); } +//FIXME finish this code! +#define MAX_STATICLIGHTS 2048 +// tyrlite types +#define LIGHTFADE_LMINUSX 0 // light, arghlite, others? +#define LIGHTFADE_LDIVX 1 +#define LIGHTFADE_LDIVX2 2 // hlight +#define LIGHTFADE_L 3 +#define LIGHTFADE_DEFAULT 999999 // light util not yet identified, switched later + +typedef struct +{ + int fadetype; // one of the LIGHTFADE_ values + int style; + vec3_t origin; + vec_t radius; // the point at which lighting stops + vec3_t direction; + vec_t cone; // if non-zero, it is a spot light + vec3_t color; + vec_t distancescale; // attenuation + vec_t lightsubtract; // biasing lighting toward black (hlight feature) +} +staticlight_t; + +staticlight_t staticlight[MAX_STATICLIGHTS]; +int staticlights; + +int r_sunlightenabled; +vec3_t r_sunlightdirection, r_sunlightcolor; +vec3_t r_light_ambientcolor; + void CL_ParseEntityLump(char *entdata) { char *data; char key[128], value[4096]; char wadname[128]; - int i, j, k; + char targetnamebuffer[65536]; + char *targetname[8192], *target[MAX_STATICLIGHTS], light_target[256]; + vec3_t targetnameorigin[8192], targetnametemporigin, v; + int targets, targetnames, targetnamebufferpos, targetnameorigintofillin; + int i, j, k, n; + float f1, f2, f3, f4; + float ambientlight, ambientcolor[3], sunlight, sunlightdirection[3], sunlightcolor[3]; + int light_fadetype, light_style, hlight, tyrlite, light_enable; + float light_origin[3], light_light, light_distancescale, light_lightcolor[3], light_color[3], light_direction[3], light_cone, light_lightradius; FOG_clear(); // LordHavoc: no fog until set R_SetSkyBox(""); // LordHavoc: no environment mapped sky until set r_farclip.value = 6144; // LordHavoc: default farclip distance + r_sunlightenabled = false; + staticlights = 0; data = entdata; if (!data) return; data = COM_Parse(data); if (!data) - return; // valid exit + return; // error if (com_token[0] != '{') return; // error + hlight = false; + tyrlite = false; + ambientlight = 0; + ambientcolor[0] = ambientcolor[1] = ambientcolor[2] = 1; + sunlight = 0; + sunlightcolor[0] = sunlightcolor[1] = sunlightcolor[2] = 1; + sunlightdirection[0] = 0; + sunlightdirection[1] = 0; + sunlightdirection[2] = -1; + targets = 0; + targetnames = 0; + targetnamebufferpos = 0; + targetnameorigintofillin = -1; + targetnametemporigin[0] = 0; + targetnametemporigin[1] = 0; + targetnametemporigin[2] = 0; while (1) { data = COM_Parse(data); if (!data) return; // error if (com_token[0] == '}') - return; // since we're just parsing the first ent (worldspawn), exit - strcpy(key, com_token); + break; // end of worldspawn + if (com_token[0] == '_') + strcpy(key, com_token + 1); + else + strcpy(key, com_token); while (key[strlen(key)-1] == ' ') // remove trailing spaces key[strlen(key)-1] = 0; data = COM_Parse(data); @@ -283,10 +342,7 @@ void CL_ParseEntityLump(char *entdata) r_farclip.value = 64; } else if (!strcmp("fog", key)) - { scanf(value, "%f %f %f %f", &fog_density, &fog_red, &fog_green, &fog_blue); - j = 0; - } else if (!strcmp("fog_density", key)) fog_density = atof(value); else if (!strcmp("fog_red", key)) @@ -325,6 +381,242 @@ void CL_ParseEntityLump(char *entdata) } } } + else if (!strcmp("light", key)) + ambientlight = atof(value); + else if (!strcmp("sunlight", key)) + { + sunlight = atof(value); + tyrlite = true; + } + else if (!strcmp("sun_color", key)) + { + if (scanf(value, "%f %f %f", &v[0], &v[1], &v[2]) == 3) + VectorCopy(v, sunlightcolor); + tyrlite = true; + } + else if (!strcmp("sun_mangle", key)) + { + if (scanf(value, "%f %f %f", &v[0], &v[1], &v[2]) == 3) + AngleVectors(v, sunlightdirection, NULL, NULL); + tyrlite = true; + } + else if (!strcmp("origin", key)) + { + if (scanf(value, "%f %f %f", &v[0], &v[1], &v[2]) == 3) + { + VectorCopy(v, targetnametemporigin); + VectorCopy(v, light_origin); + } + } + else if (!strcmp("targetname", key)) + { + if ((targetnames < 8192) && (strlen(value) + 1 + targetnamebufferpos <= 65536)) + { + targetname[targetnames] = targetnamebuffer + targetnamebufferpos; + strcpy(targetnamebuffer + targetnamebufferpos, value); + targetnamebufferpos += strlen(value) + 1; + targetnameorigintofillin = targetnames++; + } + } + } + if (targetnameorigintofillin >= 0) + VectorCopy(targetnametemporigin, targetnameorigin[targetnameorigintofillin]); + + if (sunlight) + { + r_sunlightenabled = true; + VectorScale(sunlightcolor, sunlight, r_sunlightcolor); + VectorCopy(sunlightdirection, r_sunlightdirection); + } + VectorScale(ambientcolor, ambientlight, r_light_ambientcolor); + + while(1) + { + data = COM_Parse(data); + if (!data) + break; // done + if (com_token[0] != '{') + break; // error + light_light = 0; + light_lightcolor[0] = light_lightcolor[1] = light_lightcolor[2] = 1.0f; + light_color[0] = light_color[1] = light_color[2] = 1.0f; + light_direction[0] = light_direction[1] = light_direction[2] = 0.0f; + light_cone = -cos(20*M_PI/180); + light_distancescale = 1.0f; + light_fadetype = LIGHTFADE_DEFAULT; // replaced later when light util is identified + light_style = 0; + light_lightradius = 0; + light_enable = false; + targetnameorigintofillin = -1; + targetnametemporigin[0] = 0; + targetnametemporigin[1] = 0; + targetnametemporigin[2] = 0; + while (1) + { + data = COM_Parse(data); + if (!data) + return; // error + if (com_token[0] == '}') + break; + if (com_token[0] == '_') + strcpy(key, com_token + 1); + else + strcpy(key, com_token); + while (key[strlen(key)-1] == ' ') // remove trailing spaces + key[strlen(key)-1] = 0; + data = COM_Parse(data); + if (!data) + return; // error + strcpy(value, com_token); + if (!strcmp("light", key)) + { + n = scanf(value, "%f %f %f %f", &f1, &f2, &f3, &f4); + switch(n) + { + case 1: + // id light, arghlite, tyrlite, others + light_light = f1; + light_lightcolor[0] = light_lightcolor[1] = light_lightcolor[2] = 1.0f; + break; + case 3: + // hlight specific (supports all 3 light formats, but this one is unique to it) + hlight = true; + light_light = max(f1, max(f2, f3)); + light_lightcolor[0] = f1 / light_light; + light_lightcolor[1] = f2 / light_light; + light_lightcolor[2] = f3 / light_light; + break; + case 4: + // halflife + hlight = true; // unless this is a halflife map, probably hlight + light_light = f4; + light_lightcolor[0] = f1 * (1.0f / 255.0f); + light_lightcolor[1] = f1 * (1.0f / 255.0f); + light_lightcolor[2] = f1 * (1.0f / 255.0f); + break; + default: + // error + break; + } + } + else if (!strcmp("color", key)) + { + n = scanf(value, "%f %f %f", &f1, &f2, &f3); + if (n == 3) + { + light_color[0] = f1; + light_color[1] = f2; + light_color[2] = f3; + } + // n != 3 is an error + } + else if (!strcmp("wait", key)) + light_distancescale = atof(value); + else if (!strcmp("delay", key)) + { + light_fadetype = atoi(value); + tyrlite = true; + } + else if (!strcmp("angle", key)) + light_cone = -cos(atof(value) * M_PI / 360); + else if (!strcmp("mangle", key)) + { + n = scanf(value, "%f %f %f", &v[0], &v[1], &v[2]); + if (n == 3) + AngleVectors(v, light_direction, NULL, NULL); + // n != 3 is an error + tyrlite = true; + } + else if (!strcmp("style", key)) + { + n = atoi(value); + if (n >= 0 && n < MAX_LIGHTSTYLES) + light_style = n; + } + else if (!strcmp("lightradius", key)) + { + hlight = true; + light_lightradius = atof(value); + } + else if (!strcmp("classname", key)) + if (!strncmp(value, "light", 5)) + light_enable = true; + else if (!strcmp("origin", key)) + { + if (scanf(value, "%f %f %f", &v[0], &v[1], &v[2]) == 3) + VectorCopy(v, targetnametemporigin); + } + else if (!strcmp("targetname", key)) + { + if ((targetnames < 8192) && (strlen(value) + 1 + targetnamebufferpos <= 65536)) + { + targetname[targetnames] = targetnamebuffer + targetnamebufferpos; + strcpy(targetnamebuffer + targetnamebufferpos, value); + targetnamebufferpos += strlen(value) + 1; + targetnameorigintofillin = targetnames++; + } + } + else if (!strcmp("target", key)) + if (strlen(value) < sizeof(light_target)) + strcpy(light_target, value); + } + if (targetnameorigintofillin >= 0) + VectorCopy(targetnametemporigin, targetnameorigin[targetnameorigintofillin]); + if (light_enable && staticlights < MAX_STATICLIGHTS && light_light != 0) + { + VectorCopy(light_origin, staticlight[staticlights].origin); + staticlight[staticlights].color[0] = light_light * light_lightcolor[0] * light_color[0]; + staticlight[staticlights].color[1] = light_light * light_lightcolor[1] * light_color[1]; + staticlight[staticlights].color[2] = light_light * light_lightcolor[2] * light_color[2]; + VectorCopy(light_direction, staticlight[staticlights].direction); + staticlight[staticlights].cone = light_cone; + staticlight[staticlights].distancescale = light_distancescale; + staticlight[staticlights].fadetype = light_fadetype; + staticlight[staticlights].style = light_style; + if (light_target && (targets < 8192) && (strlen(value) + 1 + targetnamebufferpos <= 65536)) + { + target[staticlights] = targetnamebuffer + targetnamebufferpos; + strcpy(targetnamebuffer + targetnamebufferpos, value); + targetnamebufferpos += strlen(value) + 1; + } + else + target[staticlights] = NULL; + staticlight[staticlights].lightsubtract = 0; + if (light_lightradius) + { + staticlight[staticlights].fadetype = LIGHTFADE_LDIVX2; + staticlight[staticlights].lightsubtract = max(staticlight[staticlights].color[0], max(staticlight[staticlights].color[1], staticlight[staticlights].color[2])) * 0.5f / (light_lightradius * light_distancescale * light_lightradius * light_distancescale * (1.0f / 65536.0f) + 1.0f); + } + staticlights++; + } + } + if (hlbsp) + n = LIGHTFADE_LDIVX2; + else if (tyrlite) + n = LIGHTFADE_LMINUSX; + else if (hlight) + n = LIGHTFADE_LDIVX2; + else + n = LIGHTFADE_LMINUSX; + for (i = 0;i < staticlights;i++) + { + if (staticlight[i].fadetype == LIGHTFADE_DEFAULT) + staticlight[i].fadetype = n; + if (target[i]) + { + for (j = 0;j < targetnames;j++) + { + if (!strcmp(target[i], targetname[j])) + { + VectorSubtract(targetnameorigin[j], staticlight[i].origin, v); + VectorNormalize(v); + VectorCopy(v, staticlight[i].direction); + break; + } + } + } + if (staticlight[i].direction[0] == 0 && staticlight[i].direction[1] == 0 && staticlight[i].direction[2] == 0) + staticlight[i].cone = 0; } } @@ -340,7 +632,7 @@ void CL_ParseServerInfo (void) int nummodels, numsounds; char model_precache[MAX_MODELS][MAX_QPATH]; char sound_precache[MAX_SOUNDS][MAX_QPATH]; - + Con_DPrintf ("Serverinfo packet received.\n"); // // wipe the client_state_t struct @@ -495,6 +787,11 @@ void CL_ValidateState(entity_state_t *s) Con_DPrintf("CL_ValidateState: no such frame %i in \"%s\"\n", s->frame, model->name); s->frame = 0; } + if (model && s->skin >= model->numskins) + { + Con_DPrintf("CL_ValidateState: no such skin %i in \"%s\"\n", s->skin, model->name); + s->skin = 0; + } } /* @@ -812,10 +1109,10 @@ void CL_ParseClientdata (int bits) i = MSG_ReadByte (); - if (standard_quake) - cl.stats[STAT_ACTIVEWEAPON] = i; - else + if (gamemode == GAME_HIPNOTIC || gamemode == GAME_ROGUE) cl.stats[STAT_ACTIVEWEAPON] = (1<= MAX_STATIC_ENTITIES) Host_Error ("Too many static entities"); ent = &cl_static_entities[cl.num_statics++]; @@ -836,9 +1133,8 @@ void CL_ParseStatic (int large) ent->render.model = cl.model_precache[ent->state_baseline.modelindex]; ent->render.frame = ent->render.frame1 = ent->render.frame2 = ent->state_baseline.frame; ent->render.framelerp = 0; - ent->render.lerp_starttime = -1; // make torchs play out of sync - ent->render.frame1start = ent->render.frame2start = -(rand() & 32767); + ent->render.frame1time = ent->render.frame2time = lhrandom(-10, -1); ent->render.colormap = -1; // no special coloring ent->render.skinnum = ent->state_baseline.skin; ent->render.effects = ent->state_baseline.effects; @@ -1046,7 +1342,7 @@ void CL_ParseServerMessage (void) case svc_serverinfo: CL_ParseServerInfo (); - vid.recalc_refdef = true; // leave intermission full screen +// vid.recalc_refdef = true; // leave intermission full screen break; case svc_setangle: @@ -1184,20 +1480,20 @@ void CL_ParseServerMessage (void) case svc_intermission: cl.intermission = 1; cl.completed_time = cl.time; - vid.recalc_refdef = true; // go to full screen +// vid.recalc_refdef = true; // go to full screen break; case svc_finale: cl.intermission = 2; cl.completed_time = cl.time; - vid.recalc_refdef = true; // go to full screen +// vid.recalc_refdef = true; // go to full screen SCR_CenterPrint (MSG_ReadString ()); break; case svc_cutscene: cl.intermission = 3; cl.completed_time = cl.time; - vid.recalc_refdef = true; // go to full screen +// vid.recalc_refdef = true; // go to full screen SCR_CenterPrint (MSG_ReadString ()); break; diff --git a/cl_tent.c b/cl_tent.c index 1c921fe3..d441a61e 100644 --- a/cl_tent.c +++ b/cl_tent.c @@ -524,7 +524,7 @@ void CL_UpdateTEnts (void) ent->render.angles[2] = rand()%360; if (r_glowinglightning.value > 0) - CL_AllocDlight(ent, ent->render.origin, lhrandom(100, 120), r_glowinglightning.value * 0.25f, r_glowinglightning.value * 0.25f, r_glowinglightning.value * 0.25f, 0, 0); + CL_AllocDlight(&ent->render, ent->render.origin, lhrandom(100, 120), r_glowinglightning.value * 0.25f, r_glowinglightning.value * 0.25f, r_glowinglightning.value * 0.25f, 0, 0); VectorMA(org, 30, dist, org); d -= 30; diff --git a/client.h b/client.h index a690fdc5..4b469bb3 100644 --- a/client.h +++ b/client.h @@ -263,17 +263,16 @@ extern client_state_t cl; extern entity_t cl_entities[MAX_EDICTS]; extern entity_t cl_static_entities[MAX_STATIC_ENTITIES]; extern lightstyle_t cl_lightstyle[MAX_LIGHTSTYLES]; -extern dlight_t cl_dlights[MAX_DLIGHTS]; extern entity_t cl_temp_entities[MAX_TEMP_ENTITIES]; extern beam_t cl_beams[MAX_BEAMS]; //============================================================================= +#include "cl_light.h" + // // cl_main // -extern void CL_AllocDlight (entity_t *ent, vec3_t org, float radius, float red, float green, float blue, float decay, float lifetime); -extern void CL_DecayLights (void); extern void CL_Init (void); diff --git a/common.c b/common.c index 4258945e..7a042874 100644 --- a/common.c +++ b/common.c @@ -58,7 +58,8 @@ char **com_argv; #define CMDLINE_LENGTH 1024 char com_cmdline[CMDLINE_LENGTH]; -qboolean standard_quake = true, rogue = false, hipnotic = false, nehahra = false; +int gamemode; +char *gamename; /* @@ -1120,28 +1121,48 @@ void COM_InitArgv (int argc, char **argv) largv[com_argc] = argvdummy; com_argv = largv; -#ifdef NEHAHRA - nehahra = true; - standard_quake = false; +#if ZYMOTIC + gamemode = GAME_ZYMOTIC; +#elif FIENDARENA + gamemode = GAME_FIENDARENA; +#elif NEHAHRA + gamemode = GAME_NEHAHRA; #else - if (COM_CheckParm ("-rogue")) - { - rogue = true; - standard_quake = false; - } - - if (COM_CheckParm ("-hipnotic")) - { - hipnotic = true; - standard_quake = false; - } - - if (COM_CheckParm ("-nehahra")) + if (COM_CheckParm ("-zymotic")) + gamemode = GAME_ZYMOTIC; + else if (COM_CheckParm ("-fiendarena")) + gamemode = GAME_FIENDARENA; + else if (COM_CheckParm ("-nehahra")) + gamemode = GAME_NEHAHRA; + else if (COM_CheckParm ("-hipnotic")) + gamemode = GAME_HIPNOTIC; + else if (COM_CheckParm ("-rogue")) + gamemode = GAME_ROGUE; +#endif + switch(gamemode) { - nehahra = true; - standard_quake = false; + case GAME_NORMAL: + gamename = "DarkPlaces"; + break; + case GAME_HIPNOTIC: + gamename = "Darkplaces-Hipnotic"; + break; + case GAME_ROGUE: + gamename = "Darkplaces-Rogue"; + break; + case GAME_NEHAHRA: + gamename = "DarkPlaces-Nehahra"; + break; + case GAME_FIENDARENA: + gamename = "FiendArena"; + break; + case GAME_ZYMOTIC: + gamename = "Zymotic"; + break; + default: + Sys_Error("COM_InitArgv: unknown gamemode %i\n", gamemode); + break; } -#endif } @@ -1378,7 +1399,7 @@ void COM_WriteFile (char *filename, void *data, int len) { int handle; char name[MAX_OSPATH]; - + sprintf (name, "%s/%s", com_gamedir, filename); // LordHavoc: added this @@ -1390,8 +1411,8 @@ void COM_WriteFile (char *filename, void *data, int len) Sys_Printf ("COM_WriteFile: failed on %s\n", name); return; } - - Sys_Printf ("COM_WriteFile: %s\n", name); + + Con_Printf ("COM_WriteFile: %s\n", name); Sys_FileWrite (handle, data, len); Sys_FileClose (handle); } @@ -1846,21 +1867,32 @@ void COM_InitFilesystem (void) com_cachedir[0] = 0; #endif -// // start up with GAMENAME by default (id1) -// COM_AddGameDirectory (va("%s/"GAMENAME, basedir) ); -#ifdef NEHAHRA - COM_AddGameDirectory (va("%s/nehahra", basedir) ); -#else - if (COM_CheckParm ("-rogue")) - COM_AddGameDirectory (va("%s/rogue", basedir) ); - if (COM_CheckParm ("-hipnotic")) + switch(gamemode) + { + case GAME_NORMAL: + break; + case GAME_HIPNOTIC: COM_AddGameDirectory (va("%s/hipnotic", basedir) ); - if (COM_CheckParm ("-nehahra")) + break; + case GAME_ROGUE: + COM_AddGameDirectory (va("%s/rogue", basedir) ); + break; + case GAME_NEHAHRA: COM_AddGameDirectory (va("%s/nehahra", basedir) ); -#endif + break; + case GAME_FIENDARENA: + COM_AddGameDirectory (va("%s/fiendarena", basedir) ); + break; + case GAME_ZYMOTIC: + COM_AddGameDirectory (va("%s/zymotic", basedir) ); + break; + default: + Sys_Error("COM_InitFilesystem: unknown gamemode %i\n", gamemode); + break; + } // // -game @@ -1886,7 +1918,7 @@ void COM_InitFilesystem (void) { if (!com_argv[i] || com_argv[i][0] == '+' || com_argv[i][0] == '-') break; - + search = Hunk_AllocName (sizeof(searchpath_t), "pack info"); if ( !strcmp(COM_FileExtension(com_argv[i]), "pak") ) { @@ -1924,7 +1956,7 @@ int COM_FileExists(char *filename) } else { - sprintf (netpath, "%s/%s",search->filename, filename); + sprintf (netpath, "%s/%s",search->filename, filename); findtime = Sys_FileTime (netpath); if (findtime != -1) return true; diff --git a/common.h b/common.h index 98467fd3..c7a0be34 100644 --- a/common.h +++ b/common.h @@ -213,7 +213,15 @@ int COM_FileExists(char *filename); extern struct cvar_s registered; -extern qboolean standard_quake, rogue, hipnotic, nehahra; +#define GAME_NORMAL 0 +#define GAME_HIPNOTIC 1 +#define GAME_ROGUE 2 +#define GAME_NEHAHRA 3 +#define GAME_FIENDARENA 4 +#define GAME_ZYMOTIC 5 + +extern int gamemode; +extern char *gamename; // LordHavoc: useful... extern void COM_ToLowerString(char *in, char *out); diff --git a/console.c b/console.c index 218ea632..2fe6eea9 100644 --- a/console.c +++ b/console.c @@ -160,7 +160,7 @@ void Con_CheckResize (void) int i, j, width, oldwidth, oldtotallines, numlines, numchars; char tbuf[CON_TEXTSIZE]; - width = (vid.width >> 3) - 2; + width = (vid.conwidth >> 3) - 2; if (width == con_linewidth) return; diff --git a/draw.h b/draw.h index 58efe1b2..80ba2d18 100644 --- a/draw.h +++ b/draw.h @@ -32,5 +32,6 @@ void Draw_PicTranslate (int x, int y, qpic_t *pic, byte *translation); void Draw_ConsoleBackground (int lines); void Draw_Fill (int x, int y, int w, int h, int c); void Draw_String (int x, int y, char *str, int maxlen); // LordHavoc: added maxlen +void Draw_AdditiveString (int x, int y, char *str, int maxlen); qpic_t *Draw_PicFromWad (char *name); qpic_t *Draw_CachePic (char *path); diff --git a/gl_draw.c b/gl_draw.c index 8e0b3dc6..bf3de8f9 100644 --- a/gl_draw.c +++ b/gl_draw.c @@ -154,7 +154,7 @@ void gl_draw_newmap(void) { } -char engineversion[40]; +extern char engineversion[40]; int engineversionx, engineversiony; extern void R_Textures_Init(); @@ -163,17 +163,10 @@ void GL_Draw_Init (void) int i; Cvar_RegisterVariable (&scr_conalpha); -#if defined(__linux__) - sprintf (engineversion, "DarkPlaces Linux GL %.2f build %3i", (float) VERSION, buildnumber); -#elif defined(WIN32) - sprintf (engineversion, "DarkPlaces Windows GL %.2f build %3i", (float) VERSION, buildnumber); -#else - sprintf (engineversion, "DarkPlaces Unknown GL %.2f build %3i", (float) VERSION, buildnumber); -#endif for (i = 0;i < 40 && engineversion[i];i++) engineversion[i] += 0x80; // shift to orange - engineversionx = vid.width - strlen(engineversion) * 8 - 8; - engineversiony = vid.height - 8; + engineversionx = vid.conwidth - strlen(engineversion) * 8 - 8; + engineversiony = vid.conheight - 8; R_Textures_Init(); R_RegisterModule("GL_Draw", gl_draw_start, gl_draw_shutdown, gl_draw_newmap); @@ -212,7 +205,7 @@ void Draw_Character (int x, int y, int num) return; glBindTexture(GL_TEXTURE_2D, R_GetTexture(char_texture)); // LordHavoc: NEAREST mode on text if not scaling up - if (glwidth <= (int) vid.width) + if (vid.realwidth <= (int) vid.conwidth) { glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); @@ -239,7 +232,7 @@ void Draw_Character (int x, int y, int num) glEnd (); // LordHavoc: revert to LINEAR mode -// if (glwidth < (int) vid.width) +// if (vid.realwidth <= (int) vid.conwidth) // { // glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); // glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); @@ -258,7 +251,7 @@ void Draw_String (int x, int y, char *str, int maxlen) float frow, fcol; if (!r_render.value) return; - if (y <= -8 || y >= (int) vid.height || x >= (int) vid.width || *str == 0) // completely offscreen or no text to print + if (y <= -8 || y >= (int) vid.conheight || x >= (int) vid.conwidth || *str == 0) // completely offscreen or no text to print return; if (maxlen < 1) maxlen = strlen(str); @@ -267,7 +260,7 @@ void Draw_String (int x, int y, char *str, int maxlen) glBindTexture(GL_TEXTURE_2D, R_GetTexture(char_texture)); // LordHavoc: NEAREST mode on text if not scaling up - if (glwidth <= (int) vid.width) + if (vid.realwidth <= (int) vid.conwidth) { glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); @@ -283,7 +276,7 @@ void Draw_String (int x, int y, char *str, int maxlen) else glColor3f(1.0f,1.0f,1.0f); glBegin (GL_QUADS); - while (maxlen-- && x < (int) vid.width) // stop rendering when out of characters or room + while (maxlen-- && x < (int) vid.conwidth) // stop rendering when out of characters or room { if ((num = *str++) != 32) // skip spaces { @@ -299,13 +292,22 @@ void Draw_String (int x, int y, char *str, int maxlen) glEnd (); // LordHavoc: revert to LINEAR mode -// if (glwidth < (int) vid.width) +// if (vid.realwidth < (int) vid.conwidth) // { // glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); // glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // } } +void Draw_AdditiveString (int x, int y, char *str, int maxlen) +{ + if (!r_render.value) + return; + glBlendFunc(GL_SRC_ALPHA, GL_ONE); + Draw_String(x, y, str, maxlen); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); +} + void Draw_GenericPic (rtexture_t *tex, float red, float green, float blue, float alpha, int x, int y, int width, int height) { if (!r_render.value) @@ -397,9 +399,9 @@ Draw_ConsoleBackground */ void Draw_ConsoleBackground (int lines) { - Draw_GenericPic (conbacktex, 1,1,1,scr_conalpha.value*lines/vid.height, 0, lines - vid.height, vid.width, vid.height); + Draw_GenericPic (conbacktex, 1,1,1,scr_conalpha.value * lines / vid.conheight, 0, lines - vid.conheight, vid.conwidth, vid.conheight); // LordHavoc: draw version - Draw_String(engineversionx, lines - vid.height + engineversiony, engineversion, 9999); + Draw_String(engineversionx, lines - vid.conheight + engineversiony, engineversion, 9999); } /* @@ -448,11 +450,11 @@ void GL_Set2D (void) { if (!r_render.value) return; - glViewport (glx, gly, glwidth, glheight); + glViewport (vid.realx, vid.realy, vid.realwidth, vid.realheight); glMatrixMode(GL_PROJECTION); glLoadIdentity (); - glOrtho (0, vid.width, vid.height, 0, -99999, 99999); + glOrtho (0, vid.conwidth, vid.conheight, 0, -99999, 99999); glMatrixMode(GL_MODELVIEW); glLoadIdentity (); @@ -503,7 +505,7 @@ void SHOWLMP_decodeshow(void) float x, y; strcpy(lmplabel,MSG_ReadString()); strcpy(picname, MSG_ReadString()); - if (nehahra) // LordHavoc: nasty old legacy junk + if (gamemode == GAME_NEHAHRA) // LordHavoc: nasty old legacy junk { x = MSG_ReadByte(); y = MSG_ReadByte(); diff --git a/gl_models.c b/gl_models.c index 035e5b09..1a18c951 100644 --- a/gl_models.c +++ b/gl_models.c @@ -266,7 +266,7 @@ void R_AliasLerpVerts(int vertcount, } } -void GL_DrawModelMesh(rtexture_t *skin, byte *colors, maliashdr_t *maliashdr) +void GL_DrawModelMesh(rtexture_t *skin, byte *colors, maliashdr_t *m) { if (!r_render.value) return; @@ -284,7 +284,7 @@ void GL_DrawModelMesh(rtexture_t *skin, byte *colors, maliashdr_t *maliashdr) glEnableClientState(GL_COLOR_ARRAY); } - glDrawElements(GL_TRIANGLES, maliashdr->numtris * 3, GL_UNSIGNED_SHORT, (void *)((int) maliashdr + maliashdr->tridata)); + glDrawElements(GL_TRIANGLES, m->numtris * 3, GL_UNSIGNED_SHORT, (void *)((int) m + m->tridata)); if (colors) glDisableClientState(GL_COLOR_ARRAY); @@ -317,51 +317,65 @@ R_DrawAliasFrame ================= */ -void R_LightModel(entity_t *ent, int numverts, vec3_t center, vec3_t basecolor); -void R_DrawAliasFrame (model_t *model, maliashdr_t *maliashdr, float alpha, vec3_t color, entity_t *ent, int shadow, vec3_t org, vec3_t angles, vec_t scale, frameblend_t *blend, rtexture_t **skin, int colormap, int effects, int flags) +void R_DrawAliasFrame (void) { + maliashdr_t *m = Mod_Extradata(currentrenderentity->model); +// int *skinanimrange = (int *) (currentrenderentity->model->skinanimrange + (int) modelheader) + skin * 2; +// int *skinanim = (int *) (currentrenderentity->model->skinanim + (int) modelheader); + int *skinanimrange = currentrenderentity->model->skinanimrange; + int skin; + rtexture_t **skinanim = currentrenderentity->model->skinanim; + rtexture_t **skinset; + + skinanimrange += currentrenderentity->skinnum * 2; + skin = skinanimrange[0]; + if (skinanimrange[1] > 1) // animated + skin += (int) (cl.time * 10) % skinanimrange[1]; + skinset = skinanim + skin * 5; + if (gl_transform.value) { if (r_render.value) { glPushMatrix(); - GL_SetupModelTransform(org, angles, scale); + GL_SetupModelTransform(currentrenderentity->origin, currentrenderentity->angles, currentrenderentity->scale); } } // always needed, for model lighting - softwaretransformforentity(ent); + softwaretransformforentity(currentrenderentity); + + R_AliasLerpVerts(m->numverts, + currentrenderentity->frameblend[0].lerp, ((trivertx_t *)((int) m + m->posedata)) + currentrenderentity->frameblend[0].frame * m->numverts, m->scale, m->scale_origin, + currentrenderentity->frameblend[1].lerp, ((trivertx_t *)((int) m + m->posedata)) + currentrenderentity->frameblend[1].frame * m->numverts, m->scale, m->scale_origin, + currentrenderentity->frameblend[2].lerp, ((trivertx_t *)((int) m + m->posedata)) + currentrenderentity->frameblend[2].frame * m->numverts, m->scale, m->scale_origin, + currentrenderentity->frameblend[3].lerp, ((trivertx_t *)((int) m + m->posedata)) + currentrenderentity->frameblend[3].frame * m->numverts, m->scale, m->scale_origin); - R_AliasLerpVerts(maliashdr->numverts, - blend[0].lerp, ((trivertx_t *)((int) maliashdr + maliashdr->posedata)) + blend[0].frame * maliashdr->numverts, maliashdr->scale, maliashdr->scale_origin, - blend[1].lerp, ((trivertx_t *)((int) maliashdr + maliashdr->posedata)) + blend[1].frame * maliashdr->numverts, maliashdr->scale, maliashdr->scale_origin, - blend[2].lerp, ((trivertx_t *)((int) maliashdr + maliashdr->posedata)) + blend[2].frame * maliashdr->numverts, maliashdr->scale, maliashdr->scale_origin, - blend[3].lerp, ((trivertx_t *)((int) maliashdr + maliashdr->posedata)) + blend[3].frame * maliashdr->numverts, maliashdr->scale, maliashdr->scale_origin); if (!gl_transform.value) - R_AliasTransformVerts(maliashdr->numverts); + R_AliasTransformVerts(m->numverts); // prep the vertex array as early as possible if (r_render.value) { glVertexPointer(3, GL_FLOAT, sizeof(float[3]), aliasvert); glEnableClientState(GL_VERTEX_ARRAY); - glTexCoordPointer(2, GL_FLOAT, sizeof(float[2]), (void *)((int) maliashdr->texdata + (int) maliashdr)); + glTexCoordPointer(2, GL_FLOAT, sizeof(float[2]), (void *)((int) m->texdata + (int) m)); glEnableClientState(GL_TEXTURE_COORD_ARRAY); - GL_LockArray(0, maliashdr->numverts); + GL_LockArray(0, m->numverts); } - R_LightModel(ent, maliashdr->numverts, org, color); + R_LightModel(m->numverts); if (!r_render.value) return; glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - glShadeModel(GL_SMOOTH); - if (effects & EF_ADDITIVE) +// glShadeModel(GL_SMOOTH); + if (currentrenderentity->effects & EF_ADDITIVE) { glBlendFunc(GL_SRC_ALPHA, GL_ONE); // additive rendering glEnable(GL_BLEND); glDepthMask(0); } - else if (alpha != 1.0 || (model->flags2 & MODF_TRANSPARENT)) + else if (currentrenderentity->alpha != 1.0 || (currentrenderentity->model->flags2 & MODF_TRANSPARENT)) { glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); @@ -373,40 +387,41 @@ void R_DrawAliasFrame (model_t *model, maliashdr_t *maliashdr, float alpha, vec3 glDepthMask(1); } - if (skin[0] || skin[1] || skin[2] || skin[3] || skin[4]) + if (skinset[0] || skinset[1] || skinset[2] || skinset[3] || skinset[4]) { - if (colormap >= 0 && (skin[0] || skin[1] || skin[2])) + if (currentrenderentity->colormap >= 0 && (skinset[0] || skinset[1] || skinset[2])) { int c; - if (skin[0]) - GL_DrawModelMesh(skin[0], aliasvertcolor, maliashdr); - if (skin[1]) + if (skinset[0]) + GL_DrawModelMesh(skinset[0], aliasvertcolor, m); + if (skinset[1]) { - c = (colormap & 0xF) << 4;c += (c >= 128 && c < 224) ? 4 : 12; // 128-224 are backwards ranges - R_TintModel(aliasvertcolor, aliasvertcolor2, maliashdr->numverts, (byte *) (&d_8to24table[c])); - GL_DrawModelMesh(skin[1], aliasvertcolor2, maliashdr); + c = (currentrenderentity->colormap & 0xF) << 4;c += (c >= 128 && c < 224) ? 4 : 12; // 128-224 are backwards ranges + R_TintModel(aliasvertcolor, aliasvertcolor2, m->numverts, (byte *) (&d_8to24table[c])); + GL_DrawModelMesh(skinset[1], aliasvertcolor2, m); } - if (skin[2]) + if (skinset[2]) { - c = colormap & 0xF0 ;c += (c >= 128 && c < 224) ? 4 : 12; // 128-224 are backwards ranges - R_TintModel(aliasvertcolor, aliasvertcolor2, maliashdr->numverts, (byte *) (&d_8to24table[c])); - GL_DrawModelMesh(skin[2], aliasvertcolor2, maliashdr); + c = currentrenderentity->colormap & 0xF0 ;c += (c >= 128 && c < 224) ? 4 : 12; // 128-224 are backwards ranges + R_TintModel(aliasvertcolor, aliasvertcolor2, m->numverts, (byte *) (&d_8to24table[c])); + GL_DrawModelMesh(skinset[2], aliasvertcolor2, m); } } else { - if (skin[4]) GL_DrawModelMesh(skin[4], aliasvertcolor, maliashdr); + if (skinset[4]) + GL_DrawModelMesh(skinset[4], aliasvertcolor, m); else { - if (skin[0]) GL_DrawModelMesh(skin[0], aliasvertcolor, maliashdr); - if (skin[1]) GL_DrawModelMesh(skin[1], aliasvertcolor, maliashdr); - if (skin[2]) GL_DrawModelMesh(skin[2], aliasvertcolor, maliashdr); + if (skinset[0]) GL_DrawModelMesh(skinset[0], aliasvertcolor, m); + if (skinset[1]) GL_DrawModelMesh(skinset[1], aliasvertcolor, m); + if (skinset[2]) GL_DrawModelMesh(skinset[2], aliasvertcolor, m); } } - if (skin[3]) GL_DrawModelMesh(skin[3], NULL, maliashdr); + if (skinset[3]) GL_DrawModelMesh(skinset[3], NULL, m); } else - GL_DrawModelMesh(0, NULL, maliashdr); + GL_DrawModelMesh(0, NULL, m); if (fogenabled) { @@ -416,14 +431,15 @@ void R_DrawAliasFrame (model_t *model, maliashdr_t *maliashdr, float alpha, vec3 glEnable (GL_BLEND); glDepthMask(0); // disable zbuffer updates - VectorSubtract(org, r_origin, diff); + VectorSubtract(currentrenderentity->origin, r_origin, diff); glColor4f(fogcolor[0], fogcolor[1], fogcolor[2], exp(fogdensity/DotProduct(diff,diff))); - glDrawElements(GL_TRIANGLES, maliashdr->numtris * 3, GL_UNSIGNED_SHORT, (void *)((int) maliashdr + maliashdr->tridata)); + glDrawElements(GL_TRIANGLES, m->numtris * 3, GL_UNSIGNED_SHORT, (void *)((int) m + m->tridata)); glEnable (GL_TEXTURE_2D); glColor3f (1,1,1); } + GL_UnlockArray(); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisableClientState(GL_VERTEX_ARRAY); @@ -441,41 +457,74 @@ R_DrawQ2AliasFrame ================= */ -void R_DrawQ2AliasFrame (model_t *model, md2mem_t *pheader, float alpha, vec3_t color, entity_t *ent, int shadow, vec3_t org, vec3_t angles, vec_t scale, frameblend_t *blend, rtexture_t *skin, int effects, int flags) +void R_DrawQ2AliasFrame (void) { int *order, count; md2frame_t *frame1, *frame2, *frame3, *frame4; + vec3_t diff; + md2mem_t *m = Mod_Extradata(currentrenderentity->model); +// int *skinanimrange = (int *) (currentrenderentity->model->skinanimrange + (int) modelheader) + skin * 2; +// int *skinanim = (int *) (currentrenderentity->model->skinanim + (int) modelheader); + int *skinanimrange = currentrenderentity->model->skinanimrange; + int skin; + rtexture_t **skinanim = currentrenderentity->model->skinanim; + rtexture_t **skinset; + + skinanimrange += currentrenderentity->skinnum * 2; + skin = skinanimrange[0]; + if (skinanimrange[1] > 1) // animated + skin += (int) (cl.time * 10) % skinanimrange[1]; + skinset = skinanim + skin * 5; if (r_render.value) - glBindTexture(GL_TEXTURE_2D, R_GetTexture(skin)); + glBindTexture(GL_TEXTURE_2D, R_GetTexture(skinset[0])); if (gl_transform.value) { if (r_render.value) { glPushMatrix(); - GL_SetupModelTransform(org, angles, scale); + GL_SetupModelTransform(currentrenderentity->origin, currentrenderentity->angles, currentrenderentity->scale); } } // always needed, for model lighting - softwaretransformforentity(ent); - - frame1 = (void *)((int) pheader + pheader->ofs_frames + (pheader->framesize * blend[0].frame)); - frame2 = (void *)((int) pheader + pheader->ofs_frames + (pheader->framesize * blend[1].frame)); - frame3 = (void *)((int) pheader + pheader->ofs_frames + (pheader->framesize * blend[2].frame)); - frame4 = (void *)((int) pheader + pheader->ofs_frames + (pheader->framesize * blend[3].frame)); - R_AliasLerpVerts(pheader->num_xyz, - blend[0].lerp, frame1->verts, frame1->scale, frame1->translate, - blend[1].lerp, frame2->verts, frame2->scale, frame2->translate, - blend[2].lerp, frame3->verts, frame3->scale, frame3->translate, - blend[3].lerp, frame4->verts, frame4->scale, frame4->translate); + softwaretransformforentity(currentrenderentity); + + frame1 = (void *)((int) m + m->ofs_frames + (m->framesize * currentrenderentity->frameblend[0].frame)); + frame2 = (void *)((int) m + m->ofs_frames + (m->framesize * currentrenderentity->frameblend[1].frame)); + frame3 = (void *)((int) m + m->ofs_frames + (m->framesize * currentrenderentity->frameblend[2].frame)); + frame4 = (void *)((int) m + m->ofs_frames + (m->framesize * currentrenderentity->frameblend[3].frame)); + R_AliasLerpVerts(m->num_xyz, + currentrenderentity->frameblend[0].lerp, frame1->verts, frame1->scale, frame1->translate, + currentrenderentity->frameblend[1].lerp, frame2->verts, frame2->scale, frame2->translate, + currentrenderentity->frameblend[2].lerp, frame3->verts, frame3->scale, frame3->translate, + currentrenderentity->frameblend[3].lerp, frame4->verts, frame4->scale, frame4->translate); if (!gl_transform.value) - R_AliasTransformVerts(pheader->num_xyz); + R_AliasTransformVerts(m->num_xyz); - R_LightModel(ent, pheader->num_xyz, org, color); + R_LightModel(m->num_xyz); if (!r_render.value) return; + + if (currentrenderentity->effects & EF_ADDITIVE) + { + glBlendFunc(GL_SRC_ALPHA, GL_ONE); // additive rendering + glEnable(GL_BLEND); + glDepthMask(0); + } + else if (currentrenderentity->alpha != 1.0 || (currentrenderentity->model->flags2 & MODF_TRANSPARENT)) + { + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_BLEND); + glDepthMask(0); + } + else + { + glDisable(GL_BLEND); + glDepthMask(1); + } + // LordHavoc: big mess... // using vertex arrays only slightly, although it is enough to prevent duplicates // (saving half the transforms) @@ -484,7 +533,7 @@ void R_DrawQ2AliasFrame (model_t *model, md2mem_t *pheader, float alpha, vec3_t glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_COLOR_ARRAY); - order = (int *)((int)pheader + pheader->ofs_glcmds); + order = (int *)((int)m + m->ofs_glcmds); while(1) { if (!(count = *order++)) @@ -514,11 +563,9 @@ void R_DrawQ2AliasFrame (model_t *model, md2mem_t *pheader, float alpha, vec3_t glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable (GL_BLEND); glDepthMask(0); // disable zbuffer updates - { - vec3_t diff; - VectorSubtract(org, r_origin, diff); - glColor4f(fogcolor[0], fogcolor[1], fogcolor[2], exp(fogdensity/DotProduct(diff,diff))); - } + + VectorSubtract(currentrenderentity->origin, r_origin, diff); + glColor4f(fogcolor[0], fogcolor[1], fogcolor[2], exp(fogdensity/DotProduct(diff,diff))); // LordHavoc: big mess... // using vertex arrays only slightly, although it is enough to prevent duplicates @@ -526,7 +573,7 @@ void R_DrawQ2AliasFrame (model_t *model, md2mem_t *pheader, float alpha, vec3_t glVertexPointer(3, GL_FLOAT, sizeof(float[3]), aliasvert); glEnableClientState(GL_VERTEX_ARRAY); - order = (int *)((int)pheader + pheader->ofs_glcmds); + order = (int *)((int)m + m->ofs_glcmds); while(1) { if (!(count = *order++)) @@ -880,25 +927,26 @@ void GL_DrawZymoticModelMeshFog(vec3_t org, zymtype1header_t *m) R_DrawZymoticFrame ================= */ -void R_DrawZymoticFrame (model_t *model, zymtype1header_t *m, float alpha, vec3_t color, entity_t *ent, int shadow, vec3_t org, vec3_t angles, vec_t scale, frameblend_t *blend, int skinblah, int effects, int flags) +void R_DrawZymoticFrame (void) { - ZymoticLerpBones(m->numbones, (zymbonematrix *)(m->lump_poses.start + (int) m), blend, (zymbone_t *)(m->lump_bones.start + (int) m), org, angles, scale); + zymtype1header_t *m = Mod_Extradata(currentrenderentity->model); + ZymoticLerpBones(m->numbones, (zymbonematrix *)(m->lump_poses.start + (int) m), currentrenderentity->frameblend, (zymbone_t *)(m->lump_bones.start + (int) m), currentrenderentity->origin, currentrenderentity->angles, currentrenderentity->scale); ZymoticTransformVerts(m->numverts, (int *)(m->lump_vertbonecounts.start + (int) m), (zymvertex_t *)(m->lump_verts.start + (int) m)); ZymoticCalcNormals(m->numverts, m->numshaders, (int *)(m->lump_render.start + (int) m)); - R_LightModel(ent, m->numverts, org, color); + R_LightModel(m->numverts); if (!r_render.value) return; glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - glShadeModel(GL_SMOOTH); - if (effects & EF_ADDITIVE) +// glShadeModel(GL_SMOOTH); + if (currentrenderentity->effects & EF_ADDITIVE) { glBlendFunc(GL_SRC_ALPHA, GL_ONE); // additive rendering glEnable(GL_BLEND); glDepthMask(0); } - else if (alpha != 1.0) + else if (currentrenderentity->alpha != 1.0) { glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); @@ -913,7 +961,7 @@ void R_DrawZymoticFrame (model_t *model, zymtype1header_t *m, float alpha, vec3_ GL_DrawZymoticModelMesh(aliasvertcolor, m); if (fogenabled) - GL_DrawZymoticModelMeshFog(org, m); + GL_DrawZymoticModelMeshFog(currentrenderentity->origin, m); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable (GL_BLEND); @@ -926,51 +974,21 @@ R_DrawAliasModel ================= */ -void R_DrawAliasModel (entity_t *ent, int cull, float alpha, model_t *clmodel, frameblend_t *blend, int skin, vec3_t org, vec3_t angles, vec_t scale, int effects, int flags, int colormap) +void R_DrawAliasModel (void) { - int i; - vec3_t mins, maxs, color; - void *modelheader; - rtexture_t **skinset; - - if (alpha < (1.0 / 64.0)) + if (currentrenderentity->alpha < (1.0 / 64.0)) return; // basically completely transparent - VectorAdd (org, clmodel->mins, mins); - VectorAdd (org, clmodel->maxs, maxs); - -// if (cull && R_CullBox (mins, maxs)) -// return; - c_models++; - if (skin < 0 || skin >= clmodel->numskins) - { - skin = 0; - Con_DPrintf("invalid skin number %d for model %s\n", skin, clmodel->name); - } - - modelheader = Mod_Extradata (clmodel); - - { -// int *skinanimrange = (int *) (clmodel->skinanimrange + (int) modelheader) + skin * 2; -// int *skinanim = (int *) (clmodel->skinanim + (int) modelheader); - int *skinanimrange = clmodel->skinanimrange + skin * 2; - rtexture_t **skinanim = clmodel->skinanim; - i = skinanimrange[0]; - if (skinanimrange[1] > 1) // animated - i += ((int) (cl.time * 10) % skinanimrange[1]); - skinset = skinanim + i*5; - } - if (r_render.value) glEnable (GL_TEXTURE_2D); - c_alias_polys += clmodel->numtris; - if (clmodel->aliastype == ALIASTYPE_ZYM) - R_DrawZymoticFrame (clmodel, modelheader, alpha, color, ent, ent != &cl.viewent, org, angles, scale, blend, 0 , effects, flags); - else if (clmodel->aliastype == ALIASTYPE_MD2) - R_DrawQ2AliasFrame (clmodel, modelheader, alpha, color, ent, ent != &cl.viewent, org, angles, scale, blend, skinset[0] , effects, flags); + c_alias_polys += currentrenderentity->model->numtris; + if (currentrenderentity->model->aliastype == ALIASTYPE_ZYM) + R_DrawZymoticFrame (); + else if (currentrenderentity->model->aliastype == ALIASTYPE_MD2) + R_DrawQ2AliasFrame (); else - R_DrawAliasFrame (clmodel, modelheader, alpha, color, ent, ent != &cl.viewent, org, angles, scale, blend, skinset , colormap, effects, flags); + R_DrawAliasFrame (); } diff --git a/gl_poly.c b/gl_poly.c index 0f35ab85..8750595a 100644 --- a/gl_poly.c +++ b/gl_poly.c @@ -1,8 +1,18 @@ #include "quakedef.h" +typedef struct +{ + unsigned short tex; + unsigned short type; + int indices; +} +rendertranspoly_t; + transvert_t *transvert; transpoly_t *transpoly; -unsigned short *transpolyindex; +rendertranspoly_t *rendertranspoly; +int *transpolyindex; +int *transvertindex; wallvert_t *wallvert; wallvertcolor_t *wallvertcolor; wallpoly_t *wallpoly; @@ -16,11 +26,13 @@ int currentwallvert; int currentskypoly; int currentskyvert; + void LoadSky_f(void); cvar_t r_multitexture = {0, "r_multitexture", "1"}; cvar_t r_skyquality = {CVAR_SAVE, "r_skyquality", "2"}; cvar_t r_mergesky = {CVAR_SAVE, "r_mergesky", "0"}; +cvar_t gl_transpolytris = {0, "gl_transpolytris", "0"}; static char skyworldname[1024]; static rtexture_t *mergeskytexture; @@ -29,7 +41,7 @@ static rtexture_t *alphaskytexture, *alphaskytexture_half; static qboolean skyavailable_quake; static qboolean skyavailable_box; -void R_BuildSky (int scrollupper, int scrolllower); +static void R_BuildSky (int scrollupper, int scrolllower); typedef struct translistitem_s { @@ -47,12 +59,14 @@ float transviewdist; // distance of view origin along the view normal float transreciptable[256]; -void gl_poly_start(void) +static void gl_poly_start(void) { int i; transvert = qmalloc(MAX_TRANSVERTS * sizeof(transvert_t)); transpoly = qmalloc(MAX_TRANSPOLYS * sizeof(transpoly_t)); - transpolyindex = qmalloc(MAX_TRANSPOLYS * sizeof(unsigned short)); + rendertranspoly = qmalloc(MAX_TRANSPOLYS * sizeof(rendertranspoly_t)); + transpolyindex = qmalloc(MAX_TRANSPOLYS * sizeof(int)); + transvertindex = qmalloc(MAX_TRANSVERTS * sizeof(int)); wallvert = qmalloc(MAX_WALLVERTS * sizeof(wallvert_t)); wallvertcolor = qmalloc(MAX_WALLVERTS * sizeof(wallvertcolor_t)); wallpoly = qmalloc(MAX_WALLPOLYS * sizeof(wallpoly_t)); @@ -63,11 +77,13 @@ void gl_poly_start(void) transreciptable[i] = 1.0f / i; } -void gl_poly_shutdown(void) +static void gl_poly_shutdown(void) { qfree(transvert); qfree(transpoly); + qfree(rendertranspoly); qfree(transpolyindex); + qfree(transvertindex); qfree(wallvert); qfree(wallvertcolor); qfree(wallpoly); @@ -75,7 +91,7 @@ void gl_poly_shutdown(void) qfree(skypoly); } -void gl_poly_newmap(void) +static void gl_poly_newmap(void) { skyavailable_box = false; skyavailable_quake = false; @@ -89,6 +105,7 @@ void GL_Poly_Init(void) Cvar_RegisterVariable (&r_multitexture); Cvar_RegisterVariable (&r_skyquality); Cvar_RegisterVariable (&r_mergesky); + Cvar_RegisterVariable (&gl_transpolytris); R_RegisterModule("GL_Poly", gl_poly_start, gl_poly_shutdown, gl_poly_newmap); } @@ -100,42 +117,7 @@ void transpolyclear(void) transviewdist = DotProduct(r_origin, vpn); } -// turned into a #define -/* -void transpolybegin(int texnum, int glowtexnum, int fogtexnum, int transpolytype) -{ - if (currenttranspoly >= MAX_TRANSPOLYS || currenttransvert >= MAX_TRANSVERTS) - return; - transpoly[currenttranspoly].texnum = (unsigned short) texnum; - transpoly[currenttranspoly].glowtexnum = (unsigned short) glowtexnum; - transpoly[currenttranspoly].fogtexnum = (unsigned short) fogtexnum; - transpoly[currenttranspoly].transpolytype = (unsigned short) transpolytype; - transpoly[currenttranspoly].firstvert = currenttransvert; - transpoly[currenttranspoly].verts = 0; -// transpoly[currenttranspoly].ndist = 0; // clear the normal -} -*/ - -// turned into a #define -/* -void transpolyvert(float x, float y, float z, float s, float t, int r, int g, int b, int a) -{ - int i; - if (currenttranspoly >= MAX_TRANSPOLYS || currenttransvert >= MAX_TRANSVERTS) - return; - transvert[currenttransvert].s = s; - transvert[currenttransvert].t = t; - transvert[currenttransvert].r = bound(0, r, 255); - transvert[currenttransvert].g = bound(0, g, 255); - transvert[currenttransvert].b = bound(0, b, 255); - transvert[currenttransvert].a = bound(0, a, 255); - transvert[currenttransvert].v[0] = x; - transvert[currenttransvert].v[1] = y; - transvert[currenttransvert].v[2] = z; - currenttransvert++; - transpoly[currenttranspoly].verts++; -} -*/ +// transpolybegin and transpolyvert are #define macros void transpolyend(void) { @@ -174,207 +156,367 @@ void transpolyend(void) currenttranspoly++; } -int transpolyindices; +void transpolyparticle(vec3_t org, vec3_t right, vec3_t up, vec_t scale, unsigned short texnum, unsigned short transpolytype, int ir, int ig, int ib, float alphaf, float s1, float t1, float s2, float t2) +{ + float center, scale2; + int i; + vec3_t corner; + byte br, bg, bb, ba; + transpoly_t *p; + transvert_t *v; + center = DotProduct(org, vpn) - transviewdist; + if (center < 4.0f || currenttranspoly >= MAX_TRANSPOLYS || (currenttransvert + 4) > MAX_TRANSVERTS) + return; + + p = transpoly + (currenttranspoly++); + v = transvert + currenttransvert; + + if (lighthalf) + { + ir >>= 1; + ig >>= 1; + ib >>= 1; + } + ir = bound(0, ir, 255); + ig = bound(0, ig, 255); + ib = bound(0, ib, 255); + br = (byte) ir; + bg = (byte) ig; + bb = (byte) ib; + +#if SLOWMATH + i = (int) alphaf; + if (i > 255) + i = 255; + ba = (byte) i; + + i = (int) center; +#else + alphaf += 8388608.0f; + i = *((long *)&alphaf) & 0x007FFFFF; + if (i > 255) + i = 255; + ba = (byte) i; + + center += 8388608.0f; + i = *((long *)¢er) & 0x007FFFFF; +#endif + i = bound(0, i, 4095); + currenttranslist->next = translisthash[i]; + currenttranslist->poly = p; + translisthash[i] = currenttranslist++; + + p->texnum = p->fogtexnum = texnum; + p->glowtexnum = 0; + p->transpolytype = transpolytype; + p->firstvert = currenttransvert; + p->verts = 4; + currenttransvert += 4; + + scale2 = scale * -0.5f; + corner[0] = org[0] + (up[0] + right[0]) * scale2; + corner[1] = org[1] + (up[1] + right[1]) * scale2; + corner[2] = org[2] + (up[2] + right[2]) * scale2; + v->s = s1; + v->t = t1; + v->r = br; + v->g = bg; + v->b = bb; + v->a = ba; + v->v[0] = corner[0]; + v->v[1] = corner[1]; + v->v[2] = corner[2]; + v++; + v->s = s1; + v->t = t2; + v->r = br; + v->g = bg; + v->b = bb; + v->a = ba; + v->v[0] = corner[0] + up[0] * scale; + v->v[1] = corner[1] + up[1] * scale; + v->v[2] = corner[2] + up[2] * scale; + v++; + v->s = s2; + v->t = t2; + v->r = br; + v->g = bg; + v->b = bb; + v->a = ba; + v->v[0] = corner[0] + (up[0] + right[0]) * scale; + v->v[1] = corner[1] + (up[1] + right[1]) * scale; + v->v[2] = corner[2] + (up[2] + right[2]) * scale; + v++; + v->s = s2; + v->t = t1; + v->r = br; + v->g = bg; + v->b = bb; + v->a = ba; + v->v[0] = corner[0] + right[0] * scale; + v->v[1] = corner[1] + right[1] * scale; + v->v[2] = corner[2] + right[2] * scale; + v++; +} void transpolyrender(void) { - int i, j, tpolytype, texnum; - transpoly_t *p; + int i, j, k, l, tpolytype, texnum, transvertindices, alpha, currentrendertranspoly; + byte fogr, fogg, fogb; + vec3_t diff; + transpoly_t *p; + rendertranspoly_t *r, *rend; + translistitem *item; + if (!r_render.value) return; if (currenttranspoly < 1) return; -// transpolyrenderminmax(); -// if (transpolyindices < 1) -// return; - // testing -// Con_DPrintf("transpolyrender: %i polys %i infront %i vertices\n", currenttranspoly, transpolyindices, currenttransvert); -// if (transpolyindices >= 2) -// transpolysort(); + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glEnable(GL_BLEND); - glShadeModel(GL_SMOOTH); +// glShadeModel(GL_SMOOTH); glDepthMask(0); // disable zbuffer updates - glDisable(GL_ALPHA_TEST); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - tpolytype = TPOLYTYPE_ALPHA; - texnum = -1; - /* - if (gl_vertexarrays.value) + + // set up the vertex array + glInterleavedArrays(GL_T2F_C4UB_V3F, sizeof(transvert[0]), transvert); + + currentrendertranspoly = 0; + transvertindices = 0; + fogr = (byte) bound(0, (int) (fogcolor[0] * 255.0f), 255); + fogg = (byte) bound(0, (int) (fogcolor[1] * 255.0f), 255); + fogb = (byte) bound(0, (int) (fogcolor[2] * 255.0f), 255); + if (gl_transpolytris.value) { - // set up the vertex array - glInterleavedArrays(GL_T2F_C4UB_V3F, 0, transvert); - for (i = 0;i < transpolyindices;i++) + int glowtexnum, fogtexnum; + for (i = 4095;i >= 0;i--) { - p = &transpoly[transpolyindex[i]]; - if (p->texnum != texnum || p->transpolytype != tpolytype) + item = translisthash[i]; + while(item) { - if (p->texnum != texnum) + p = item->poly; + item = item->next; + glowtexnum = p->glowtexnum; + fogtexnum = p->fogtexnum; + +#define POLYTOTRI(pfirstvert, ptexnum, ptranspolytype) \ + l = pfirstvert;\ + r = &rendertranspoly[currentrendertranspoly++];\ + r->tex = ptexnum;\ + r->type = ptranspolytype;\ + if (p->verts == 4)\ + {\ + transvertindex[transvertindices] = l;\ + transvertindex[transvertindices + 1] = l + 1;\ + transvertindex[transvertindices + 2] = l + 2;\ + transvertindex[transvertindices + 3] = l;\ + transvertindex[transvertindices + 4] = l + 2;\ + transvertindex[transvertindices + 5] = l + 3;\ + transvertindices += 6;\ + r->indices = 6;\ + }\ + else if (p->verts == 3)\ + {\ + transvertindex[transvertindices] = l;\ + transvertindex[transvertindices + 1] = l + 1;\ + transvertindex[transvertindices + 2] = l + 2;\ + transvertindices += 3;\ + r->indices = 3;\ + }\ + else\ + {\ + for (j = l + p->verts, k = l + 2;k < j;k++)\ + {\ + transvertindex[transvertindices] = l;\ + transvertindex[transvertindices + 1] = k - 1;\ + transvertindex[transvertindices + 2] = k;\ + transvertindices += 3;\ + }\ + r->indices = (p->verts - 2) * 3;\ + } + + POLYTOTRI(p->firstvert, p->texnum, p->transpolytype) + + if (p->glowtexnum) { - texnum = p->texnum; - glBindTexture(GL_TEXTURE_2D, texnum); + // make another poly for glow effect + if (currenttranspoly < MAX_TRANSPOLYS && currenttransvert + p->verts <= MAX_TRANSVERTS) + { + memcpy(&transvert[currenttransvert], &transvert[p->firstvert], sizeof(transvert_t) * p->verts); + POLYTOTRI(currenttransvert, p->glowtexnum, TPOLYTYPE_ADD) + for (j = 0;j < p->verts;j++) + { + transvert[currenttransvert].r = transvert[currenttransvert].g = transvert[currenttransvert].b = 255; + currenttransvert++; + } + } } - if (p->transpolytype != tpolytype) + + if (fogenabled) { - tpolytype = p->transpolytype; - if (tpolytype == TPOLYTYPE_ADD) // additive - glBlendFunc(GL_SRC_ALPHA, GL_ONE); - else // alpha - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + // make another poly for fog + if (currenttranspoly < MAX_TRANSPOLYS && currenttransvert + p->verts <= MAX_TRANSVERTS) + { + memcpy(&transvert[currenttransvert], &transvert[p->firstvert], sizeof(transvert_t) * p->verts); + POLYTOTRI(currenttransvert, p->fogtexnum, TPOLYTYPE_ALPHA) + for (j = 0, k = p->firstvert;j < p->verts;j++, k++) + { + transvert[currenttransvert].r = fogr; + transvert[currenttransvert].g = fogg; + transvert[currenttransvert].b = fogb; + VectorSubtract(transvert[currenttransvert].v, r_origin, diff); + alpha = transvert[currenttransvert].a * exp(fogdensity / DotProduct(diff, diff)); + transvert[currenttransvert].a = (byte) bound(0, alpha, 255); + currenttransvert++; + } + } } } - glDrawArrays(GL_POLYGON, p->firstvert, p->verts); - if (p->glowtexnum) - { - texnum = p->glowtexnum; // highly unlikely to match next poly, but... - glBindTexture(GL_TEXTURE_2D, texnum); - tpolytype = TPOLYTYPE_ADD; // might match next poly - glBlendFunc(GL_SRC_ALPHA, GL_ONE); - glDrawArrays(GL_POLYGON, p->firstvert, p->verts); - } } - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - glDisableClientState(GL_COLOR_ARRAY); - glDisableClientState(GL_VERTEX_ARRAY); } else - */ { - int points = -1; - translistitem *item; - transvert_t *vert; for (i = 4095;i >= 0;i--) { item = translisthash[i]; - while (item) + while(item) { p = item->poly; item = item->next; - if (p->texnum != texnum || p->verts != points || p->transpolytype != tpolytype) - { - glEnd(); - if (isG200) - { - // LordHavoc: Matrox G200 cards can't handle per pixel alpha - if (p->fogtexnum) - glEnable(GL_ALPHA_TEST); - else - glDisable(GL_ALPHA_TEST); - } - if (p->texnum != texnum) - { - texnum = p->texnum; - glBindTexture(GL_TEXTURE_2D, texnum); - } - if (p->transpolytype != tpolytype) - { - tpolytype = p->transpolytype; - if (tpolytype == TPOLYTYPE_ADD) // additive - glBlendFunc(GL_SRC_ALPHA, GL_ONE); - else // alpha - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - } - points = p->verts; - switch (points) - { - case 3: - glBegin(GL_TRIANGLES); - break; - case 4: - glBegin(GL_QUADS); - break; - default: - glBegin(GL_POLYGON); - points = -1; // to force a reinit on the next poly - break; - } - } - for (j = 0,vert = &transvert[p->firstvert];j < p->verts;j++, vert++) - { - // would be 2fv, but windoze Matrox G200 and probably G400 drivers don't support that (dumb...) - glTexCoord2f(vert->s, vert->t); - // again, vector version isn't supported I think - glColor4ub(vert->r, vert->g, vert->b, vert->a); - glVertex3fv(vert->v); - } + + l = p->firstvert; + r = &rendertranspoly[currentrendertranspoly++]; + r->tex = p->texnum; + r->type = p->transpolytype; + r->indices = p->verts; + + for (j = l + p->verts, k = l;k < j;k++) + transvertindex[transvertindices++] = k; + if (p->glowtexnum) { - glEnd(); - texnum = p->glowtexnum; // highly unlikely to match next poly, but... - glBindTexture(GL_TEXTURE_2D, texnum); - if (tpolytype != TPOLYTYPE_ADD) - { - tpolytype = TPOLYTYPE_ADD; // might match next poly - glBlendFunc(GL_SRC_ALPHA, GL_ONE); - } - points = -1; - glBegin(GL_POLYGON); - for (j = 0,vert = &transvert[p->firstvert];j < p->verts;j++, vert++) - { - glColor4ub(255,255,255,vert->a); - // would be 2fv, but windoze Matrox G200 and probably G400 drivers don't support that (dumb...) - glTexCoord2f(vert->s, vert->t); - glVertex3fv(vert->v); - } - glEnd(); - } - if (fogenabled && p->transpolytype == TPOLYTYPE_ALPHA) - { - vec3_t diff; - glEnd(); - points = -1; // to force a reinit on the next poly - if (tpolytype != TPOLYTYPE_ALPHA) + // make another poly for glow effect + if (currentrendertranspoly < MAX_TRANSPOLYS && currenttransvert + p->verts <= MAX_TRANSVERTS) { - tpolytype = TPOLYTYPE_ALPHA; // probably matchs next poly - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - } - if (p->fogtexnum) - { - if (texnum != p->fogtexnum) // highly unlikely to match next poly, but... - { - texnum = p->fogtexnum; - glBindTexture(GL_TEXTURE_2D, texnum); - } - glBegin(GL_POLYGON); - for (j = 0,vert = &transvert[p->firstvert];j < p->verts;j++, vert++) + l = currenttransvert; + r = &rendertranspoly[currentrendertranspoly++]; + r->tex = p->glowtexnum; + r->type = TPOLYTYPE_ADD; + r->indices = p->verts; + + memcpy(&transvert[currenttransvert], &transvert[p->firstvert], sizeof(transvert_t) * p->verts); + for (j = 0;j < p->verts;j++) { - VectorSubtract(vert->v, r_origin, diff); - glTexCoord2f(vert->s, vert->t); - glColor4f(fogcolor[0], fogcolor[1], fogcolor[2], vert->a*(1.0f/255.0f)*exp(fogdensity/DotProduct(diff,diff))); - glVertex3fv(vert->v); + transvert[currenttransvert].r = transvert[currenttransvert].g = transvert[currenttransvert].b = 255; + transvertindex[transvertindices++] = currenttransvert++; } - glEnd (); } - else + } + if (fogenabled) + { + // make another poly for fog + if (currentrendertranspoly < MAX_TRANSPOLYS && currenttransvert + p->verts <= MAX_TRANSVERTS) { - glDisable(GL_TEXTURE_2D); - glBegin(GL_POLYGON); - for (j = 0,vert = &transvert[p->firstvert];j < p->verts;j++, vert++) + l = currenttransvert; + r = &rendertranspoly[currentrendertranspoly++]; + r->tex = p->fogtexnum; + r->type = TPOLYTYPE_ALPHA; + r->indices = p->verts; + + memcpy(&transvert[currenttransvert], &transvert[p->firstvert], sizeof(transvert_t) * p->verts); + for (j = 0;j < p->verts;j++) { - VectorSubtract(vert->v, r_origin, diff); - glColor4f(fogcolor[0], fogcolor[1], fogcolor[2], vert->a*(1.0f/255.0f)*exp(fogdensity/DotProduct(diff,diff))); - glVertex3fv(vert->v); + transvert[currenttransvert].r = fogr; + transvert[currenttransvert].g = fogg; + transvert[currenttransvert].b = fogb; + VectorSubtract(transvert[currenttransvert].v, r_origin, diff); + alpha = transvert[currenttransvert].a * exp(fogdensity / DotProduct(diff, diff)); + transvert[currenttransvert].a = (byte) bound(0, alpha, 255); + transvertindex[transvertindices++] = currenttransvert++; } - glEnd (); - glEnable(GL_TEXTURE_2D); } } } } - glEnd(); } + GL_LockArray(0, currenttransvert); + + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + tpolytype = TPOLYTYPE_ALPHA; + texnum = -1; + transvertindices = 0; + r = rendertranspoly; + rend = r + currentrendertranspoly; + while(r < rend) + { + if (texnum != r->tex) + { + texnum = r->tex; + glBindTexture(GL_TEXTURE_2D, texnum); + } + if (tpolytype != r->type) + { + tpolytype = r->type; + if (tpolytype == TPOLYTYPE_ADD) // additive + glBlendFunc(GL_SRC_ALPHA, GL_ONE); + else // alpha + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } + k = transvertindices; + if (gl_transpolytris.value) + { + do + transvertindices += r->indices, r++; + while (r < rend && r->tex == texnum && r->type == tpolytype); + glDrawElements(GL_TRIANGLES, transvertindices - k, GL_UNSIGNED_INT, &transvertindex[k]); + } + else + { + if (r->indices == 4) + { + do + transvertindices += 4, r++; + while (r < rend && r->indices == 4 && r->tex == texnum && r->type == tpolytype); + glDrawElements(GL_QUADS, transvertindices - k, GL_UNSIGNED_INT, &transvertindex[k]); + } + else if (r->indices == 3) + { + do + transvertindices += 3, r++; + while (r < rend && r->indices == 3 && r->tex == texnum && r->type == tpolytype); + glDrawElements(GL_TRIANGLES, transvertindices - k, GL_UNSIGNED_INT, &transvertindex[k]); + } + else + { + transvertindices += r->indices, r++; + glDrawElements(GL_POLYGON, transvertindices - k, GL_UNSIGNED_INT, &transvertindex[k]); + } + } + } + + GL_UnlockArray(); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glDepthMask(1); // enable zbuffer updates - glDisable(GL_ALPHA_TEST); + glDisable(GL_BLEND); + glColor3f(1,1,1); + + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + glDisableClientState(GL_COLOR_ARRAY); + glDisableClientState(GL_VERTEX_ARRAY); + } void wallpolyclear(void) { + if (!gl_mtexable) + r_multitexture.value = 0; currentwallpoly = currentwallvert = 0; } -void wallpolyrender(void) +// render walls and fullbrights, but not fog +void wallpolyrender1(void) { int i, j, texnum, lighttexnum; wallpoly_t *p; @@ -387,11 +529,9 @@ void wallpolyrender(void) c_brush_polys += currentwallpoly; // testing //Con_DPrintf("wallpolyrender: %i polys %i vertices\n", currentwallpoly, currentwallvert); - if (!gl_mtexable) - r_multitexture.value = 0; glDisable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glShadeModel(GL_FLAT); +// glShadeModel(GL_FLAT); // make sure zbuffer is enabled glEnable(GL_DEPTH_TEST); // glDisable(GL_ALPHA_TEST); @@ -401,7 +541,7 @@ void wallpolyrender(void) { glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); texnum = -1; - for (i = 0,p = wallpoly;i < currentwallpoly;i++, p++) + for (i = 0, p = wallpoly;i < currentwallpoly;i++, p++) { if (p->texnum != texnum) { @@ -472,7 +612,7 @@ void wallpolyrender(void) } texnum = -1; lighttexnum = -1; - for (i = 0,p = wallpoly;i < currentwallpoly;i++, p++) + for (i = 0, p = wallpoly;i < currentwallpoly;i++, p++) { if (p->texnum != texnum) { @@ -508,7 +648,7 @@ void wallpolyrender(void) // first do the textures glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); texnum = -1; - for (i = 0,p = wallpoly;i < currentwallpoly;i++, p++) + for (i = 0, p = wallpoly;i < currentwallpoly;i++, p++) { if (p->texnum != texnum) { @@ -549,10 +689,10 @@ void wallpolyrender(void) // switch to additive mode settings glDepthMask(0); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - glBlendFunc(GL_SRC_ALPHA, GL_ONE); + glBlendFunc(GL_ONE, GL_ONE); glEnable(GL_BLEND); // glDisable(GL_ALPHA_TEST); - glShadeModel(GL_SMOOTH); +// glShadeModel(GL_SMOOTH); // render vertex lit overlays ontop texnum = -1; for (i = 0, p = wallpoly;i < currentwallpoly;i++, p++) @@ -582,14 +722,13 @@ lit: glEnd(); } // render glow textures - glShadeModel(GL_FLAT); - glBlendFunc(GL_ONE, GL_ONE); +// glShadeModel(GL_FLAT); if (lighthalf) glColor3f(0.5,0.5,0.5); else glColor3f(1,1,1); texnum = -1; - for (i = 0,p = wallpoly;i < currentwallpoly;i++, p++) + for (i = 0, p = wallpoly;i < currentwallpoly;i++, p++) { if (!p->glowtexnum) continue; @@ -609,31 +748,54 @@ lit: } glColor3f(1,1,1); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glShadeModel(GL_SMOOTH); +// glDisable(GL_ALPHA_TEST); +// glShadeModel(GL_SMOOTH); + glDisable(GL_BLEND); + glDepthMask(1); +} + +// render fog +void wallpolyrender2(void) +{ + if (!r_render.value) + return; + if (currentwallpoly < 1) + return; if (fogenabled) { + int i, j, alpha, fogr, fogg, fogb; + wallpoly_t *p; + wallvert_t *vert; vec3_t diff; + glEnable(GL_DEPTH_TEST); + glDepthMask(0); + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_BLEND); +// glShadeModel(GL_SMOOTH); glDisable(GL_TEXTURE_2D); - for (i = 0,p = &wallpoly[0];i < currentwallpoly;i++, p++) + fogr = (byte) bound(0, (int) (fogcolor[0] * 255.0f), 255); + fogg = (byte) bound(0, (int) (fogcolor[1] * 255.0f), 255); + fogb = (byte) bound(0, (int) (fogcolor[2] * 255.0f), 255); + for (i = 0, p = wallpoly;i < currentwallpoly;i++, p++) { vert = &wallvert[p->firstvert]; glBegin(GL_POLYGON); for (j=0 ; jnumverts ; j++, vert++) { VectorSubtract(vert->vert, r_origin, diff); - glColor4f(fogcolor[0], fogcolor[1], fogcolor[2], exp(fogdensity/DotProduct(diff,diff))); + alpha = 255.0f * exp(fogdensity/DotProduct(diff,diff)); + alpha = bound(0, alpha, 255); + glColor4ub(fogr, fogg, fogb, (byte) alpha); glVertex3fv (vert->vert); } glEnd (); } glEnable(GL_TEXTURE_2D); + glColor3f(1,1,1); + glDisable(GL_BLEND); + glDepthMask(1); } - glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); -// glDisable(GL_ALPHA_TEST); - glShadeModel(GL_SMOOTH); - glDisable(GL_BLEND); - glDepthMask(1); } static int skyrendersphere; @@ -691,6 +853,8 @@ void skypolyclear(void) } +static void R_Sky(void); + void skypolyrender(void) { int i, j; @@ -859,6 +1023,8 @@ void skypolyrender(void) } GL_UnlockArray(); glDisableClientState(GL_VERTEX_ARRAY); + + R_Sky(); } static char skyname[256]; @@ -868,8 +1034,8 @@ static char skyname[256]; R_SetSkyBox ================== */ -char *suf[6] = {"rt", "bk", "lf", "ft", "up", "dn"}; -rtexture_t *skyboxside[6]; +static char *suf[6] = {"rt", "bk", "lf", "ft", "up", "dn"}; +static rtexture_t *skyboxside[6]; int R_SetSkyBox(char *sky) { int i; @@ -900,7 +1066,7 @@ int R_SetSkyBox(char *sky) sprintf (name, "gfx/env/%s%s", sky, suf[i]); if (!(image_rgba = loadimagepixels(name, false, 0, 0))) { - Con_Printf ("Couldn't load %s\n", name); + Con_Printf ("Couldn't load env/%s%s or gfx/env/%s%s\n", sky, suf[i], sky, suf[i]); continue; } } @@ -949,7 +1115,7 @@ void LoadSky_f (void) glTexCoord2f((s) * (254.0f/256.0f) + (1.0f/256.0f), (t) * (254.0f/256.0f) + (1.0f/256.0f));\ glVertex3f((x) * 1024.0 + r_origin[0], (y) * 1024.0 + r_origin[1], (z) * 1024.0 + r_origin[2]); -void R_SkyBox(void) +static void R_SkyBox(void) { glDisable(GL_DEPTH_TEST); glDepthMask(0); @@ -1006,9 +1172,9 @@ void R_SkyBox(void) glColor3f (1,1,1); } -float skysphere[33*33*5]; -int skysphereindices[32*32*6]; -void skyspherecalc(float *sphere, float dx, float dy, float dz) +static float skysphere[33*33*5]; +static int skysphereindices[32*32*6]; +static void skyspherecalc(float *sphere, float dx, float dy, float dz) { float a, b, x, ax, ay, v[3], length; int i, j, *index; @@ -1047,7 +1213,7 @@ void skyspherecalc(float *sphere, float dx, float dy, float dz) } } -void skyspherearrays(float *vert, float *tex, float *tex2, float *source, float s, float s2) +static void skyspherearrays(float *vert, float *tex, float *tex2, float *source, float s, float s2) { float *v, *t, *t2; int i; @@ -1068,7 +1234,7 @@ void skyspherearrays(float *vert, float *tex, float *tex2, float *source, float } } -void R_SkySphere(void) +static void R_SkySphere(void) { float speedscale, speedscale2; float vert[33*33*4], tex[33*33*2], tex2[33*33*2]; @@ -1207,7 +1373,7 @@ void R_SkySphere(void) glColor3f (1,1,1); } -void R_Sky(void) +static void R_Sky(void) { if (!r_render.value) return; @@ -1219,11 +1385,11 @@ void R_Sky(void) //=============================================================== -byte skyupperlayerpixels[128*128*4]; -byte skylowerlayerpixels[128*128*4]; -byte skymergedpixels[128*128*4]; +static byte skyupperlayerpixels[128*128*4]; +static byte skylowerlayerpixels[128*128*4]; +static byte skymergedpixels[128*128*4]; -void R_BuildSky (int scrollupper, int scrolllower) +static void R_BuildSky (int scrollupper, int scrolllower) { int x, y, ux, uy, lx, ly; byte *m, *u, *l; diff --git a/gl_poly.h b/gl_poly.h index 21665d71..6db5741e 100644 --- a/gl_poly.h +++ b/gl_poly.h @@ -9,9 +9,11 @@ extern void transpolyclear(void); extern void transpolyrender(void); extern void transpolybegin(int texnum, int glowtexnum, int fogtexnum, int transpolytype); extern void transpolyend(void); +extern void transpolyparticle(vec3_t org, vec3_t right, vec3_t up, vec_t scale, unsigned short texnum, unsigned short transpolytype, int ir, int ig, int ib, float alphaf, float s1, float t1, float s2, float t2); extern void wallpolyclear(void); -extern void wallpolyrender(void); +extern void wallpolyrender1(void); +extern void wallpolyrender2(void); extern void skypolyclear(void); extern void skypolyrender(void); @@ -88,7 +90,9 @@ skypoly_t; extern transvert_t *transvert; extern transpoly_t *transpoly; -extern unsigned short *transpolyindex; +extern int *transpolyindex; +extern int *transvertindex; +extern transpoly_t **transpolylist; extern wallvert_t *wallvert; extern wallvertcolor_t *wallvertcolor; extern wallpoly_t *wallpoly; diff --git a/gl_rmain.c b/gl_rmain.c index ffa9226b..f848defa 100644 --- a/gl_rmain.c +++ b/gl_rmain.c @@ -8,7 +8,7 @@ of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. @@ -21,10 +21,10 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "quakedef.h" -qboolean r_cache_thrash; // compatability +//static qboolean r_cache_thrash; // compatability -vec3_t modelorg, r_entorigin; -entity_t *currententity; +vec3_t modelorg; +entity_render_t *currentrenderentity; int r_framecount; // used for dlight push checking @@ -46,8 +46,8 @@ vec3_t vpn; vec3_t vright; vec3_t r_origin; -float r_world_matrix[16]; -float r_base_world_matrix[16]; +//float r_world_matrix[16]; +//float r_base_world_matrix[16]; // // screen size info @@ -58,8 +58,6 @@ mleaf_t *r_viewleaf, *r_oldviewleaf; unsigned short d_lightstylevalue[256]; // 8.8 fraction of base light value -void R_MarkLeaves (void); - //cvar_t r_norefresh = {0, "r_norefresh","0"}; cvar_t r_drawentities = {0, "r_drawentities","1"}; cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1"}; @@ -86,24 +84,23 @@ cvar_t gl_fogend = {0, "gl_fogend","0"}; cvar_t glfog = {0, "glfog", "0"}; cvar_t r_ser = {CVAR_SAVE, "r_ser", "1"}; +cvar_t gl_viewmodeldepthhack = {0, "gl_viewmodeldepthhack", "1"}; -/* int R_VisibleCullBox (vec3_t mins, vec3_t maxs) { int sides; mnode_t *nodestack[8192], *node; int stack = 0; + if (R_CullBox(mins, maxs)) + return true; + node = cl.worldmodel->nodes; loc0: if (node->contents < 0) { if (((mleaf_t *)node)->visframe == r_framecount) - { - if (R_CullBox(mins, maxs)) - return true; return false; - } if (!stack) return true; node = nodestack[--stack]; @@ -132,7 +129,6 @@ loc0: node = node->children[1]; goto loc0; } -*/ qboolean lighthalf; @@ -143,10 +139,8 @@ qboolean fogenabled; qboolean oldgl_fogenable; void FOG_framebegin(void) { - if (nehahra) + if (gamemode == GAME_NEHAHRA) { -// if (!Nehahrademcompatibility) -// gl_fogenable.value = 0; if (gl_fogenable.value) { oldgl_fogenable = true; @@ -182,7 +176,7 @@ void FOG_framebegin(void) return; if(fog_density) { - // LordHavoc: Borland C++ 5.0 was choking on this line, stupid compiler... + // LordHavoc: Borland C++ 5.0 was choking on this line... //GLfloat colors[4] = {(GLfloat) gl_fogred.value, (GLfloat) gl_foggreen.value, (GLfloat) gl_fogblue.value, (GLfloat) 1}; GLfloat colors[4]; colors[0] = fog_red; @@ -197,7 +191,7 @@ void FOG_framebegin(void) } glFogi (GL_FOG_MODE, GL_EXP2); - glFogf (GL_FOG_DENSITY, (GLfloat) fog_density / 100); + glFogf (GL_FOG_DENSITY, (GLfloat) fog_density / 100); glFogfv (GL_FOG_COLOR, colors); glEnable (GL_FOG); } @@ -225,7 +219,7 @@ void FOG_frameend(void) void FOG_clear(void) { - if (nehahra) + if (gamemode == GAME_NEHAHRA) { Cvar_Set("gl_fogenable", "0"); Cvar_Set("gl_fogdensity", "0.2"); @@ -239,7 +233,7 @@ void FOG_clear(void) void FOG_registercvars(void) { Cvar_RegisterVariable (&glfog); - if (nehahra) + if (gamemode == GAME_NEHAHRA) { Cvar_RegisterVariable (&gl_fogenable); Cvar_RegisterVariable (&gl_fogdensity); @@ -278,12 +272,11 @@ void GL_Main_Init(void) Cvar_RegisterVariable (&r_dynamic); Cvar_RegisterVariable (&r_waterripple); Cvar_RegisterVariable (&r_farclip); - if (nehahra) - Cvar_SetValue("r_fullbrights", 0); -// if (gl_vendor && strstr(gl_vendor, "3Dfx")) -// gl_lightmode.value = 0; Cvar_RegisterVariable (&r_fullbright); Cvar_RegisterVariable (&r_ser); + Cvar_RegisterVariable (&gl_viewmodeldepthhack); + if (gamemode == GAME_NEHAHRA) + Cvar_SetValue("r_fullbrights", 0); R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap); } @@ -360,151 +353,66 @@ void GL_Init (void) } -/* -void R_RotateForEntity (entity_t *e) -{ - glTranslatef (e->origin[0], e->origin[1], e->origin[2]); - - glRotatef (e->angles[1], 0, 0, 1); - glRotatef (-e->angles[0], 0, 1, 0); - glRotatef (e->angles[2], 1, 0, 0); - - glScalef (e->scale, e->scale, e->scale); // LordHavoc: model scale -} -*/ - -// LordHavoc: shading stuff -vec3_t shadevector; -vec3_t shadecolor; - -float modelalpha; - //================================================================================== -void R_LerpUpdate(entity_t *ent) +void R_Entity_Callback(void *data, void *junk) { - int frame; - frame = ent->render.frame; - if (ent->render.model && ent->render.frame >= ent->render.model->numframes) - { - Con_Printf("R_LerpUpdate: no such frame%6i in \"%s\"\n", ent->render.frame, ent->render.model->name); - frame = 0; - } - - if (ent->render.lerp_model != ent->render.model) - { - // reset all interpolation information - ent->render.lerp_model = ent->render.model; - ent->render.frame1 = ent->render.frame2 = frame; - ent->render.frame1start = ent->render.frame2start = cl.time; - ent->render.framelerp = 1; - ent->render.lerp_starttime = 0; - } - else if (ent->render.frame2 != frame) - { - // transition to new frame - ent->render.frame1 = ent->render.frame2; - ent->render.frame1start = ent->render.frame2start; - ent->render.frame2 = frame; - ent->render.frame2start = cl.time; - ent->render.framelerp = 0; - ent->render.lerp_starttime = cl.time; - } - else - { - // lerp_starttime < 0 is used to prevent changing of framelerp - if (ent->render.lerp_starttime >= 0) - { - // update transition - ent->render.framelerp = (cl.time - ent->render.lerp_starttime) * 10; - ent->render.framelerp = bound(0, ent->render.framelerp, 1); - } - } + ((entity_render_t *)data)->visframe = r_framecount; } - -void R_PrepareEntities (void) +static void R_AddModelEntities (void) { - int i; - entity_t *ent; - vec3_t v; - // this updates entities that are supposed to be view relative + int i; + vec3_t v; + + if (!r_drawentities.value) + return; + for (i = 0;i < cl_numvisedicts;i++) { - ent = cl_visedicts[i]; + currentrenderentity = &cl_visedicts[i]->render; - if (ent->render.flags & RENDER_VIEWMODEL) + // move view-relative models to where they should be + if (currentrenderentity->flags & RENDER_VIEWMODEL) { // remove flag so it will not be repeated incase RelinkEntities is not called again for a while - ent->render.flags -= RENDER_VIEWMODEL; + currentrenderentity->flags -= RENDER_VIEWMODEL; // transform origin - VectorCopy(ent->render.origin, v); - ent->render.origin[0] = v[0] * vpn[0] + v[1] * vright[0] + v[2] * vup[0] + r_origin[0]; - ent->render.origin[1] = v[0] * vpn[1] + v[1] * vright[1] + v[2] * vup[1] + r_origin[1]; - ent->render.origin[2] = v[0] * vpn[2] + v[1] * vright[2] + v[2] * vup[2] + r_origin[2]; + VectorCopy(currentrenderentity->origin, v); + currentrenderentity->origin[0] = v[0] * vpn[0] + v[1] * vright[0] + v[2] * vup[0] + r_origin[0]; + currentrenderentity->origin[1] = v[0] * vpn[1] + v[1] * vright[1] + v[2] * vup[1] + r_origin[1]; + currentrenderentity->origin[2] = v[0] * vpn[2] + v[1] * vright[2] + v[2] * vup[2] + r_origin[2]; // adjust angles - VectorAdd(ent->render.angles, r_refdef.viewangles, ent->render.angles); + VectorAdd(currentrenderentity->angles, r_refdef.viewangles, currentrenderentity->angles); } - } -} - -void R_Entity_Callback(void *data, void *junk) -{ - ((entity_t *)data)->render.visframe = r_framecount; -} - -void R_AddModelEntities (void) -{ - int i; - vec3_t mins, maxs; - frameblend_t blend[4]; - - if (!r_drawentities.value) - return; - for (i = 0;i < cl_numvisedicts;i++) - { - currententity = cl_visedicts[i]; - if (currententity->render.model->type == mod_brush) + if (currentrenderentity->angles[0] || currentrenderentity->angles[2]) { - modelalpha = currententity->render.alpha; - R_DrawBrushModel (currententity); + VectorMA(currentrenderentity->origin, currentrenderentity->scale, currentrenderentity->model->rotatedmins, currentrenderentity->mins); + VectorMA(currentrenderentity->origin, currentrenderentity->scale, currentrenderentity->model->rotatedmaxs, currentrenderentity->maxs); } - else if (currententity->render.model->type == mod_alias) + else if (currentrenderentity->angles[1]) { - VectorAdd(currententity->render.origin, currententity->render.model->mins, mins); - VectorAdd(currententity->render.origin, currententity->render.model->maxs, maxs); - if (r_ser.value) - R_Clip_AddBox(mins, maxs, R_Entity_Callback, currententity, NULL); - else if (R_NotCulledBox(mins, maxs)) - currententity->render.visframe = r_framecount; + VectorMA(currentrenderentity->origin, currentrenderentity->scale, currentrenderentity->model->yawmins, currentrenderentity->mins); + VectorMA(currentrenderentity->origin, currentrenderentity->scale, currentrenderentity->model->yawmaxs, currentrenderentity->maxs); } - else if (currententity->render.model->type == mod_sprite) + else { - R_LerpUpdate(currententity); - if (r_ser.value) - { - R_LerpAnimation(currententity->render.model, currententity->render.frame1, currententity->render.frame2, currententity->render.frame1start, currententity->render.frame2start, currententity->render.framelerp, blend); - R_ClipSprite(currententity, blend); - } - else - { - VectorAdd(currententity->render.origin, currententity->render.model->mins, mins); - VectorAdd(currententity->render.origin, currententity->render.model->maxs, maxs); - if (R_NotCulledBox(mins, maxs)) - currententity->render.visframe = r_framecount; - } + VectorMA(currentrenderentity->origin, currentrenderentity->scale, currentrenderentity->model->normalmins, currentrenderentity->mins); + VectorMA(currentrenderentity->origin, currentrenderentity->scale, currentrenderentity->model->normalmaxs, currentrenderentity->maxs); } + if (R_VisibleCullBox(currentrenderentity->mins, currentrenderentity->maxs)) + continue; + + R_LerpAnimation(currentrenderentity); + if (r_ser.value) + currentrenderentity->model->SERAddEntity(); + else + currentrenderentity->visframe = r_framecount; } } -/* -============= -R_DrawEntitiesOnList -============= -*/ -/* -void R_DrawEntitiesOnList1 (void) +void R_DrawModels1 (void) { int i; @@ -513,65 +421,24 @@ void R_DrawEntitiesOnList1 (void) for (i = 0;i < cl_numvisedicts;i++) { - if (cl_visedicts[i]->render.visframe != r_framecount) - continue; - if (cl_visedicts[i]->render.model->type != mod_brush) - continue; - currententity = cl_visedicts[i]; - modelalpha = currententity->render.alpha; - - R_DrawBrushModel (currententity); + currentrenderentity = &cl_visedicts[i]->render; + if (currentrenderentity->visframe == r_framecount && currentrenderentity->model->DrawEarly) + currentrenderentity->model->DrawEarly(); } } -*/ -void R_DrawModels (void) +void R_DrawModels2 (void) { int i; - frameblend_t blend[4]; -// vec3_t mins, maxs; if (!r_drawentities.value) return; for (i = 0;i < cl_numvisedicts;i++) { - if (cl_visedicts[i]->render.visframe != r_framecount) - continue; - currententity = cl_visedicts[i]; - if (currententity->render.model->type != mod_alias && currententity->render.model->type != mod_sprite) - continue; - - modelalpha = currententity->render.alpha; - - if (currententity->render.model->type == mod_alias) - { - // only lerp models here because sprites were already lerped for their clip polygon - R_LerpUpdate(currententity); - R_LerpAnimation(currententity->render.model, currententity->render.frame1, currententity->render.frame2, currententity->render.frame1start, currententity->render.frame2start, currententity->render.framelerp, blend); - R_DrawAliasModel (currententity, true, modelalpha, currententity->render.model, blend, currententity->render.skinnum, currententity->render.origin, currententity->render.angles, currententity->render.scale, currententity->render.effects, currententity->render.model->flags, currententity->render.colormap); - } - else //if (currententity->render.model->type == mod_sprite) - { - // build blend array - R_LerpAnimation(currententity->render.model, currententity->render.frame1, currententity->render.frame2, currententity->render.frame1start, currententity->render.frame2start, currententity->render.framelerp, blend); - R_DrawSpriteModel (currententity, blend); - } - - /* - VectorAdd(cl_visedicts[i]->render.origin, cl_visedicts[i]->render.model->mins, mins); - VectorAdd(cl_visedicts[i]->render.origin, cl_visedicts[i]->render.model->maxs, maxs); - - switch (cl_visedicts[i]->render.model->type) - { - case mod_alias: - R_Clip_AddBox(mins, maxs, R_DrawModelCallback, cl_visedicts[i], NULL); - break; - case mod_sprite: - R_Clip_AddBox(mins, maxs, R_DrawSpriteCallback, cl_visedicts[i], NULL); - break; - } - */ + currentrenderentity = &cl_visedicts[i]->render; + if (currentrenderentity->visframe == r_framecount && currentrenderentity->model->DrawLate) + currentrenderentity->model->DrawLate(); } } @@ -582,31 +449,22 @@ R_DrawViewModel */ void R_DrawViewModel (void) { - frameblend_t blend[4]; - if (!r_drawviewmodel.value || chase_active.value || envmap || !r_drawentities.value || cl.items & IT_INVISIBILITY || cl.stats[STAT_HEALTH] <= 0 || !cl.viewent.render.model) return; - currententity = &cl.viewent; - currententity->render.alpha = modelalpha = cl_entities[cl.viewentity].render.alpha; // LordHavoc: if the player is transparent, so is the gun - currententity->render.effects = cl_entities[cl.viewentity].render.effects; - currententity->render.scale = 1; - VectorCopy(cl_entities[cl.viewentity].render.colormod, currententity->render.colormod); + currentrenderentity = &cl.viewent.render; - R_LerpUpdate(currententity); - R_LerpAnimation(currententity->render.model, currententity->render.frame1, currententity->render.frame2, currententity->render.frame1start, currententity->render.frame2start, currententity->render.framelerp, blend); + R_LerpAnimation(currentrenderentity); // hack the depth range to prevent view model from poking into walls - glDepthRange (gldepthmin, gldepthmin + 0.3*(gldepthmax-gldepthmin)); - R_DrawAliasModel (currententity, false, modelalpha, currententity->render.model, blend, currententity->render.skinnum, currententity->render.origin, currententity->render.angles, currententity->render.scale, currententity->render.effects, currententity->render.model->flags, currententity->render.colormap); - glDepthRange (gldepthmin, gldepthmax); + if (gl_viewmodeldepthhack.value) + glDepthRange (gldepthmin, gldepthmin + 0.3*(gldepthmax-gldepthmin)); + currentrenderentity->model->DrawLate(); + if (gl_viewmodeldepthhack.value) + glDepthRange (gldepthmin, gldepthmax); } -void R_DrawBrushModel (entity_t *e); - -void RotatePointAroundVector( vec3_t dst, const vec3_t dir, const vec3_t point, float degrees ); - -void R_SetFrustum (void) +static void R_SetFrustum (void) { int i; @@ -646,21 +504,20 @@ void R_SetFrustum (void) } } -void R_AnimateLight (void); -void V_CalcBlend (void); - /* =============== R_SetupFrame =============== */ -void R_SetupFrame (void) +static void R_SetupFrame (void) { // don't allow cheats in multiplayer if (cl.maxclients > 1) { - Cvar_Set ("r_fullbright", "0"); - Cvar_Set ("r_ambient", "0"); + if (r_fullbright.value != 0) + Cvar_Set ("r_fullbright", "0"); + if (r_ambient.value != 0) + Cvar_Set ("r_ambient", "0"); } r_framecount++; @@ -677,7 +534,7 @@ void R_SetupFrame (void) V_SetContentsColor (r_viewleaf->contents); V_CalcBlend (); - r_cache_thrash = false; +// r_cache_thrash = false; c_brush_polys = 0; c_alias_polys = 0; @@ -695,17 +552,20 @@ void R_SetupFrame (void) } -void MYgluPerspective( GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar ) +static void MYgluPerspective(GLdouble fovx, GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar ) { - GLdouble xmin, xmax, ymin, ymax; + GLdouble xmax, ymax; - ymax = zNear * tan( fovy * M_PI / 360.0 ); - ymin = -ymax; + xmax = zNear * tan( fovx * M_PI / 360.0 ) * aspect; + ymax = zNear * tan( fovy * M_PI / 360.0 ); - xmin = ymin * aspect; - xmax = ymax * aspect; + if (r_viewleaf->contents != CONTENTS_EMPTY && r_viewleaf->contents != CONTENTS_SOLID) + { + xmax *= (sin(cl.time * 4.7) * 0.03 + 0.97); + ymax *= (sin(cl.time * 3) * 0.03 + 0.97); + } - glFrustum( xmin, xmax, ymin, ymax, zNear, zFar ); + glFrustum(-xmax, xmax, -ymax, ymax, zNear, zFar ); } @@ -714,60 +574,33 @@ void MYgluPerspective( GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble R_SetupGL ============= */ -void R_SetupGL (void) +static void R_SetupGL (void) { - float screenaspect; - int x, x2, y2, y, w, h; - if (!r_render.value) return; - // + // set up viewpoint - // glMatrixMode(GL_PROJECTION); - glLoadIdentity (); - x = r_refdef.vrect.x * glwidth/vid.width; - x2 = (r_refdef.vrect.x + r_refdef.vrect.width) * glwidth/vid.width; - y = (vid.height-r_refdef.vrect.y) * glheight/vid.height; - y2 = (vid.height - (r_refdef.vrect.y + r_refdef.vrect.height)) * glheight/vid.height; - - // fudge around because of frac screen scale - if (x > 0) - x--; - if (x2 < glwidth) - x2++; - if (y2 < 0) - y2--; - if (y < glheight) - y++; - - w = x2 - x; - h = y - y2; - - if (envmap) - { - x = y2 = 0; - w = h = 256; - } + glLoadIdentity (); - glViewport (glx + x, gly + y2, w, h); - screenaspect = (float)r_refdef.vrect.width/r_refdef.vrect.height; -// yfov = 2*atan((float)r_refdef.vrect.height/r_refdef.vrect.width)*180/M_PI; - MYgluPerspective (r_refdef.fov_y, screenaspect, 4, r_farclip.value); + // y is weird beause OpenGL is bottom to top, we use top to bottom + glViewport(r_refdef.x, vid.realheight - (r_refdef.y + r_refdef.height), r_refdef.width, r_refdef.height); +// yfov = 2*atan((float)r_refdef.height/r_refdef.width)*180/M_PI; + MYgluPerspective (r_refdef.fov_x, r_refdef.fov_y, r_refdef.width/r_refdef.height, 4, r_farclip.value); glCullFace(GL_FRONT); glMatrixMode(GL_MODELVIEW); - glLoadIdentity (); + glLoadIdentity (); - glRotatef (-90, 1, 0, 0); // put Z going up - glRotatef (90, 0, 0, 1); // put Z going up - glRotatef (-r_refdef.viewangles[2], 1, 0, 0); - glRotatef (-r_refdef.viewangles[0], 0, 1, 0); - glRotatef (-r_refdef.viewangles[1], 0, 0, 1); - glTranslatef (-r_refdef.vieworg[0], -r_refdef.vieworg[1], -r_refdef.vieworg[2]); + glRotatef (-90, 1, 0, 0); // put Z going up + glRotatef (90, 0, 0, 1); // put Z going up + glRotatef (-r_refdef.viewangles[2], 1, 0, 0); + glRotatef (-r_refdef.viewangles[0], 0, 1, 0); + glRotatef (-r_refdef.viewangles[1], 0, 0, 1); + glTranslatef (-r_refdef.vieworg[0], -r_refdef.vieworg[1], -r_refdef.vieworg[2]); - glGetFloatv (GL_MODELVIEW_MATRIX, r_world_matrix); +// glGetFloatv (GL_MODELVIEW_MATRIX, r_world_matrix); // // set drawing parms @@ -790,7 +623,7 @@ void R_SetupGL (void) R_Clear ============= */ -void R_Clear (void) +static void R_Clear (void) { if (!r_render.value) return; @@ -802,35 +635,7 @@ void R_Clear (void) glDepthRange (gldepthmin, gldepthmax); } -// LordHavoc: my trick to *FIX* GLQuake lighting once and for all :) -void GL_Brighten(void) -{ - if (!r_render.value) - return; - glMatrixMode(GL_PROJECTION); - glLoadIdentity (); - glOrtho (0, vid.width, vid.height, 0, -99999, 99999); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity (); - glDisable (GL_DEPTH_TEST); - glDisable (GL_CULL_FACE); - glDisable(GL_TEXTURE_2D); - glEnable(GL_BLEND); - glBlendFunc (GL_DST_COLOR, GL_ONE); - glBegin (GL_TRIANGLES); - glColor3f (1, 1, 1); - glVertex2f (-5000, -5000); - glVertex2f (10000, -5000); - glVertex2f (-5000, 10000); - glEnd (); - glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glDisable(GL_BLEND); - glEnable(GL_TEXTURE_2D); - glEnable (GL_DEPTH_TEST); - glEnable (GL_CULL_FACE); -} - -void GL_BlendView(void) +static void GL_BlendView(void) { if (!r_render.value) return; @@ -840,7 +645,7 @@ void GL_BlendView(void) glMatrixMode(GL_PROJECTION); glLoadIdentity (); - glOrtho (0, vid.width, vid.height, 0, -99999, 99999); + glOrtho (0, 256, 256, 0, -99999, 99999); glMatrixMode(GL_MODELVIEW); glLoadIdentity (); glDisable (GL_DEPTH_TEST); @@ -871,7 +676,6 @@ R_RenderView r_refdef must be set before the first call ================ */ -extern void R_Sky(void); extern void UploadLightmaps(void); extern void R_DrawSurfaces(void); extern void R_DrawPortals(void); @@ -919,28 +723,28 @@ void timestring(int t, char *desc) void R_RenderView (void) { double starttime, currtime, temptime; -// if (r_norefresh.value) -// return; if (!cl.worldmodel) Host_Error ("R_RenderView: NULL worldmodel"); if (r_speeds2.value) { - starttime = currtime = Sys_DoubleTime(); - speedstringcount = 0; sprintf(r_speeds2_string, "org:'%c%6.2f %c%6.2f %c%6.2f' ang:'%c%3.0f %c%3.0f %c%3.0f' dir:'%c%2.3f %c%2.3f %c%2.3f'\n%6i walls %6i dlitwalls %7i modeltris %7i transpoly\nBSP: %6i faces %6i nodes %6i leafs\n%4i models %4i bmodels %4i sprites %5i particles %3i dlights\n", r_origin[0] < 0 ? '-' : ' ', fabs(r_origin[0]), r_origin[1] < 0 ? '-' : ' ', fabs(r_origin[1]), r_origin[2] < 0 ? '-' : ' ', fabs(r_origin[2]), r_refdef.viewangles[0] < 0 ? '-' : ' ', fabs(r_refdef.viewangles[0]), r_refdef.viewangles[1] < 0 ? '-' : ' ', fabs(r_refdef.viewangles[1]), r_refdef.viewangles[2] < 0 ? '-' : ' ', fabs(r_refdef.viewangles[2]), vpn[0] < 0 ? '-' : ' ', fabs(vpn[0]), vpn[1] < 0 ? '-' : ' ', fabs(vpn[1]), vpn[2] < 0 ? '-' : ' ', fabs(vpn[2]), c_brush_polys, c_light_polys, c_alias_polys, currenttranspoly, c_faces, c_nodes, c_leafs, c_models, c_bmodels, c_sprites, c_particles, c_dlights); + + starttime = currtime = Sys_DoubleTime(); } else starttime = currtime = 0; R_MoveParticles (); + TIMEREPORT("mparticles") R_MoveExplosions(); + TIMEREPORT("mexplosion") FOG_framebegin(); @@ -954,8 +758,6 @@ void R_RenderView (void) R_SetupGL (); R_Clip_StartFrame(); - R_PrepareEntities(); - skypolyclear(); wallpolyclear(); transpolyclear(); @@ -963,17 +765,21 @@ void R_RenderView (void) TIMEREPORT("setup ") R_DrawWorld (); - TIMEREPORT("world ") + TIMEREPORT("addworld ") R_AddModelEntities(); - TIMEREPORT("addmodels") + TIMEREPORT("addmodels ") R_Clip_EndFrame(); TIMEREPORT("scanedge ") // now mark the lit surfaces R_PushDlights (); - // yes this does add the world surfaces after the brush models + TIMEREPORT("marklights") + + R_DrawModels1 (); + + // yes this does add the world after the brush models when using the SER R_DrawSurfaces (); R_DrawPortals (); TIMEREPORT("surfaces "); @@ -981,30 +787,29 @@ void R_RenderView (void) UploadLightmaps(); TIMEREPORT("uploadlmap") - // fogged sky polys, affects depth skypolyrender(); - - // does not affect depth, draws over the sky polys - if (currentskypoly) - R_Sky(); TIMEREPORT("skypoly ") - wallpolyrender(); - TIMEREPORT("wallpoly ") + wallpolyrender1(); + TIMEREPORT("wallpoly1 ") GL_DrawDecals(); TIMEREPORT("ddecal ") + wallpolyrender2(); + TIMEREPORT("wallpoly2 ") + // don't let sound skip if going slow if (!intimerefresh && !r_speeds2.value) S_ExtraUpdate (); R_DrawViewModel (); - R_DrawModels (); + R_DrawModels2 (); TIMEREPORT("models ") R_DrawParticles (); TIMEREPORT("dparticles") + R_DrawExplosions(); TIMEREPORT("dexplosion") diff --git a/gl_rmisc.c b/gl_rmisc.c index 5a8a874b..5cf56120 100644 --- a/gl_rmisc.c +++ b/gl_rmisc.c @@ -8,7 +8,7 @@ of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. @@ -29,74 +29,104 @@ R_Envmap_f Grab six views for environment mapping tests =============== */ +float CalcFov (float fov_x, float width, float height); +struct +{ + float angles[3]; + char *name; +} +envmapinfo[6] = +{ + {{ 0, 0, 0}, "ft"}, + {{ 0, 90, 0}, "rt"}, + {{ 0, 180, 0}, "bk"}, + {{ 0, 270, 0}, "lf"}, + {{-90, 90, 0}, "up"}, + {{ 90, 90, 0}, "dn"} +}; void R_Envmap_f (void) { - byte buffer[256*256*4]; + int i, size; + char filename[256]; + char basename[256]; + byte *buffer, gamma[256]; + + if (Cmd_Argc() != 3) + { + Con_Printf ("envmap : save out 6 cubic environment map images, usable with loadsky, note that size must one of 128, 256, 512, or 1024 and can't be bigger than your current resolution\n"); + return; + } if (!r_render.value) return; - glDrawBuffer (GL_FRONT); - glReadBuffer (GL_FRONT); + strcpy(basename, Cmd_Argv(1)); + size = atoi(Cmd_Argv(2)); + if (size != 128 && size != 256 && size != 512 && size != 1024) + { + Con_Printf("envmap: size must be one of 128, 256, 512, or 1024\n"); + return; + } + if (size > vid.realwidth || size > vid.realheight) + { + Con_Printf("envmap: your resolution is not big enough to render that size\n"); + return; + } + + buffer = malloc(size*size*3); + if (buffer == NULL) + { + Con_Printf("envmap: unable to allocate memory for image\n"); + return; + } + + BuildGammaTable8((lighthalf && hardwaregammasupported) ? 2.0f : 1.0f, 1, 1, 0, gamma); + +// glDrawBuffer (GL_FRONT); +// glReadBuffer (GL_FRONT); + glDrawBuffer (GL_BACK); + glReadBuffer (GL_BACK); envmap = true; - r_refdef.vrect.x = 0; - r_refdef.vrect.y = 0; - r_refdef.vrect.width = 256; - r_refdef.vrect.height = 256; - - r_refdef.viewangles[0] = 0; - r_refdef.viewangles[1] = 0; - r_refdef.viewangles[2] = 0; - R_RenderView (); - glReadPixels (0, 0, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, buffer); - COM_WriteFile ("env0.rgb", buffer, sizeof(buffer)); - - r_refdef.viewangles[1] = 90; - R_RenderView (); - glReadPixels (0, 0, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, buffer); - COM_WriteFile ("env1.rgb", buffer, sizeof(buffer)); - - r_refdef.viewangles[1] = 180; - R_RenderView (); - glReadPixels (0, 0, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, buffer); - COM_WriteFile ("env2.rgb", buffer, sizeof(buffer)); - - r_refdef.viewangles[1] = 270; - GL_BeginRendering (&glx, &gly, &glwidth, &glheight); - R_RenderView (); - glReadPixels (0, 0, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, buffer); - COM_WriteFile ("env3.rgb", buffer, sizeof(buffer)); - - r_refdef.viewangles[0] = -90; - r_refdef.viewangles[1] = 0; - R_RenderView (); - glReadPixels (0, 0, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, buffer); - COM_WriteFile ("env4.rgb", buffer, sizeof(buffer)); - - r_refdef.viewangles[0] = 90; - r_refdef.viewangles[1] = 0; - R_RenderView (); - glReadPixels (0, 0, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, buffer); - COM_WriteFile ("env5.rgb", buffer, sizeof(buffer)); + r_refdef.x = 0; + r_refdef.y = 0; + r_refdef.width = size; + r_refdef.height = size; + + r_refdef.fov_x = 90; + r_refdef.fov_y = 90; + + for (i = 0;i < 6;i++) + { + VectorCopy(envmapinfo[i].angles, r_refdef.viewangles); + glClearColor(0,0,0,0); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // LordHavoc: clear the screen (around the view as well) + R_RenderView (); + glReadPixels (0, 0, size, size, GL_RGB, GL_UNSIGNED_BYTE, buffer); + sprintf(filename, "env/%s%s.tga", basename, envmapinfo[i].name); + Image_GammaRemapRGB(buffer, buffer, size * size, gamma, gamma, gamma); + Image_WriteTGARGB_preflipped(filename, size, size, buffer); + } envmap = false; glDrawBuffer (GL_BACK); glReadBuffer (GL_BACK); - GL_EndRendering (); -} -void R_InitParticles (void); + free(buffer); + + // cause refdef to be fixed +// vid.recalc_refdef = 1; +} -void gl_misc_start(void) +static void gl_misc_start(void) { } -void gl_misc_shutdown(void) +static void gl_misc_shutdown(void) { } -void gl_misc_newmap(void) +static void gl_misc_newmap(void) { } @@ -105,15 +135,15 @@ void gl_misc_newmap(void) R_Init =============== */ +static void R_TimeRefresh_f (void); void GL_Misc_Init (void) -{ - Cmd_AddCommand ("envmap", R_Envmap_f); - Cmd_AddCommand ("timerefresh", R_TimeRefresh_f); +{ + Cmd_AddCommand ("envmap", R_Envmap_f); + Cmd_AddCommand ("timerefresh", R_TimeRefresh_f); R_RegisterModule("GL_Misc", gl_misc_start, gl_misc_shutdown, gl_misc_newmap); } -extern void R_ClearParticles (void); extern void GL_BuildLightmaps (void); /* @@ -124,7 +154,7 @@ R_NewMap void R_NewMap (void) { int i; - + for (i=0 ; i<256 ; i++) d_lightstylevalue[i] = 264; // normal light value @@ -145,20 +175,22 @@ For program optimization ==================== */ qboolean intimerefresh = 0; -void R_TimeRefresh_f (void) +static void R_TimeRefresh_f (void) { int i; float start, stop, time; intimerefresh = 1; start = Sys_DoubleTime (); + glDrawBuffer (GL_FRONT); for (i = 0;i < 128;i++) { r_refdef.viewangles[0] = 0; r_refdef.viewangles[1] = i/128.0*360.0; r_refdef.viewangles[2] = 0; - SCR_UpdateScreen(); + R_RenderView(); } + glDrawBuffer (GL_BACK); stop = Sys_DoubleTime (); intimerefresh = 0; diff --git a/gl_rsurf.c b/gl_rsurf.c index 30851689..0b9f07f2 100644 --- a/gl_rsurf.c +++ b/gl_rsurf.c @@ -38,8 +38,10 @@ short lightmapupdate[MAX_LIGHTMAPS][2]; signed int blocklights[BLOCK_WIDTH*BLOCK_HEIGHT*3]; // LordHavoc: *3 for colored lighting -int lightmapalign, lightmapalignmask; // LordHavoc: NVIDIA's broken subimage fix, see BuildLightmaps for notes -cvar_t gl_lightmapalign = {0, "gl_lightmapalign", "4"}; +byte templight[BLOCK_WIDTH*BLOCK_HEIGHT*4]; + +int lightmapalign, lightmapalignmask; // LordHavoc: align texsubimage updates on 4 byte boundaries +cvar_t gl_lightmapalign = {0, "gl_lightmapalign", "4"}; // align texsubimage updates on 4 byte boundaries cvar_t gl_lightmaprgba = {0, "gl_lightmaprgba", "1"}; cvar_t gl_nosubimagefragments = {0, "gl_nosubimagefragments", "0"}; cvar_t gl_nosubimage = {0, "gl_nosubimage", "0"}; @@ -48,8 +50,6 @@ cvar_t gl_vertex = {0, "gl_vertex", "0"}; cvar_t r_dlightmap = {CVAR_SAVE, "r_dlightmap", "1"}; cvar_t r_drawportals = {0, "r_drawportals", "0"}; cvar_t r_testvis = {0, "r_testvis", "0"}; -cvar_t r_solidworldnode = {0, "r_solidworldnode", "3"}; -cvar_t r_pvsworldnode = {0, "r_pvsworldnode", "1"}; qboolean lightmaprgba, nosubimagefragments, nosubimage; int lightmapbytes; @@ -82,8 +82,6 @@ void GL_Surf_Init(void) Cvar_RegisterVariable(&r_dlightmap); Cvar_RegisterVariable(&r_drawportals); Cvar_RegisterVariable(&r_testvis); - Cvar_RegisterVariable(&r_solidworldnode); - Cvar_RegisterVariable(&r_pvsworldnode); R_RegisterModule("GL_Surf", gl_surf_start, gl_surf_shutdown, gl_surf_newmap); } @@ -124,7 +122,7 @@ int R_AddDynamicLights (msurface_t *surf) if (!(surf->dlightbits[lnum >> 5] & (1 << (lnum & 31)))) continue; // not lit by this light - VectorSubtract (cl_dlights[lnum].origin, currententity->render.origin, local); + VectorSubtract (cl_dlights[lnum].origin, currentrenderentity->origin, local); dist = DotProduct (local, surf->plane->normal) - surf->plane->dist; // for comparisons to minimum acceptable light @@ -232,7 +230,7 @@ R_BuildLightMap Combine and scale multiple lightmaps into the 8.8 format in blocklights =============== */ -void R_BuildLightMap (msurface_t *surf, byte *dest, int stride) +void R_BuildLightMap (msurface_t *surf, byte *dest, int stride, int dlightchanged) { int smax, tmax; int i, j, size, size3; @@ -241,9 +239,14 @@ void R_BuildLightMap (msurface_t *surf, byte *dest, int stride) int maps; int *bl; + // update cached lighting info surf->cached_dlight = 0; surf->cached_lightscalebit = lightscalebit; surf->cached_ambient = r_ambient.value; + surf->cached_light[0] = d_lightstylevalue[surf->styles[0]]; + surf->cached_light[1] = d_lightstylevalue[surf->styles[1]]; + surf->cached_light[2] = d_lightstylevalue[surf->styles[2]]; + surf->cached_light[3] = d_lightstylevalue[surf->styles[3]]; smax = (surf->extents[0]>>4)+1; tmax = (surf->extents[1]>>4)+1; @@ -252,10 +255,10 @@ void R_BuildLightMap (msurface_t *surf, byte *dest, int stride) lightmap = surf->samples; // set to full bright if no light data - if ((currententity && (currententity->render.effects & EF_FULLBRIGHT)) || !cl.worldmodel->lightdata) + if ((currentrenderentity->effects & EF_FULLBRIGHT) || !cl.worldmodel->lightdata) { bl = blocklights; - for (i=0 ; idlightframe == r_framecount) + { + if ((surf->cached_dlight = R_AddDynamicLights(surf))) + c_light_polys++; + else if (dlightchanged) + return; // don't upload if only updating dlights and none mattered + } + // add all the lightmaps if (lightmap) - { for (maps = 0;maps < MAXLIGHTMAPS && surf->styles[maps] != 255;maps++) - { - scale = d_lightstylevalue[surf->styles[maps]]; - surf->cached_light[maps] = scale; // 8.8 fraction - bl = blocklights; - for (i = 0;i < size3;i++) + for (scale = d_lightstylevalue[surf->styles[maps]], bl = blocklights, i = 0;i < size3;i++) *bl++ += *lightmap++ * scale; - } - } - if (r_dlightmap.value && surf->dlightframe == r_framecount) - if ((surf->cached_dlight = R_AddDynamicLights(surf))) - c_light_polys++; } + R_ConvertLightmap(blocklights, dest, smax, tmax, stride); } -byte templight[BLOCK_WIDTH*BLOCK_HEIGHT*4]; - -void R_UpdateLightmap(msurface_t *s, int lnum) +void R_UpdateLightmap(msurface_t *s, int lnum, int dlightschanged) { int smax, tmax; // upload the new lightmap texture fragment @@ -309,9 +309,9 @@ void R_UpdateLightmap(msurface_t *s, int lnum) if (lightmapupdate[lnum][1] < (s->light_t + ((s->extents[1]>>4)+1))) lightmapupdate[lnum][1] = (s->light_t + ((s->extents[1]>>4)+1)); if (lightmaprgba) - R_BuildLightMap (s, lightmaps[s->lightmaptexturenum] + (s->light_t * BLOCK_WIDTH + s->light_s) * 4, BLOCK_WIDTH * 4); + R_BuildLightMap (s, lightmaps[s->lightmaptexturenum] + (s->light_t * BLOCK_WIDTH + s->light_s) * 4, BLOCK_WIDTH * 4, false); else - R_BuildLightMap (s, lightmaps[s->lightmaptexturenum] + (s->light_t * BLOCK_WIDTH + s->light_s) * 3, BLOCK_WIDTH * 3); + R_BuildLightMap (s, lightmaps[s->lightmaptexturenum] + (s->light_t * BLOCK_WIDTH + s->light_s) * 3, BLOCK_WIDTH * 3, false); } else { @@ -319,13 +319,13 @@ void R_UpdateLightmap(msurface_t *s, int lnum) tmax = (s->extents[1]>>4)+1; if (lightmaprgba) { - R_BuildLightMap (s, templight, smax * 4); + R_BuildLightMap (s, templight, smax * 4, false); if(r_upload.value) glTexSubImage2D(GL_TEXTURE_2D, 0, s->light_s, s->light_t, smax, tmax, GL_RGBA, GL_UNSIGNED_BYTE, templight); } else { - R_BuildLightMap (s, templight, smax * 3); + R_BuildLightMap (s, templight, smax * 3, false); if(r_upload.value) glTexSubImage2D(GL_TEXTURE_2D, 0, s->light_s, s->light_t, smax, tmax, GL_RGB , GL_UNSIGNED_BYTE, templight); } @@ -342,44 +342,13 @@ Returns the proper texture for a given time and base texture */ texture_t *R_TextureAnimation (texture_t *base) { -// texture_t *original; -// int relative; -// int count; + if (currentrenderentity->frame && base->alternate_anims != NULL) + base = base->alternate_anims; - if (currententity->render.frame) - { - if (base->alternate_anims) - base = base->alternate_anims; - } - - if (!base->anim_total) + if (base->anim_total < 2) return base; - return base->anim_frames[(int)(cl.time*5) % base->anim_total]; - - /* - original = base; - - relative = (int)(cl.time*5) % base->anim_total; - - count = 0; - while (base->anim_min > relative || base->anim_max <= relative) - { - base = base->anim_next; - if (!base) - { - Con_Printf("R_TextureAnimation: broken cycle"); - return original; - } - if (++count > 100) - { - Con_Printf("R_TextureAnimation: infinite cycle"); - return original; - } - } - - return base; - */ + return base->anim_frames[(int)(cl.time * 5.0f) % base->anim_total]; } @@ -625,24 +594,26 @@ void RSurf_DrawWall(msurface_t *s, texture_t *t, int transform) wallvertcolor_t *outcolor; // check for lightmap modification if (s->cached_dlight - || (r_dynamic.value && r_dlightmap.value && s->dlightframe == r_framecount) || r_ambient.value != s->cached_ambient || lightscalebit != s->cached_lightscalebit || (r_dynamic.value - && ((s->styles[0] != 255 && d_lightstylevalue[s->styles[0]] != s->cached_light[0]) - || (s->styles[1] != 255 && d_lightstylevalue[s->styles[1]] != s->cached_light[1]) - || (s->styles[2] != 255 && d_lightstylevalue[s->styles[2]] != s->cached_light[2]) - || (s->styles[3] != 255 && d_lightstylevalue[s->styles[3]] != s->cached_light[3])))) - R_UpdateLightmap(s, s->lightmaptexturenum); + && (d_lightstylevalue[s->styles[0]] != s->cached_light[0] + || d_lightstylevalue[s->styles[1]] != s->cached_light[1] + || d_lightstylevalue[s->styles[2]] != s->cached_light[2] + || d_lightstylevalue[s->styles[3]] != s->cached_light[3]))) + R_UpdateLightmap(s, s->lightmaptexturenum, false); // base lighting changed + else if (r_dynamic.value && r_dlightmap.value && s->dlightframe == r_framecount) + R_UpdateLightmap(s, s->lightmaptexturenum, true); // only dlights + if (s->dlightframe != r_framecount || r_dlightmap.value) { // LordHavoc: fast path version for no vertex lighting cases - wp = &wallpoly[currentwallpoly]; out = &wallvert[currentwallvert]; for (p = s->polys;p;p = p->next) { if ((currentwallpoly >= MAX_WALLPOLYS) || (currentwallvert+p->numverts > MAX_WALLVERTS)) return; + wp = &wallpoly[currentwallpoly++]; wp->texnum = (unsigned short) R_GetTexture(t->texture); wp->lighttexnum = (unsigned short) (lightmap_textures + s->lightmaptexturenum); wp->glowtexnum = (unsigned short) R_GetTexture(t->glowtexture); @@ -650,7 +621,6 @@ void RSurf_DrawWall(msurface_t *s, texture_t *t, int transform) wp->numverts = p->numverts; wp->lit = false; wp++; - currentwallpoly++; currentwallvert += p->numverts; v = p->verts[0]; if (transform) @@ -757,7 +727,7 @@ void RSurf_DrawWallVertex(msurface_t *s, texture_t *t, int transform, int isbmod float *v, *wv, scale; glpoly_t *p; byte *lm; - alpha = (int) (modelalpha * 255.0f); + alpha = (int) (currentrenderentity->alpha * 255.0f); size3 = ((s->extents[0]>>4)+1)*((s->extents[1]>>4)+1)*3; // *3 for colored lighting wv = wvert; for (p = s->polys;p;p = p->next) @@ -792,14 +762,14 @@ void RSurf_DrawWallVertex(msurface_t *s, texture_t *t, int transform, int isbmod if (s->dlightframe == r_framecount) RSurf_Light(s->dlightbits, s->polys); wv = wvert; - if (isbmodel && (currententity->render.colormod[0] != 1 || currententity->render.colormod[1] != 1 || currententity->render.colormod[2] != 1)) + if (alpha != 255 || currentrenderentity->colormod[0] != 1 || currentrenderentity->colormod[1] != 1 || currentrenderentity->colormod[2] != 1) { for (p = s->polys;p;p = p->next) { v = p->verts[0]; - transpolybegin(R_GetTexture(t->texture), R_GetTexture(t->glowtexture), 0, currententity->render.effects & EF_ADDITIVE ? TPOLYTYPE_ADD : TPOLYTYPE_ALPHA); + transpolybegin(R_GetTexture(t->texture), R_GetTexture(t->glowtexture), 0, currentrenderentity->effects & EF_ADDITIVE ? TPOLYTYPE_ADD : TPOLYTYPE_ALPHA); for (i = 0,v = p->verts[0];i < p->numverts;i++, v += VERTEXSIZE, wv += 6) - transpolyvert(wv[0], wv[1], wv[2], v[3], v[4], wv[3] * currententity->render.colormod[0], wv[4] * currententity->render.colormod[1], wv[5] * currententity->render.colormod[2], alpha); + transpolyvert(wv[0], wv[1], wv[2], v[3], v[4], wv[3] * currentrenderentity->colormod[0], wv[4] * currentrenderentity->colormod[1], wv[5] * currentrenderentity->colormod[2], alpha); transpolyend(); } } @@ -808,7 +778,7 @@ void RSurf_DrawWallVertex(msurface_t *s, texture_t *t, int transform, int isbmod for (p = s->polys;p;p = p->next) { v = p->verts[0]; - transpolybegin(R_GetTexture(t->texture), R_GetTexture(t->glowtexture), 0, currententity->render.effects & EF_ADDITIVE ? TPOLYTYPE_ADD : TPOLYTYPE_ALPHA); + transpolybegin(R_GetTexture(t->texture), R_GetTexture(t->glowtexture), 0, currentrenderentity->effects & EF_ADDITIVE ? TPOLYTYPE_ADD : TPOLYTYPE_ALPHA); for (i = 0,v = p->verts[0];i < p->numverts;i++, v += VERTEXSIZE, wv += 6) transpolyvert(wv[0], wv[1], wv[2], v[3], v[4], wv[3], wv[4], wv[5], alpha); transpolyend(); @@ -822,6 +792,7 @@ float bmverts[256*3]; int vertexworld; +// LordHavoc: disabled clipping on bmodels because they tend to intersect things sometimes /* void RBrushModelSurf_DoVisible(msurface_t *surf) { @@ -837,12 +808,14 @@ void RBrushModelSurf_DoVisible(msurface_t *surf) } */ +/* void RBrushModelSurf_Callback(void *data, void *data2) { - entity_t *ent = data2; msurface_t *surf = data; texture_t *t; + currentrenderentity = data2; +*/ /* // FIXME: implement better dupe prevention in AddPolygon callback code if (ent->render.model->firstmodelsurface != 0) @@ -852,14 +825,12 @@ void RBrushModelSurf_Callback(void *data, void *data2) return; } */ +/* surf->visframe = r_framecount; c_faces++; - currententity = ent; - modelalpha = ent->render.alpha; - - softwaretransformforbrushentity (ent); + softwaretransformforbrushentity (currentrenderentity); if (surf->flags & (SURF_DRAWSKY | SURF_DRAWTURB)) { @@ -872,69 +843,52 @@ void RBrushModelSurf_Callback(void *data, void *data2) else { t = R_TextureAnimation(surf->texinfo->texture); - if (surf->texinfo->texture->transparent || vertexworld || ent->render.alpha != 1 || ent->render.model->firstmodelsurface == 0 || (ent->render.effects & EF_FULLBRIGHT) || ent->render.colormod[0] != 1 || ent->render.colormod[2] != 1 || ent->render.colormod[2] != 1) + if (t->transparent || vertexworld || ent->render.alpha != 1 || ent->render.model->firstmodelsurface == 0 || (ent->render.effects & EF_FULLBRIGHT) || ent->render.colormod[0] != 1 || ent->render.colormod[2] != 1 || ent->render.colormod[2] != 1) RSurf_DrawWallVertex(surf, t, true, true); else RSurf_DrawWall(surf, t, true); } } +*/ /* ================= R_DrawBrushModel ================= */ -void R_DrawBrushModel (entity_t *e) +void R_DrawBrushModel (void) { - int i, j, vertexlit; - vec3_t mins, maxs; + int i/*, j*/, vertexlit, rotated, transform; msurface_t *s; - model_t *clmodel; - int rotated; - vec3_t org; - glpoly_t *p; - - currententity = e; - - clmodel = e->render.model; - - if (e->render.angles[0] || e->render.angles[1] || e->render.angles[2]) - { - rotated = true; - for (i=0 ; i<3 ; i++) - { - mins[i] = e->render.origin[i] - clmodel->radius; - maxs[i] = e->render.origin[i] + clmodel->radius; - } - } - else - { - rotated = false; - VectorAdd (e->render.origin, clmodel->mins, mins); - VectorAdd (e->render.origin, clmodel->maxs, maxs); - } + model_t *model; + vec3_t org, temp, forward, right, up; +// glpoly_t *p; + texture_t *t; - if (R_CullBox (mins, maxs)) - return; + model = currentrenderentity->model; c_bmodels++; - VectorSubtract (r_origin, e->render.origin, modelorg); - if (rotated) + VectorSubtract (r_origin, currentrenderentity->origin, modelorg); + rotated = false; + transform = false; + if (currentrenderentity->angles[0] || currentrenderentity->angles[1] || currentrenderentity->angles[2]) { - vec3_t temp; - vec3_t forward, right, up; - + transform = true; + rotated = true; VectorCopy (modelorg, temp); - AngleVectors (e->render.angles, forward, right, up); + AngleVectors (currentrenderentity->angles, forward, right, up); modelorg[0] = DotProduct (temp, forward); modelorg[1] = -DotProduct (temp, right); modelorg[2] = DotProduct (temp, up); } + else if (currentrenderentity->origin[0] || currentrenderentity->origin[1] || currentrenderentity->origin[2] || currentrenderentity->scale) + transform = true; - softwaretransformforbrushentity (e); + if (transform) + softwaretransformforbrushentity (currentrenderentity); - for (i = 0, s = &clmodel->surfaces[clmodel->firstmodelsurface];i < clmodel->nummodelsurfaces;i++, s++) + for (i = 0, s = &model->surfaces[model->firstmodelsurface];i < model->nummodelsurfaces;i++, s++) { s->visframe = -1; if (((s->flags & SURF_PLANEBACK) == 0) == (PlaneDiff(modelorg, s->plane) >= 0)) @@ -947,45 +901,56 @@ void R_DrawBrushModel (entity_t *e) if (!cl_dlights[i].radius) continue; - VectorSubtract(cl_dlights[i].origin, currententity->render.origin, org); - R_NoVisMarkLights (org, &cl_dlights[i], 1<<(i&31), i >> 5, clmodel); + if (rotated) + { + VectorSubtract(cl_dlights[i].origin, currentrenderentity->origin, temp); + org[0] = DotProduct (temp, forward); + org[1] = -DotProduct (temp, right); + org[2] = DotProduct (temp, up); + } + else + VectorSubtract(cl_dlights[i].origin, currentrenderentity->origin, org); + R_NoVisMarkLights (org, &cl_dlights[i], 1<<(i&31), i >> 5, model); } - vertexlit = modelalpha != 1 || clmodel->firstmodelsurface == 0 || (currententity->render.effects & EF_FULLBRIGHT) || currententity->render.colormod[0] != 1 || currententity->render.colormod[2] != 1 || currententity->render.colormod[2] != 1; + vertexlit = vertexworld || currentrenderentity->alpha != 1 || model->firstmodelsurface == 0 || (currentrenderentity->effects & EF_FULLBRIGHT) || currentrenderentity->colormod[0] != 1 || currentrenderentity->colormod[2] != 1 || currentrenderentity->colormod[2] != 1; // draw texture - for (i = 0, s = &clmodel->surfaces[clmodel->firstmodelsurface];i < clmodel->nummodelsurfaces;i++, s++) + for (i = 0, s = &model->surfaces[model->firstmodelsurface];i < model->nummodelsurfaces;i++, s++) { if (s->visframe == r_framecount) { // R_DrawSurf(s, true, vertexlit || s->texinfo->texture->transparent); + /* if (r_ser.value) { for (p = s->polys;p;p = p->next) { for (j = 0;j < p->numverts;j++) softwaretransform(&p->verts[j][0], bmverts + j * 3); - R_Clip_AddPolygon(bmverts, p->numverts, 3 * sizeof(float), (s->flags & SURF_CLIPSOLID) != 0 && modelalpha == 1, RBrushModelSurf_Callback, s, e, NULL); + R_Clip_AddPolygon(bmverts, p->numverts, 3 * sizeof(float), (s->flags & SURF_CLIPSOLID) != 0 && currentrenderentity->alpha == 1, RBrushModelSurf_Callback, s, e, NULL); } } else { + */ + c_faces++; + t = R_TextureAnimation(s->texinfo->texture); if (s->flags & (SURF_DRAWSKY | SURF_DRAWTURB)) { // sky and liquid don't need sorting (skypoly/transpoly) if (s->flags & SURF_DRAWSKY) - RSurf_DrawSky(s, true); + RSurf_DrawSky(s, transform); else - RSurf_DrawWater(s, R_TextureAnimation(s->texinfo->texture), true, s->flags & SURF_DRAWNOALPHA ? 255 : wateralpha); + RSurf_DrawWater(s, t, transform, s->flags & SURF_DRAWNOALPHA ? 255 : wateralpha); } else { - texture_t *t = R_TextureAnimation(s->texinfo->texture); - if (vertexlit || s->texinfo->texture->transparent) - RSurf_DrawWallVertex(s, t, true, true); + if (t->transparent || vertexlit) + RSurf_DrawWallVertex(s, t, transform, true); else - RSurf_DrawWall(s, t, true); + RSurf_DrawWall(s, t, transform); } - } + //} } } UploadLightmaps(); @@ -1138,7 +1103,7 @@ void R_MarkLeaves (void) void R_SolidWorldNode (void) { - if ((int) r_solidworldnode.value == 3) + if (r_viewleaf->contents != CONTENTS_SOLID) { int portalstack; mportal_t *p, *pstack[8192]; @@ -1146,6 +1111,10 @@ void R_SolidWorldNode (void) mleaf_t *leaf; glpoly_t *poly; tinyplane_t plane; + // LordHavoc: portal-passage worldnode; follows portals leading + // outward from viewleaf, if a portal leads offscreen it is not + // followed, in indoor maps this can often cull a great deal of + // geometry away when pvs data is not present (useful with pvs as well) leaf = r_viewleaf; leaf->worldnodeframe = r_framecount; @@ -1239,18 +1208,22 @@ void R_SolidWorldNode (void) if (portalstack) goto loc1; } - else if ((int) r_solidworldnode.value == 2) + else { mnode_t *nodestack[8192], *node = cl.worldmodel->nodes; int nodestackpos = 0; glpoly_t *poly; + // LordHavoc: recursive descending worldnode; if portals are not + // available, this is a good last resort, can cull large amounts of + // geometry, but is more time consuming than portal-passage and renders + // things behind walls loc2: if (R_NotCulledBox(node->mins, node->maxs)) { - if (r_ser.value) + if (node->numsurfaces) { - if (node->numsurfaces) + if (r_ser.value) { msurface_t *surf = cl.worldmodel->surfaces + node->firstsurface, *surfend = surf + node->numsurfaces; tinyplane_t plane; @@ -1277,10 +1250,7 @@ loc2: } } } - } - else - { - if (node->numsurfaces) + else { msurface_t *surf = cl.worldmodel->surfaces + node->firstsurface, *surfend = surf + node->numsurfaces; if (PlaneDiff (r_origin, node->plane) < 0) @@ -1339,111 +1309,6 @@ loc2: goto loc2; } } - else if ((int) r_solidworldnode.value == 1 && r_ser.value) - { - glpoly_t *poly; - msurface_t *surf, *endsurf; - tinyplane_t plane; - - surf = &cl.worldmodel->surfaces[cl.worldmodel->firstmodelsurface]; - endsurf = surf + cl.worldmodel->nummodelsurfaces; - for (;surf < endsurf;surf++) - { - if (PlaneDiff(r_origin, surf->plane) < 0) - { - if (surf->flags & SURF_PLANEBACK) - { - VectorNegate(surf->plane->normal, plane.normal); - plane.dist = -surf->plane->dist; - for (poly = surf->polys;poly;poly = poly->next) - R_Clip_AddPolygon((float *)poly->verts, poly->numverts, VERTEXSIZE * sizeof(float), (surf->flags & SURF_CLIPSOLID) != 0, RSurf_Callback, surf, NULL, &plane); - } - } - else - { - if (!(surf->flags & SURF_PLANEBACK)) - for (poly = surf->polys;poly;poly = poly->next) - R_Clip_AddPolygon((float *)poly->verts, poly->numverts, VERTEXSIZE * sizeof(float), (surf->flags & SURF_CLIPSOLID) != 0, RSurf_Callback, surf, NULL, (tinyplane_t *)&surf->plane); - } - } - } - else - { - int l; - mleaf_t *leaf; - msurface_t *surf, **mark, **endmark; - glpoly_t *poly; - tinyplane_t plane; - - for (l = 0, leaf = cl.worldmodel->leafs;l < cl.worldmodel->numleafs;l++, leaf++) - { - if (R_CullBox(leaf->mins, leaf->maxs)) - continue; - leaf->visframe = r_framecount; - c_leafs++; - if (leaf->nummarksurfaces) - { -// if (R_CullBox(leaf->mins, leaf->maxs)) -// continue; - - if (leaf->nummarksurfaces) - { - mark = leaf->firstmarksurface; - endmark = mark + leaf->nummarksurfaces; - if (r_ser.value) - { - do - { - surf = *mark++; - // make sure surfaces are only processed once - if (surf->worldnodeframe == r_framecount) - continue; - surf->worldnodeframe = r_framecount; - if (PlaneDist(r_origin, surf->plane) < surf->plane->dist) - { - if (surf->flags & SURF_PLANEBACK) - { - VectorNegate(surf->plane->normal, plane.normal); - plane.dist = -surf->plane->dist; - for (poly = surf->polys;poly;poly = poly->next) - R_Clip_AddPolygon((float *)poly->verts, poly->numverts, VERTEXSIZE * sizeof(float), (surf->flags & SURF_CLIPSOLID) != 0, RSurf_Callback, surf, NULL, &plane); - } - } - else - { - if (!(surf->flags & SURF_PLANEBACK)) - for (poly = surf->polys;poly;poly = poly->next) - R_Clip_AddPolygon((float *)poly->verts, poly->numverts, VERTEXSIZE * sizeof(float), (surf->flags & SURF_CLIPSOLID) != 0, RSurf_Callback, surf, NULL, (tinyplane_t *)surf->plane); - } - } - while (mark < endmark); - } - else - { - do - { - surf = *mark++; - // make sure surfaces are only processed once - if (surf->worldnodeframe == r_framecount) - continue; - surf->worldnodeframe = r_framecount; - if (PlaneDist(r_origin, surf->plane) < surf->plane->dist) - { - if (surf->flags & SURF_PLANEBACK) - surf->visframe = r_framecount; - } - else - { - if (!(surf->flags & SURF_PLANEBACK)) - surf->visframe = r_framecount; - } - } - while (mark < endmark); - } - } - } - } - } } /* @@ -1629,220 +1494,111 @@ void R_Portal_Callback(void *data, void *data2) void R_PVSWorldNode() { - if (r_pvsworldnode.value == 1) - { - int portalstack, i; - mportal_t *p, *pstack[8192]; - msurface_t *surf, **mark, **endmark; - mleaf_t *leaf; - tinyplane_t plane; - glpoly_t *poly; - byte *worldvis; + int portalstack, i; + mportal_t *p, *pstack[8192]; + msurface_t *surf, **mark, **endmark; + mleaf_t *leaf; + tinyplane_t plane; + glpoly_t *poly; + byte *worldvis; - worldvis = Mod_LeafPVS (r_viewleaf, cl.worldmodel); + worldvis = Mod_LeafPVS (r_viewleaf, cl.worldmodel); - leaf = r_viewleaf; - leaf->worldnodeframe = r_framecount; - portalstack = 0; - loc0: - c_leafs++; + leaf = r_viewleaf; + leaf->worldnodeframe = r_framecount; + portalstack = 0; +loc0: + c_leafs++; - leaf->visframe = r_framecount; + leaf->visframe = r_framecount; - if (leaf->nummarksurfaces) + if (leaf->nummarksurfaces) + { + mark = leaf->firstmarksurface; + endmark = mark + leaf->nummarksurfaces; + if (r_ser.value) { - mark = leaf->firstmarksurface; - endmark = mark + leaf->nummarksurfaces; - if (r_ser.value) + do { - do + surf = *mark++; + // make sure surfaces are only processed once + if (surf->worldnodeframe == r_framecount) + continue; + surf->worldnodeframe = r_framecount; + if (PlaneDist(modelorg, surf->plane) < surf->plane->dist) { - surf = *mark++; - // make sure surfaces are only processed once - if (surf->worldnodeframe == r_framecount) - continue; - surf->worldnodeframe = r_framecount; - if (PlaneDist(modelorg, surf->plane) < surf->plane->dist) - { - if (surf->flags & SURF_PLANEBACK) - { - VectorNegate(surf->plane->normal, plane.normal); - plane.dist = -surf->plane->dist; - for (poly = surf->polys;poly;poly = poly->next) - R_Clip_AddPolygon((float *)poly->verts, poly->numverts, VERTEXSIZE * sizeof(float), (surf->flags & SURF_CLIPSOLID) != 0, RSurf_Callback, surf, NULL, &plane); - } - } - else + if (surf->flags & SURF_PLANEBACK) { - if (!(surf->flags & SURF_PLANEBACK)) - for (poly = surf->polys;poly;poly = poly->next) - R_Clip_AddPolygon((float *)poly->verts, poly->numverts, VERTEXSIZE * sizeof(float), (surf->flags & SURF_CLIPSOLID) != 0, RSurf_Callback, surf, NULL, (tinyplane_t *)surf->plane); + VectorNegate(surf->plane->normal, plane.normal); + plane.dist = -surf->plane->dist; + for (poly = surf->polys;poly;poly = poly->next) + R_Clip_AddPolygon((float *)poly->verts, poly->numverts, VERTEXSIZE * sizeof(float), (surf->flags & SURF_CLIPSOLID) != 0, RSurf_Callback, surf, NULL, &plane); } } - while (mark < endmark); - } - else - { - do + else { - surf = *mark++; - // make sure surfaces are only processed once - if (surf->worldnodeframe == r_framecount) - continue; - surf->worldnodeframe = r_framecount; - if (PlaneDist(modelorg, surf->plane) < surf->plane->dist) - { - if (surf->flags & SURF_PLANEBACK) - surf->visframe = r_framecount; - } - else - { - if (!(surf->flags & SURF_PLANEBACK)) - surf->visframe = r_framecount; - } + if (!(surf->flags & SURF_PLANEBACK)) + for (poly = surf->polys;poly;poly = poly->next) + R_Clip_AddPolygon((float *)poly->verts, poly->numverts, VERTEXSIZE * sizeof(float), (surf->flags & SURF_CLIPSOLID) != 0, RSurf_Callback, surf, NULL, (tinyplane_t *)surf->plane); } - while (mark < endmark); } + while (mark < endmark); } - - // follow portals into other leafs - p = leaf->portals; - for (;p;p = p->next) + else { - if (DotProduct(r_origin, p->plane.normal) < p->plane.dist) + do { - leaf = p->past; - if (leaf->worldnodeframe != r_framecount) + surf = *mark++; + // make sure surfaces are only processed once + if (surf->worldnodeframe == r_framecount) + continue; + surf->worldnodeframe = r_framecount; + if (PlaneDist(modelorg, surf->plane) < surf->plane->dist) { - leaf->worldnodeframe = r_framecount; - if (leaf->contents != CONTENTS_SOLID) - { - i = (leaf - cl.worldmodel->leafs) - 1; - if (worldvis[i>>3] & (1<<(i&7))) - { - if (R_NotCulledBox(leaf->mins, leaf->maxs)) - { - pstack[portalstack++] = p; - goto loc0; - - loc1: - p = pstack[--portalstack]; - } - } - } + if (surf->flags & SURF_PLANEBACK) + surf->visframe = r_framecount; + } + else + { + if (!(surf->flags & SURF_PLANEBACK)) + surf->visframe = r_framecount; } } + while (mark < endmark); } - - if (portalstack) - goto loc1; } - else - { - int i/*, l*/, k, c, row, numbits, bit, leafnum, numleafs; - mleaf_t *leaf; - msurface_t *surf, **mark, **endmark; - model_t *model = cl.worldmodel; - byte *in; - // mportal_t *portal; - glpoly_t *poly; - tinyplane_t plane; - - // c_leafs++; - // r_viewleaf->visframe = r_framecount; - if (!r_testvis.value) - r_portalframecount++; - numleafs = model->numleafs; - numbits = numleafs; - k = 0; - in = r_viewleaf->compressed_vis; - row = (numbits + 7) >> 3; - while (k < row) + // follow portals into other leafs + p = leaf->portals; + for (;p;p = p->next) + { + if (DotProduct(r_origin, p->plane.normal) < p->plane.dist) { - c = *in++; - if (c) + leaf = p->past; + if (leaf->worldnodeframe != r_framecount) { - for (i = 0, bit = 1;c;i++, bit <<= 1) + leaf->worldnodeframe = r_framecount; + if (leaf->contents != CONTENTS_SOLID) { - if (c & bit) + i = (leaf - cl.worldmodel->leafs) - 1; + if (worldvis[i>>3] & (1<<(i&7))) { - leafnum = (k << 3)+i+1; - if (leafnum > numleafs) - return; - c -= bit; - leaf = &model->leafs[leafnum]; if (R_NotCulledBox(leaf->mins, leaf->maxs)) { - //for (portal = leaf->portals;portal;portal = portal->next) - // if (DotProduct(r_origin, portal->plane.normal) > portal->plane.dist) - // R_Clip_AddPolygon((float *)portal->points, portal->numpoints, sizeof(mvertex_t), false, R_Portal_Callback, leaf, portal, portal->plane); - //leaf->visframe = r_framecount; - c_leafs++; - if (leaf->nummarksurfaces) - { - mark = leaf->firstmarksurface; - endmark = mark + leaf->nummarksurfaces; - if (r_ser.value) - { - do - { - surf = *mark++; - // make sure surfaces are only processed once - if (surf->worldnodeframe == r_framecount) - continue; - surf->worldnodeframe = r_framecount; - if (PlaneDist(r_origin, surf->plane) < surf->plane->dist) - { - if (surf->flags & SURF_PLANEBACK) - { - VectorNegate(surf->plane->normal, plane.normal); - plane.dist = -surf->plane->dist; - for (poly = surf->polys;poly;poly = poly->next) - R_Clip_AddPolygon((float *)poly->verts, poly->numverts, VERTEXSIZE * sizeof(float), (surf->flags & SURF_CLIPSOLID) != 0, RSurf_Callback, surf, NULL, &plane); - } - } - else - { - if (!(surf->flags & SURF_PLANEBACK)) - for (poly = surf->polys;poly;poly = poly->next) - R_Clip_AddPolygon((float *)poly->verts, poly->numverts, VERTEXSIZE * sizeof(float), (surf->flags & SURF_CLIPSOLID) != 0, RSurf_Callback, surf, NULL, (tinyplane_t *)surf->plane); - } - } - while (mark < endmark); - } - else - { - do - { - surf = *mark++; - // make sure surfaces are only processed once - if (surf->worldnodeframe == r_framecount) - continue; - surf->worldnodeframe = r_framecount; - if (PlaneDist(r_origin, surf->plane) < surf->plane->dist) - { - if (surf->flags & SURF_PLANEBACK) - surf->visframe = r_framecount; - } - else - { - if (!(surf->flags & SURF_PLANEBACK)) - surf->visframe = r_framecount; - } - } - while (mark < endmark); - } - } + pstack[portalstack++] = p; + goto loc0; + +loc1: + p = pstack[--portalstack]; } } } - k++; } - else - k += *in++; } } + + if (portalstack) + goto loc1; } entity_t clworldent; @@ -1853,8 +1609,7 @@ void R_DrawSurfaces (void) texture_t *t, *currentt; int vertex = gl_vertex.value; - currententity = &clworldent; - modelalpha = 1; + currentrenderentity = &clworldent.render; softwaretransformidentity(); surf = &cl.worldmodel->surfaces[cl.worldmodel->firstmodelsurface]; endsurf = surf + cl.worldmodel->nummodelsurfaces; @@ -1955,6 +1710,19 @@ void R_DrawPortals(void) } } +void R_SetupWorldEnt(void) +{ + memset (&clworldent, 0, sizeof(clworldent)); + clworldent.render.model = cl.worldmodel; + clworldent.render.colormod[0] = clworldent.render.colormod[1] = clworldent.render.colormod[2] = 1; + clworldent.render.alpha = 1; + clworldent.render.scale = 1; + + VectorCopy (r_origin, modelorg); + + currentrenderentity = &clworldent.render; +} + /* ============= R_DrawWorld @@ -1965,28 +1733,14 @@ void R_DrawWorld (void) wateralpha = bound(0, r_wateralpha.value*255.0f, 255); vertexworld = gl_vertex.value; - memset (&clworldent, 0, sizeof(clworldent)); - clworldent.render.model = cl.worldmodel; - clworldent.render.colormod[0] = clworldent.render.colormod[1] = clworldent.render.colormod[2] = 1; - modelalpha = clworldent.render.alpha = 1; - clworldent.render.scale = 1; - - VectorCopy (r_origin, modelorg); - - currententity = &clworldent; + R_SetupWorldEnt(); softwaretransformidentity(); // LordHavoc: clear transform - if (cl.worldmodel) - { - if (r_novis.value || r_viewleaf->compressed_vis == NULL) - R_SolidWorldNode (); - else - { -// R_MarkLeaves (); - R_PVSWorldNode (); - } - } + if (r_viewleaf->contents == CONTENTS_SOLID || r_novis.value || r_viewleaf->compressed_vis == NULL) + R_SolidWorldNode (); + else + R_PVSWorldNode (); } /* @@ -2008,7 +1762,7 @@ int AllocBlock (int w, int h, short *x, short *y) { best = BLOCK_HEIGHT; - for (i = 0;i < BLOCK_WIDTH - w;i += lightmapalign) // LordHavoc: NVIDIA has broken subimage, so align the lightmaps + for (i = 0;i < BLOCK_WIDTH - w;i += lightmapalign) // LordHavoc: align updates on 4 byte boundaries { best2 = 0; @@ -2040,17 +1794,16 @@ int AllocBlock (int w, int h, short *x, short *y) // LordHavoc: clear texture to blank image, fragments are uploaded using subimage else if (!allocated[texnum][0]) { - byte blank[BLOCK_WIDTH*BLOCK_HEIGHT*4]; - memset(blank, 0, sizeof(blank)); + memset(templight, 0, sizeof(templight)); if(r_upload.value) { glBindTexture(GL_TEXTURE_2D, lightmap_textures + texnum); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); if (lightmaprgba) - glTexImage2D (GL_TEXTURE_2D, 0, 3, BLOCK_WIDTH, BLOCK_HEIGHT, 0, GL_RGBA, GL_UNSIGNED_BYTE, blank); + glTexImage2D (GL_TEXTURE_2D, 0, 3, BLOCK_WIDTH, BLOCK_HEIGHT, 0, GL_RGBA, GL_UNSIGNED_BYTE, templight); else - glTexImage2D (GL_TEXTURE_2D, 0, 3, BLOCK_WIDTH, BLOCK_HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, blank); + glTexImage2D (GL_TEXTURE_2D, 0, 3, BLOCK_WIDTH, BLOCK_HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, templight); } } @@ -2195,13 +1948,13 @@ void GL_CreateSurfaceLightmap (msurface_t *surf) smax = ((surf->extents[0]>>4)+lightmapalign) & lightmapalignmask; if (lightmaprgba) { - R_BuildLightMap (surf, templight, smax * 4); + R_BuildLightMap (surf, templight, smax * 4, false); if(r_upload.value) glTexSubImage2D(GL_TEXTURE_2D, 0, surf->light_s, surf->light_t, smax, tmax, GL_RGBA, GL_UNSIGNED_BYTE, templight); } else { - R_BuildLightMap (surf, templight, smax * 3); + R_BuildLightMap (surf, templight, smax * 3, false); if(r_upload.value) glTexSubImage2D(GL_TEXTURE_2D, 0, surf->light_s, surf->light_t, smax, tmax, GL_RGB , GL_UNSIGNED_BYTE, templight); } @@ -2246,18 +1999,24 @@ void GL_BuildLightmaps (void) lightmapbytes = 3; } - // LordHavoc: NVIDIA seems to have a broken glTexSubImage2D, - // it needs to be aligned on 4 pixel boundaries... - // so I implemented an adjustable lightmap alignment - if (gl_lightmapalign.value < 1) - gl_lightmapalign.value = 1; - if (gl_lightmapalign.value > 16) - gl_lightmapalign.value = 16; + // LordHavoc: TexSubImage2D needs data aligned on 4 byte boundaries unless + // I specify glPixelStorei(GL_UNPACK_ALIGNMENT, 1), I suspect 4 byte may be + // faster anyway, so I implemented an adjustable lightmap alignment... + + // validate the lightmap alignment + i = 1; + while (i < 16 && i < gl_lightmapalign.value) + i <<= 1; + Cvar_SetValue("gl_lightmapalign", i); + + // find the lowest pixel count which satisfies the byte alignment lightmapalign = 1; - while (lightmapalign < gl_lightmapalign.value) + j = lightmaprgba ? 4 : 3; // bytes per pixel + while ((lightmapalign * j) & (i - 1)) lightmapalign <<= 1; - gl_lightmapalign.value = lightmapalign; lightmapalignmask = ~(lightmapalign - 1); + + // alignment is irrelevant if using fallback modes if (nosubimagefragments || nosubimage) { lightmapalign = 1; @@ -2267,6 +2026,9 @@ void GL_BuildLightmaps (void) if (!lightmap_textures) lightmap_textures = R_GetTextureSlots(MAX_LIGHTMAPS); + // need a world entity for lightmap code + R_SetupWorldEnt(); + for (j=1 ; j 0) { @@ -229,19 +227,8 @@ CalcFov */ float CalcFov (float fov_x, float width, float height) { - float a; - float x; - - if (fov_x < 1 || fov_x > 179) - Sys_Error ("Bad fov: %f", fov_x); - - x = width/tan(fov_x/360*M_PI); - - a = atan (height/x); - - a = a*360/M_PI; - - return a; + // calculate vision size and alter by aspect, then convert back to angle + return atan (height / (width / tan(fov_x/360*M_PI))) * 360 / M_PI; } /* @@ -254,15 +241,12 @@ Internal use only */ static void SCR_CalcRefdef (void) { - float size; - int h; - qboolean full = false; - + float size; - vid.recalc_refdef = 0; +// vid.recalc_refdef = 0; //======================================== - + // bound viewsize if (scr_viewsize.value < 30) Cvar_Set ("viewsize","30"); @@ -278,7 +262,6 @@ static void SCR_CalcRefdef (void) // intermission is always full screen if (cl.intermission) { - full = true; size = 1; sb_lines = 0; } @@ -290,39 +273,31 @@ static void SCR_CalcRefdef (void) sb_lines = 24; // no inventory else sb_lines = 24+16+8; - - if (scr_viewsize.value >= 100.0) - { - full = true; - size = 1.0f; - } - else - size = scr_viewsize.value * (1.0f / 100.0f); + size = scr_viewsize.value * (1.0 / 100.0); } - // LordHavoc: always fullscreen rendering - h = vid.height/* - sb_lines*/; - - r_refdef.vrect.width = vid.width * size; - if (r_refdef.vrect.width < 96) + if (size >= 1) { - size = 96.0 / r_refdef.vrect.width; - r_refdef.vrect.width = 96; // min for icons + r_refdef.width = vid.realwidth; + r_refdef.height = vid.realheight; + r_refdef.x = 0; + r_refdef.y = 0; } - - r_refdef.vrect.height = vid.height * size; - //if (r_refdef.vrect.height > vid.height - sb_lines) - // r_refdef.vrect.height = vid.height - sb_lines; - if (r_refdef.vrect.height > (int) vid.height) - r_refdef.vrect.height = vid.height; - r_refdef.vrect.x = (vid.width - r_refdef.vrect.width)/2; - if (full) - r_refdef.vrect.y = 0; else - r_refdef.vrect.y = (h - r_refdef.vrect.height)/2; + { + r_refdef.width = vid.realwidth * size; + r_refdef.height = vid.realheight * size; + r_refdef.x = (vid.realwidth - r_refdef.width)/2; + r_refdef.y = (vid.realheight - r_refdef.height)/2; + } r_refdef.fov_x = scr_fov.value; - r_refdef.fov_y = CalcFov (r_refdef.fov_x, r_refdef.vrect.width, r_refdef.vrect.height); + r_refdef.fov_y = CalcFov (r_refdef.fov_x, r_refdef.width, r_refdef.height); + + r_refdef.width = bound(0, r_refdef.width, vid.realwidth); + r_refdef.height = bound(0, r_refdef.height, vid.realheight); + r_refdef.x = bound(0, r_refdef.x, vid.realwidth) + vid.realx; + r_refdef.y = bound(0, r_refdef.y, vid.realheight) + vid.realy; } @@ -336,7 +311,7 @@ Keybinding command void SCR_SizeUp_f (void) { Cvar_SetValue ("viewsize",scr_viewsize.value+10); - vid.recalc_refdef = 1; +// vid.recalc_refdef = 1; } @@ -350,7 +325,7 @@ Keybinding command void SCR_SizeDown_f (void) { Cvar_SetValue ("viewsize",scr_viewsize.value-10); - vid.recalc_refdef = 1; +// vid.recalc_refdef = 1; } //============================================================================ @@ -415,13 +390,9 @@ SCR_DrawRam */ void SCR_DrawRam (void) { - if (!scr_showram.value) - return; - - if (!r_cache_thrash) - return; - - Draw_Pic (32, 0, scr_ram); +// if (!scr_showram.value) +// return; +// Draw_Pic (32, 0, scr_ram); } /* @@ -480,8 +451,7 @@ void SCR_DrawPause (void) return; pic = Draw_CachePic ("gfx/pause.lmp"); - Draw_Pic ( (vid.width - pic->width)/2, - (vid.height - 48 - pic->height)/2, pic); + Draw_Pic ((vid.conwidth - pic->width)/2, (vid.conheight - pic->height)/2, pic); } @@ -500,8 +470,7 @@ void SCR_DrawLoading (void) return; pic = Draw_CachePic ("gfx/loading.lmp"); - Draw_Pic ( (vid.width - pic->width)/2, - (vid.height - 48 - pic->height)/2, pic); + Draw_Pic ((vid.conwidth - pic->width)/2, (vid.conheight - pic->height)/2, pic); } */ @@ -527,14 +496,14 @@ void SCR_SetUpToDrawConsole (void) if (con_forcedup) { - scr_conlines = vid.height; // full screen + scr_conlines = vid.conheight; // full screen scr_con_current = scr_conlines; } else if (key_dest == key_console) - scr_conlines = vid.height/2; // half screen + scr_conlines = vid.conheight/2; // half screen else scr_conlines = 0; // none visible - + if (scr_conlines < scr_con_current) { scr_con_current -= scr_conspeed.value*host_realframetime; @@ -549,7 +518,7 @@ void SCR_SetUpToDrawConsole (void) scr_con_current = scr_conlines; } } - + /* ================== SCR_DrawConsole @@ -572,33 +541,33 @@ void SCR_DrawConsole (void) /* ============================================================================== - + SCREEN SHOTS ============================================================================== */ /* -================== +================== SCR_ScreenShot_f -================== +================== */ -void SCR_ScreenShot_f (void) +void SCR_ScreenShot_f (void) { - byte *buffer; - char filename[80]; + byte *buffer, gamma[256]; + char filename[80]; char checkname[MAX_OSPATH]; int i; // -// find a file name to save it to -// +// find a file name to save it to +// strcpy(filename,"dp0000.tga"); - - for (i=0 ; i<=9999 ; i++) - { - filename[2] = (i/1000)%10 + '0'; - filename[3] = (i/ 100)%10 + '0'; - filename[4] = (i/ 10)%10 + '0'; + + for (i=0 ; i<=9999 ; i++) + { + filename[2] = (i/1000)%10 + '0'; + filename[3] = (i/ 100)%10 + '0'; + filename[4] = (i/ 10)%10 + '0'; filename[5] = (i/ 1)%10 + '0'; sprintf (checkname, "%s/%s", com_gamedir, filename); if (Sys_FileTime(checkname) == -1) @@ -606,13 +575,18 @@ void SCR_ScreenShot_f (void) } if (i==10000) { - Con_Printf ("SCR_ScreenShot_f: Couldn't create a TGA file\n"); + Con_Printf ("SCR_ScreenShot_f: Couldn't create a TGA file\n"); return; } - buffer = qmalloc(glwidth*glheight*3); - glReadPixels (glx, gly, glwidth, glheight, GL_RGB, GL_UNSIGNED_BYTE, buffer); - Image_WriteTGARGB_preflipped(filename, glwidth, glheight, buffer); + buffer = qmalloc(vid.realwidth*vid.realheight*3); + glReadPixels (vid.realx, vid.realy, vid.realwidth, vid.realheight, GL_RGB, GL_UNSIGNED_BYTE, buffer); + + // apply hardware gamma to the image + BuildGammaTable8((lighthalf && hardwaregammasupported) ? 2.0f : 1.0f, 1, 1, 0, gamma); + Image_GammaRemapRGB(buffer, buffer, vid.realwidth*vid.realheight, gamma, gamma, gamma); + + Image_WriteTGARGB_preflipped(filename, vid.realwidth, vid.realheight, buffer); qfree(buffer); Con_Printf ("Wrote %s\n", filename); @@ -637,7 +611,7 @@ void SCR_BeginLoadingPlaque (void) // return; // if (cls.signon != SIGNONS) // return; - + // redraw with no console and the loading plaque // Con_ClearNotify (); // scr_centertime_off = 0; @@ -678,7 +652,7 @@ void SCR_DrawNotifyString (void) start = scr_notifystring; - y = vid.height*0.35; + y = vid.conheight*0.35; do { @@ -686,7 +660,7 @@ void SCR_DrawNotifyString (void) for (l=0 ; l<40 ; l++) if (start[l] == '\n' || !start[l]) break; - x = (vid.width - l*8)/2; + x = (vid.conwidth - l*8)/2; // LordHavoc: speedup // for (j=0 ; jv.items = (int)sv_player->v.items | HIT_PROXIMITY_GUN; - else - sv_player->v.items = (int)sv_player->v.items | IT_GRENADE_LAUNCHER; - } - else if (t[0] == '9') - sv_player->v.items = (int)sv_player->v.items | HIT_LASER_CANNON; - else if (t[0] == '0') - sv_player->v.items = (int)sv_player->v.items | HIT_MJOLNIR; - else if (t[0] >= '2') - sv_player->v.items = (int)sv_player->v.items | (IT_SHOTGUN << (t[0] - '2')); - } - else - { - if (t[0] >= '2') - sv_player->v.items = (int)sv_player->v.items | (IT_SHOTGUN << (t[0] - '2')); - } + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + // MED 01/04/97 added hipnotic give stuff + if (gamemode == GAME_HIPNOTIC) + { + if (t[0] == '6') + { + if (t[1] == 'a') + sv_player->v.items = (int)sv_player->v.items | HIT_PROXIMITY_GUN; + else + sv_player->v.items = (int)sv_player->v.items | IT_GRENADE_LAUNCHER; + } + else if (t[0] == '9') + sv_player->v.items = (int)sv_player->v.items | HIT_LASER_CANNON; + else if (t[0] == '0') + sv_player->v.items = (int)sv_player->v.items | HIT_MJOLNIR; + else if (t[0] >= '2') + sv_player->v.items = (int)sv_player->v.items | (IT_SHOTGUN << (t[0] - '2')); + } + else + { + if (t[0] >= '2') + sv_player->v.items = (int)sv_player->v.items | (IT_SHOTGUN << (t[0] - '2')); + } break; - - case 's': - if (rogue) + + case 's': + if (gamemode == GAME_ROGUE) { - if ((val = GETEDICTFIELDVALUE(sv_player, eval_ammo_shells1))) - val->_float = v; + if ((val = GETEDICTFIELDVALUE(sv_player, eval_ammo_shells1))) + val->_float = v; } - sv_player->v.ammo_shells = v; - break; - case 'n': - if (rogue) + sv_player->v.ammo_shells = v; + break; + case 'n': + if (gamemode == GAME_ROGUE) { - if ((val = GETEDICTFIELDVALUE(sv_player, eval_ammo_nails1))) + if ((val = GETEDICTFIELDVALUE(sv_player, eval_ammo_nails1))) { - val->_float = v; + val->_float = v; if (sv_player->v.weapon <= IT_LIGHTNING) sv_player->v.ammo_nails = v; } @@ -1335,9 +1335,9 @@ void Host_Give_f (void) { sv_player->v.ammo_nails = v; } - break; - case 'l': - if (rogue) + break; + case 'l': + if (gamemode == GAME_ROGUE) { val = GETEDICTFIELDVALUE(sv_player, eval_ammo_lava_nails); if (val) @@ -1347,9 +1347,9 @@ void Host_Give_f (void) sv_player->v.ammo_nails = v; } } - break; - case 'r': - if (rogue) + break; + case 'r': + if (gamemode == GAME_ROGUE) { val = GETEDICTFIELDVALUE(sv_player, eval_ammo_rockets1); if (val) @@ -1363,9 +1363,9 @@ void Host_Give_f (void) { sv_player->v.ammo_rockets = v; } - break; - case 'm': - if (rogue) + break; + case 'm': + if (gamemode == GAME_ROGUE) { val = GETEDICTFIELDVALUE(sv_player, eval_ammo_multi_rockets); if (val) @@ -1375,12 +1375,12 @@ void Host_Give_f (void) sv_player->v.ammo_rockets = v; } } - break; - case 'h': - sv_player->v.health = v; - break; - case 'c': - if (rogue) + break; + case 'h': + sv_player->v.health = v; + break; + case 'c': + if (gamemode == GAME_ROGUE) { val = GETEDICTFIELDVALUE(sv_player, eval_ammo_cells1); if (val) @@ -1394,9 +1394,9 @@ void Host_Give_f (void) { sv_player->v.ammo_cells = v; } - break; - case 'p': - if (rogue) + break; + case 'p': + if (gamemode == GAME_ROGUE) { val = GETEDICTFIELDVALUE(sv_player, eval_ammo_plasma); if (val) @@ -1406,15 +1406,15 @@ void Host_Give_f (void) sv_player->v.ammo_cells = v; } } - break; - } + break; + } } edict_t *FindViewthing (void) { int i; edict_t *e; - + for (i=0 ; iofs_scenes && data) + if (m->ofs_scenes && (data = (int) Mod_Extradata(m))) Con_Printf("frame %i: %s\n", frame, ((animscene_t *) (m->ofs_scenes + data))[frame].name); else Con_Printf("frame %i\n", frame); @@ -1620,7 +1619,7 @@ void Host_InitCommands (void) { Cmd_AddCommand ("status", Host_Status_f); Cmd_AddCommand ("quit", Host_Quit_f); - if (nehahra) + if (gamemode == GAME_NEHAHRA) { Cmd_AddCommand ("max", Host_God_f); Cmd_AddCommand ("monster", Host_Notarget_f); diff --git a/image.c b/image.c index acfdf77b..6023e91b 100644 --- a/image.c +++ b/image.c @@ -4,6 +4,18 @@ int image_width; int image_height; +void Image_GammaRemapRGB(byte *in, byte *out, int pixels, byte *gammar, byte *gammag, byte *gammab) +{ + while (pixels--) + { + out[0] = gammar[in[0]]; + out[1] = gammag[in[1]]; + out[2] = gammab[in[2]]; + in += 3; + out += 3; + } +} + // note: pal must be 32bit color void Image_Copy8bitRGBA(byte *in, byte *out, int pixels, int *pal) { diff --git a/image.h b/image.h index 9fc65f0d..0a1d73fd 100644 --- a/image.h +++ b/image.h @@ -1,4 +1,5 @@ +void Image_GammaRemapRGB(byte *in, byte *out, int pixels, byte *gammar, byte *gammag, byte *gammab); void Image_Copy8bitRGBA(byte *in, byte *out, int pixels, int *pal); void Image_CopyRGBAGamma(byte *in, byte *out, int pixels); int image_makemask (byte *in, byte *out, int size); diff --git a/keys.c b/keys.c index 9632ed63..6fe4a86f 100644 --- a/keys.c +++ b/keys.c @@ -279,8 +279,8 @@ void Key_Console (int key) if (key == K_PGUP || key==K_MWHEELUP) { con_backscroll += 2; - if (con_backscroll > con_totallines - (vid.height>>3) - 1) - con_backscroll = con_totallines - (vid.height>>3) - 1; + if (con_backscroll > con_totallines - (vid.conheight>>3) - 1) + con_backscroll = con_totallines - (vid.conheight>>3) - 1; return; } @@ -294,7 +294,7 @@ void Key_Console (int key) if (key == K_HOME) { - con_backscroll = con_totallines - (vid.height>>3) - 1; + con_backscroll = con_totallines - (vid.conheight>>3) - 1; return; } diff --git a/makefile b/makefile index f30f40ac..a6f6e423 100644 --- a/makefile +++ b/makefile @@ -9,7 +9,7 @@ SOUNDLIB=-lasound #SND=snd_oss.o #SOUNDLIB= -OBJECTS= buildnumber.o cd_linux.o chase.o cl_demo.o cl_input.o cl_main.o cl_parse.o cl_tent.o cmd.o common.o console.o crc.o cvar.o fractalnoise.o gl_draw.o gl_poly.o gl_rmain.o gl_rmisc.o gl_rsurf.o gl_screen.o gl_warp.o host.o host_cmd.o image.o keys.o mathlib.o menu.o model_alias.o model_brush.o model_shared.o model_sprite.o net_bsd.o net_udp.o net_dgrm.o net_loop.o net_main.o pr_cmds.o pr_edict.o pr_exec.o r_light.o r_part.o r_explosion.o sbar.o snd_dma.o snd_mem.o snd_mix.o $(SND) sv_main.o sv_move.o sv_phys.o sv_user.o sv_light.o sys_linux.o transform.o view.o wad.o world.o zone.o vid_shared.o palette.o r_crosshairs.o gl_textures.o gl_models.o r_sprites.o r_modules.o r_explosion.o r_lerpanim.o cl_effects.o r_decals.o protocol.o quakeio.o r_clip.o ui.o portals.o sys_shared.o +OBJECTS= buildnumber.o cd_linux.o chase.o cl_demo.o cl_input.o cl_main.o cl_parse.o cl_tent.o cmd.o common.o console.o crc.o cvar.o fractalnoise.o gl_draw.o gl_poly.o gl_rmain.o gl_rmisc.o gl_rsurf.o gl_screen.o gl_warp.o host.o host_cmd.o image.o keys.o mathlib.o menu.o model_alias.o model_brush.o model_shared.o model_sprite.o net_bsd.o net_udp.o net_dgrm.o net_loop.o net_main.o pr_cmds.o pr_edict.o pr_exec.o r_light.o r_part.o r_explosion.o sbar.o snd_dma.o snd_mem.o snd_mix.o $(SND) sv_main.o sv_move.o sv_phys.o sv_user.o sv_light.o sys_linux.o transform.o view.o wad.o world.o zone.o vid_shared.o palette.o r_crosshairs.o gl_textures.o gl_models.o r_sprites.o r_modules.o r_explosion.o r_lerpanim.o cl_effects.o r_decals.o protocol.o quakeio.o r_clip.o ui.o portals.o sys_shared.o cl_light.o #K6/athlon optimizations CPUOPTIMIZATIONS=-march=k6 @@ -37,9 +37,17 @@ CFLAGS= -MD -Wall -Werror -I/usr/X11R6/include -I/usr/include/glide $(OPTIMIZATI LDFLAGS= -L/usr/X11R6/lib -lm -lX11 -lXext -lXIE -lXxf86dga -lXxf86vm -lGL -ldl $(SOUNDLIB) -lz $(PROFILEOPTION) #most people can't build the -3dfx version (-3dfx version needs some updates for new mesa) -all: darkplaces-glx +all: buildnum darkplaces-glx #all: darkplaces-glx darkplaces-3dfx +buildnum/buildnum: + cd buildnum + make + cd .. + +buildnum: buildnum/buildnum + buildnum/buildnum buildnumber.c + .c.o: gcc $(CFLAGS) -c $*.c @@ -54,6 +62,6 @@ clean: -rm -f darkplaces-glx darkplaces-3dfx -rm -f vid_glx.o in_svgalib.o vid_3dfxsvga.o $(OBJECTS) *.d -.PHONY: clean +.PHONY: clean buildnum -include *.d diff --git a/mathlib.c b/mathlib.c index 6709b1e5..726cd089 100644 --- a/mathlib.c +++ b/mathlib.c @@ -631,7 +631,7 @@ int VectorCompare (vec3_t v1, vec3_t v2) return 1; } -void VectorMA (vec3_t veca, float scale, vec3_t vecb, vec3_t vecc) +void VectorMASlow (vec3_t veca, float scale, vec3_t vecb, vec3_t vecc) { vecc[0] = veca[0] + scale*vecb[0]; vecc[1] = veca[1] + scale*vecb[1]; diff --git a/mathlib.h b/mathlib.h index d3cfe5ee..96497960 100644 --- a/mathlib.h +++ b/mathlib.h @@ -63,7 +63,7 @@ extern int nanmask; #define VectorDistance(a, b) (sqrt(VectorDistance2(a,b))) #define VectorLength(a) sqrt(DotProduct(a, a)) #define VectorScale(in, scale, out) {(out)[0] = (in)[0] * (scale);(out)[1] = (in)[1] * (scale);(out)[2] = (in)[2] * (scale);} -#define VectorMAQuick(a, scale, b, c) {(c)[0] = (a)[0] + (scale) * (b)[0];(c)[1] = (a)[1] + (scale) * (b)[1];(c)[2] = (a)[2] + (scale) * (b)[2];} +#define VectorMA(a, scale, b, c) {(c)[0] = (a)[0] + (scale) * (b)[0];(c)[1] = (a)[1] + (scale) * (b)[1];(c)[2] = (a)[2] + (scale) * (b)[2];} #define VectorNormalizeFast(_v)\ {\ float _y, _number;\ @@ -74,10 +74,11 @@ extern int nanmask; _y = _y * (1.5f - (_number * 0.5f * _y * _y));\ VectorScale(_v, _y, _v);\ }\ -}\ +} +#define VectorRandom(v) {do{(v)[0] = lhrandom(-1, 1);(v)[1] = lhrandom(-1, 1);(v)[2] = lhrandom(-1, 1);}while(DotProduct(v, v) > 1);} -void VectorMA (vec3_t veca, float scale, vec3_t vecb, vec3_t vecc); +void VectorMASlow (vec3_t veca, float scale, vec3_t vecb, vec3_t vecc); vec_t _DotProduct (vec3_t v1, vec3_t v2); void _VectorSubtract (vec3_t veca, vec3_t vecb, vec3_t out); @@ -152,3 +153,5 @@ typedef struct { double normal[3], dist; } tinydoubleplane_t; + +void RotatePointAroundVector( vec3_t dst, const vec3_t dir, const vec3_t point, float degrees ); diff --git a/menu.c b/menu.c index e7687541..c4d80a5b 100644 --- a/menu.c +++ b/menu.c @@ -119,7 +119,7 @@ Draws one solid graphics character */ void M_DrawCharacter (int cx, int line, int num) { - Draw_Character ( cx + ((vid.width - 320)>>1), line, num); + Draw_Character ( cx + ((vid.conwidth - 320)>>1), line, num); } void M_Print (int cx, int cy, char *str) @@ -144,7 +144,7 @@ void M_PrintWhite (int cx, int cy, char *str) void M_DrawPic (int x, int y, qpic_t *pic) { - Draw_Pic (x + ((vid.width - 320)>>1), y, pic); + Draw_Pic (x + ((vid.conwidth - 320)>>1), y, pic); } byte identityTable[256]; @@ -179,7 +179,7 @@ void M_BuildTranslationTable(int top, int bottom) void M_DrawPicTranslate (int x, int y, qpic_t *pic) { - Draw_PicTranslate (x + ((vid.width - 320)>>1), y, pic, translationTable); + Draw_PicTranslate (x + ((vid.conwidth - 320)>>1), y, pic, translationTable); } @@ -420,7 +420,7 @@ int MAIN_ITEMS = 4; // Nehahra: Menu Disable void M_Menu_Main_f (void) { - if (nehahra) + if (gamemode == GAME_NEHAHRA) { if (NehGameType == TYPE_DEMO) MAIN_ITEMS = 4; @@ -452,7 +452,7 @@ void M_Main_Draw (void) p = Draw_CachePic ("gfx/ttl_main.lmp"); M_DrawPic ( (320-p->width)/2, 4, p); // Nehahra - if (nehahra) + if (gamemode == GAME_NEHAHRA) { if (NehGameType == TYPE_BOTH) M_DrawPic (72, 32, Draw_CachePic ("gfx/mainmenu.lmp")); @@ -497,7 +497,7 @@ void M_Main_Key (int key) case K_ENTER: m_entersound = true; - if (nehahra) + if (gamemode == GAME_NEHAHRA) { switch (NehGameType) { @@ -673,7 +673,7 @@ void M_SinglePlayer_Key (int key) if (sv.active) Cbuf_AddText ("disconnect\n"); Cbuf_AddText ("maxplayers 1\n"); - if (nehahra) + if (gamemode == GAME_NEHAHRA) Cbuf_AddText ("map nehstart\n"); else Cbuf_AddText ("map start\n"); @@ -1758,7 +1758,7 @@ char *quitMessage [] = " this game just like ", " everything else? ", " ", - + " Milord, methinks that ", " thou art a lowly ", " quitter. Is this true? ", @@ -2335,7 +2335,7 @@ void M_GameOptions_Draw (void) M_Print (160, 64, "Deathmatch"); M_Print (0, 72, " Teamplay"); - if (rogue) + if (gamemode == GAME_ROGUE) { char *msg; @@ -2387,40 +2387,40 @@ void M_GameOptions_Draw (void) M_Print (160, 96, va("%i minutes", (int)timelimit.value)); M_Print (0, 112, " Episode"); - //MED 01/06/97 added hipnotic episodes - if (hipnotic) - M_Print (160, 112, hipnoticepisodes[startepisode].description); - //PGM 01/07/97 added rogue episodes - else if (rogue) - M_Print (160, 112, rogueepisodes[startepisode].description); - else if (nehahra) - M_Print (160, 112, nehahraepisodes[startepisode].description); - else - M_Print (160, 112, episodes[startepisode].description); + //MED 01/06/97 added hipnotic episodes + if (gamemode == GAME_HIPNOTIC) + M_Print (160, 112, hipnoticepisodes[startepisode].description); + //PGM 01/07/97 added rogue episodes + else if (gamemode == GAME_ROGUE) + M_Print (160, 112, rogueepisodes[startepisode].description); + else if (gamemode == GAME_NEHAHRA) + M_Print (160, 112, nehahraepisodes[startepisode].description); + else + M_Print (160, 112, episodes[startepisode].description); M_Print (0, 120, " Level"); - //MED 01/06/97 added hipnotic episodes - if (hipnotic) - { - M_Print (160, 120, hipnoticlevels[hipnoticepisodes[startepisode].firstLevel + startlevel].description); - M_Print (160, 128, hipnoticlevels[hipnoticepisodes[startepisode].firstLevel + startlevel].name); - } - //PGM 01/07/97 added rogue episodes - else if (rogue) - { - M_Print (160, 120, roguelevels[rogueepisodes[startepisode].firstLevel + startlevel].description); - M_Print (160, 128, roguelevels[rogueepisodes[startepisode].firstLevel + startlevel].name); - } - else if (nehahra) - { - M_Print (160, 120, nehahralevels[nehahraepisodes[startepisode].firstLevel + startlevel].description); - M_Print (160, 128, nehahralevels[nehahraepisodes[startepisode].firstLevel + startlevel].name); - } - else - { - M_Print (160, 120, levels[episodes[startepisode].firstLevel + startlevel].description); - M_Print (160, 128, levels[episodes[startepisode].firstLevel + startlevel].name); - } + //MED 01/06/97 added hipnotic episodes + if (gamemode == GAME_HIPNOTIC) + { + M_Print (160, 120, hipnoticlevels[hipnoticepisodes[startepisode].firstLevel + startlevel].description); + M_Print (160, 128, hipnoticlevels[hipnoticepisodes[startepisode].firstLevel + startlevel].name); + } + //PGM 01/07/97 added rogue episodes + else if (gamemode == GAME_ROGUE) + { + M_Print (160, 120, roguelevels[rogueepisodes[startepisode].firstLevel + startlevel].description); + M_Print (160, 128, roguelevels[rogueepisodes[startepisode].firstLevel + startlevel].name); + } + else if (gamemode == GAME_NEHAHRA) + { + M_Print (160, 120, nehahralevels[nehahraepisodes[startepisode].firstLevel + startlevel].description); + M_Print (160, 128, nehahralevels[nehahraepisodes[startepisode].firstLevel + startlevel].name); + } + else + { + M_Print (160, 120, levels[episodes[startepisode].firstLevel + startlevel].description); + M_Print (160, 128, levels[episodes[startepisode].firstLevel + startlevel].name); + } // line cursor M_DrawCharacter (144, gameoptions_cursor_table[gameoptions_cursor], 12+((int)(realtime*4)&1)); @@ -2483,7 +2483,7 @@ void M_NetStart_Change (int dir) break; case 3: - if (rogue) + if (gamemode == GAME_ROGUE) count = 6; else count = 2; @@ -2522,13 +2522,13 @@ void M_NetStart_Change (int dir) case 7: startepisode += dir; //MED 01/06/97 added hipnotic count - if (hipnotic) + if (gamemode == GAME_HIPNOTIC) count = 6; //PGM 01/07/97 added rogue count //PGM 03/02/97 added 1 for dmatch episode - else if (rogue) + else if (gamemode == GAME_ROGUE) count = 4; - else if (nehahra) + else if (gamemode == GAME_NEHAHRA) count = 4; else if (registered.value) count = 7; @@ -2547,12 +2547,12 @@ void M_NetStart_Change (int dir) case 8: startlevel += dir; //MED 01/06/97 added hipnotic episodes - if (hipnotic) + if (gamemode == GAME_HIPNOTIC) count = hipnoticepisodes[startepisode].levels; //PGM 01/06/97 added hipnotic episodes - else if (rogue) + else if (gamemode == GAME_ROGUE) count = rogueepisodes[startepisode].levels; - else if (nehahra) + else if (gamemode == GAME_NEHAHRA) count = nehahraepisodes[startepisode].levels; else count = episodes[startepisode].levels; @@ -2612,11 +2612,11 @@ void M_GameOptions_Key (int key) Cbuf_AddText ( va ("maxplayers %u\n", maxplayers) ); // SCR_BeginLoadingPlaque (); - if (hipnotic) + if (gamemode == GAME_HIPNOTIC) Cbuf_AddText ( va ("map %s\n", hipnoticlevels[hipnoticepisodes[startepisode].firstLevel + startlevel].name) ); - else if (rogue) + else if (gamemode == GAME_ROGUE) Cbuf_AddText ( va ("map %s\n", roguelevels[rogueepisodes[startepisode].firstLevel + startlevel].name) ); - else if (nehahra) + else if (gamemode == GAME_NEHAHRA) Cbuf_AddText ( va ("map %s\n", nehahralevels[nehahraepisodes[startepisode].firstLevel + startlevel].name) ); else Cbuf_AddText ( va ("map %s\n", levels[episodes[startepisode].firstLevel + startlevel].name) ); @@ -2812,7 +2812,7 @@ void M_Init (void) Cmd_AddCommand ("help", M_Menu_Help_f); Cmd_AddCommand ("menu_quit", M_Menu_Quit_f); - if (nehahra) + if (gamemode == GAME_NEHAHRA) { if (COM_FileExists("maps/neh1m4.bsp")) { @@ -2854,7 +2854,7 @@ void M_Draw (void) { if (scr_con_current) { - Draw_ConsoleBackground (vid.height); + Draw_ConsoleBackground (vid.conheight); S_ExtraUpdate (); } } diff --git a/model_alias.c b/model_alias.c index 10326026..edca9f90 100644 --- a/model_alias.c +++ b/model_alias.c @@ -20,7 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "quakedef.h" -cvar_t r_mipskins = {CVAR_SAVE, "r_mipskins", "1"}; +static cvar_t r_mipskins = {CVAR_SAVE, "r_mipskins", "0"}; /* =============== @@ -32,19 +32,26 @@ void Mod_AliasInit (void) Cvar_RegisterVariable(&r_mipskins); } -int posenum; +static void Mod_Alias_SERAddEntity(void) +{ + R_Clip_AddBox(currentrenderentity->mins, currentrenderentity->maxs, R_Entity_Callback, currentrenderentity, NULL); +} + +static int posenum; -float aliasbboxmin[3], aliasbboxmax[3]; // LordHavoc: proper bounding box considerations +// LordHavoc: proper bounding box considerations +static float aliasbboxmin[3], aliasbboxmax[3], modelyawradius, modelradius; -float vertst[MAXALIASVERTS][2]; -int vertusage[MAXALIASVERTS]; -int vertonseam[MAXALIASVERTS]; -int vertremap[MAXALIASVERTS]; -unsigned short temptris[MAXALIASTRIS][3]; +static float vertst[MAXALIASVERTS][2]; +static int vertusage[MAXALIASVERTS]; +static int vertonseam[MAXALIASVERTS]; +static int vertremap[MAXALIASVERTS]; +static unsigned short temptris[MAXALIASTRIS][3]; -void Mod_ConvertAliasVerts (int inverts, vec3_t scale, vec3_t translate, trivertx_t *v, trivertx_t *out) +static void Mod_ConvertAliasVerts (int inverts, vec3_t scale, vec3_t translate, trivertx_t *v, trivertx_t *out) { int i, j, invalidnormals = 0; + float dist; vec3_t temp; for (i = 0;i < inverts;i++) { @@ -60,6 +67,12 @@ void Mod_ConvertAliasVerts (int inverts, vec3_t scale, vec3_t translate, trivert if (temp[0] > aliasbboxmax[0]) aliasbboxmax[0] = temp[0]; if (temp[1] > aliasbboxmax[1]) aliasbboxmax[1] = temp[1]; if (temp[2] > aliasbboxmax[2]) aliasbboxmax[2] = temp[2]; + dist = temp[0]*temp[0]+temp[1]*temp[1]; + if (modelyawradius < dist) + modelyawradius = dist; + dist += temp[2]*temp[2]; + if (modelradius < dist) + modelradius = dist; j = vertremap[i]; // not onseam if (j >= 0) { @@ -92,11 +105,11 @@ void Mod_ConvertAliasVerts (int inverts, vec3_t scale, vec3_t translate, trivert Mod_LoadAliasFrame ================= */ -void * Mod_LoadAliasFrame (void *pin, maliashdr_t *mheader, int inverts, int outverts, trivertx_t **posevert, animscene_t *scene) +static void * Mod_LoadAliasFrame (void *pin, maliashdr_t *mheader, int inverts, int outverts, trivertx_t **posevert, animscene_t *scene) { trivertx_t *pinframe; daliasframe_t *pdaliasframe; - + pdaliasframe = (daliasframe_t *)pin; strcpy(scene->name, pdaliasframe->name); @@ -122,12 +135,12 @@ void * Mod_LoadAliasFrame (void *pin, maliashdr_t *mheader, int inverts, int out Mod_LoadAliasGroup ================= */ -void *Mod_LoadAliasGroup (void *pin, maliashdr_t *mheader, int inverts, int outverts, trivertx_t **posevert, animscene_t *scene) +static void *Mod_LoadAliasGroup (void *pin, maliashdr_t *mheader, int inverts, int outverts, trivertx_t **posevert, animscene_t *scene) { int i, numframes; void *ptemp; float interval; - + numframes = LittleLong (((daliasgroup_t *)pin)->numframes); strcpy(scene->name, ((daliasframe_t *) (sizeof(daliasinterval_t) * numframes + sizeof(daliasgroup_t) + (int) pin))->name); @@ -155,81 +168,7 @@ void *Mod_LoadAliasGroup (void *pin, maliashdr_t *mheader, int inverts, int outv //========================================================= -/* -================= -Mod_FloodFillSkin - -Fill background pixels so mipmapping doesn't have haloes - Ed -================= -*/ - -typedef struct -{ - short x, y; -} floodfill_t; - -// must be a power of 2 -#define FLOODFILL_FIFO_SIZE 0x1000 -#define FLOODFILL_FIFO_MASK (FLOODFILL_FIFO_SIZE - 1) - -#define FLOODFILL_STEP( off, dx, dy ) \ -{ \ - if (pos[off] == fillcolor) \ - { \ - pos[off] = 255; \ - fifo[inpt].x = x + (dx), fifo[inpt].y = y + (dy); \ - inpt = (inpt + 1) & FLOODFILL_FIFO_MASK; \ - } \ - else if (pos[off] != 255) fdc = pos[off]; \ -} - -void Mod_FloodFillSkin( byte *skin, int skinwidth, int skinheight ) -{ - byte fillcolor = *skin; // assume this is the pixel to fill - floodfill_t fifo[FLOODFILL_FIFO_SIZE]; - int inpt = 0, outpt = 0; - int filledcolor = -1; - int i; - - if (filledcolor == -1) - { - filledcolor = 0; - // attempt to find opaque black - for (i = 0; i < 256; ++i) - if (d_8to24table[i] == (255 << 0)) // alpha 1.0 - { - filledcolor = i; - break; - } - } - - // can't fill to filled color or to transparent color (used as visited marker) - if ((fillcolor == filledcolor) || (fillcolor == 255)) - { - //printf( "not filling skin from %d to %d\n", fillcolor, filledcolor ); - return; - } - - fifo[inpt].x = 0, fifo[inpt].y = 0; - inpt = (inpt + 1) & FLOODFILL_FIFO_MASK; - - while (outpt != inpt) - { - int x = fifo[outpt].x, y = fifo[outpt].y; - int fdc = filledcolor; - byte *pos = &skin[x + skinwidth * y]; - - outpt = (outpt + 1) & FLOODFILL_FIFO_MASK; - - if (x > 0) FLOODFILL_STEP( -1, -1, 0 ); - if (x < skinwidth - 1) FLOODFILL_STEP( 1, 1, 0 ); - if (y > 0) FLOODFILL_STEP( -skinwidth, 0, -1 ); - if (y < skinheight - 1) FLOODFILL_STEP( skinwidth, 0, 1 ); - skin[x + skinwidth * y] = fdc; - } -} - -rtexture_t *GL_SkinSplitShirt(byte *in, byte *out, int width, int height, unsigned short bits, char *name, int precache) +static rtexture_t *GL_SkinSplitShirt(byte *in, byte *out, int width, int height, unsigned short bits, char *name, int precache) { int i, pixels, passed; byte pixeltest[16]; @@ -259,7 +198,7 @@ rtexture_t *GL_SkinSplitShirt(byte *in, byte *out, int width, int height, unsign return NULL; } -rtexture_t *GL_SkinSplit(byte *in, byte *out, int width, int height, unsigned short bits, char *name, int precache) +static rtexture_t *GL_SkinSplit(byte *in, byte *out, int width, int height, unsigned short bits, char *name, int precache) { int i, pixels, passed; byte pixeltest[16]; @@ -285,7 +224,7 @@ rtexture_t *GL_SkinSplit(byte *in, byte *out, int width, int height, unsigned sh return NULL; } -int GL_SkinCheck(byte *in, int width, int height, unsigned short bits) +static int GL_SkinCheck(byte *in, int width, int height, unsigned short bits) { int i, pixels, passed; byte pixeltest[16]; @@ -302,7 +241,7 @@ int GL_SkinCheck(byte *in, int width, int height, unsigned short bits) return false; } -void Mod_LoadSkin (maliashdr_t *mheader, char *basename, byte *skindata, byte *skintemp, int width, int height, rtexture_t **skintex) +static void Mod_LoadSkin (maliashdr_t *mheader, char *basename, byte *skindata, byte *skintemp, int width, int height, rtexture_t **skintex) { skintex[0] = loadtextureimage(va("%s_normal", basename), 0, 0, false, r_mipskins.value, true); skintex[1] = NULL; @@ -340,7 +279,7 @@ void Mod_LoadSkin (maliashdr_t *mheader, char *basename, byte *skindata, byte *s Mod_LoadAllSkins =============== */ -void *Mod_LoadAllSkins (maliashdr_t *mheader, int numskins, daliasskintype_t *pskintype, int width, int height) +static void *Mod_LoadAllSkins (maliashdr_t *mheader, int numskins, daliasskintype_t *pskintype, int width, int height) { int i, j; char name[32]; @@ -353,7 +292,7 @@ void *Mod_LoadAllSkins (maliashdr_t *mheader, int numskins, daliasskintype_t *ps rtexture_t **skintex; void *temp; byte *skintemp = NULL; - + skin = (byte *)(pskintype + 1); if (numskins < 1 || numskins > MAX_SKINS) @@ -429,7 +368,7 @@ void *Mod_LoadAllSkins (maliashdr_t *mheader, int numskins, daliasskintype_t *ps return (void *)pskintype; } -void *Mod_SkipAllSkins (int numskins, daliasskintype_t *pskintype, int skinsize) +static void *Mod_SkipAllSkins (int numskins, daliasskintype_t *pskintype, int skinsize) { int i; for (i = 0;i < numskins;i++) @@ -468,6 +407,9 @@ void Mod_LoadAliasModel (model_t *mod, void *buffer) trivertx_t *posevert; animscene_t *animscenes; + modelyawradius = 0; + modelradius = 0; + start = Hunk_LowMark (); pinmodel = (mdl_t *)buffer; @@ -632,11 +574,24 @@ void Mod_LoadAliasModel (model_t *mod, void *buffer) // LordHavoc: fixed model bbox - was //FIXME: do this right //mod->mins[0] = mod->mins[1] = mod->mins[2] = -16; //mod->maxs[0] = mod->maxs[1] = mod->maxs[2] = 16; + modelyawradius = sqrt(modelyawradius); + modelradius = sqrt(modelradius); +// mod->modelradius = modelradius; for (j = 0;j < 3;j++) { - mod->mins[j] = aliasbboxmin[j]; - mod->maxs[j] = aliasbboxmax[j]; + mod->normalmins[j] = aliasbboxmin[j]; + mod->normalmaxs[j] = aliasbboxmax[j]; + mod->rotatedmins[j] = -modelradius; + mod->rotatedmaxs[j] = modelradius; } + mod->yawmins[0] = mod->yawmins[1] = -(mod->yawmaxs[0] = mod->yawmaxs[1] = modelyawradius); + mod->yawmins[2] = mod->normalmins[2]; + mod->yawmaxs[2] = mod->normalmaxs[2]; + + mod->SERAddEntity = Mod_Alias_SERAddEntity; + mod->DrawEarly = NULL; + mod->DrawLate = R_DrawAliasModel; + mod->DrawShadow = NULL; // move the complete, relocatable alias model to the cache end = Hunk_LowMark (); @@ -650,9 +605,10 @@ void Mod_LoadAliasModel (model_t *mod, void *buffer) Hunk_FreeToLowMark (start); } -void Mod_ConvertQ2AliasVerts (int numverts, vec3_t scale, vec3_t translate, trivertx_t *v, trivertx_t *out) +static void Mod_ConvertQ2AliasVerts (int numverts, vec3_t scale, vec3_t translate, trivertx_t *v, trivertx_t *out) { int i, invalidnormals = 0; + float dist; vec3_t temp; for (i = 0;i < numverts;i++) { @@ -667,6 +623,12 @@ void Mod_ConvertQ2AliasVerts (int numverts, vec3_t scale, vec3_t translate, triv if (temp[0] > aliasbboxmax[0]) aliasbboxmax[0] = temp[0]; if (temp[1] > aliasbboxmax[1]) aliasbboxmax[1] = temp[1]; if (temp[2] > aliasbboxmax[2]) aliasbboxmax[2] = temp[2]; + dist = temp[0]*temp[0]+temp[1]*temp[1]; + if (modelyawradius < dist) + modelyawradius = dist; + dist += temp[2]*temp[2]; + if (modelradius < dist) + modelradius = dist; out[i].lightnormalindex = v[i].lightnormalindex; if (out[i].lightnormalindex >= NUMVERTEXNORMALS) { @@ -695,6 +657,9 @@ void Mod_LoadQ2AliasModel (model_t *mod, void *buffer) // temptris_t *tris; animscene_t *animscenes; + modelyawradius = 0; + modelradius = 0; + start = Hunk_LowMark (); // if (!temptris) @@ -705,7 +670,7 @@ void Mod_LoadQ2AliasModel (model_t *mod, void *buffer) version = LittleLong (pinmodel->version); if (version != MD2ALIAS_VERSION) Host_Error ("%s has wrong version number (%i should be %i)", - mod->name, version, MD2ALIAS_VERSION); + mod->name, version, MD2ALIAS_VERSION); mod->type = mod_alias; mod->aliastype = ALIASTYPE_MD2; @@ -720,7 +685,7 @@ void Mod_LoadQ2AliasModel (model_t *mod, void *buffer) if (size <= 0 || size >= MD2MAX_SIZE) Host_Error ("%s is not a valid model", mod->name); pheader = Hunk_AllocName (size, va("%s Quake2 model", loadname)); - + mod->flags = 0; // there are no MD2 flags mod->numframes = LittleLong(pinmodel->num_frames); mod->synctype = ST_RAND; @@ -761,7 +726,7 @@ void Mod_LoadQ2AliasModel (model_t *mod, void *buffer) int *skinrange; skinrange = loadmodel->skinanimrange; skin = loadmodel->skinanim; -// skinrange = Hunk_AllocName (sizeof(int) * (pheader->num_skins * 2), loadname); +// skinrange = Hunk_AllocName (sizeof(int) * (pheader->num_skins * 2), loadname); // skin = skinrange + pheader->num_skins * 2; // loadmodel->skinanimrange = (int) skinrange - (int) pheader; // loadmodel->skinanim = (int) skin - (int) pheader; @@ -835,11 +800,19 @@ void Mod_LoadQ2AliasModel (model_t *mod, void *buffer) mod->ofs_scenes = (int) animscenes - (int) pheader; // LordHavoc: model bbox + modelyawradius = sqrt(modelyawradius); + modelradius = sqrt(modelradius); +// mod->modelradius = modelradius; for (j = 0;j < 3;j++) { - mod->mins[j] = aliasbboxmin[j]; - mod->maxs[j] = aliasbboxmax[j]; + mod->normalmins[j] = aliasbboxmin[j]; + mod->normalmaxs[j] = aliasbboxmax[j]; + mod->rotatedmins[j] = -modelradius; + mod->rotatedmaxs[j] = modelradius; } + mod->yawmins[0] = mod->yawmins[1] = -(mod->yawmaxs[0] = mod->yawmaxs[1] = modelyawradius); + mod->yawmins[2] = mod->normalmins[2]; + mod->yawmaxs[2] = mod->normalmaxs[2]; // load the draw list pinglcmd = (void*) ((int) pinmodel + LittleLong(pinmodel->ofs_glcmds)); @@ -848,6 +821,11 @@ void Mod_LoadQ2AliasModel (model_t *mod, void *buffer) for (i = 0;i < pheader->num_glcmds;i++) *poutglcmd++ = LittleLong(*pinglcmd++); + mod->SERAddEntity = Mod_Alias_SERAddEntity; + mod->DrawEarly = NULL; + mod->DrawLate = R_DrawAliasModel; + mod->DrawShadow = NULL; + // move the complete, relocatable alias model to the cache end = Hunk_LowMark (); mod->cachesize = total = end - start; @@ -860,7 +838,7 @@ void Mod_LoadQ2AliasModel (model_t *mod, void *buffer) Hunk_FreeToLowMark (start); } -void swapintblock(int *m, int size) +static void swapintblock(int *m, int size) { size /= 4; while(size--) @@ -879,6 +857,7 @@ void Mod_LoadZymoticModel (model_t *mod, void *buffer) zymscene_t *scene; zymbone_t *bone; animscene_t *animscenes; + float corner[2], modelradius; start = Hunk_LowMark (); @@ -936,7 +915,7 @@ void Mod_LoadZymoticModel (model_t *mod, void *buffer) // load the skins skinrange = loadmodel->skinanimrange; skin = loadmodel->skinanim; -// skinrange = Hunk_AllocName (sizeof(int) * (pheader->num_skins * 2), loadname); +// skinrange = Hunk_AllocName (sizeof(int) * (pheader->num_skins * 2), loadname); // skin = skinrange + pheader->num_skins * 2; // loadmodel->skinanimrange = (int) skinrange - (int) pheader; // loadmodel->skinanim = (int) skin - (int) pheader; @@ -1017,16 +996,33 @@ void Mod_LoadZymoticModel (model_t *mod, void *buffer) swapintblock((void *) (pheader->lump_trizone.start + pbase), pheader->lump_trizone.length); // model bbox + modelradius = pheader->radius; +// mod->modelradius = pheader->radius; for (i = 0;i < 3;i++) { - mod->mins[i] = pheader->mins[i]; - mod->maxs[i] = pheader->maxs[i]; + mod->normalmins[i] = pheader->mins[i]; + mod->normalmaxs[i] = pheader->maxs[i]; + mod->rotatedmins[i] = -modelradius; + mod->rotatedmaxs[i] = modelradius; } + corner[0] = max(fabs(mod->normalmins[0]), fabs(mod->normalmaxs[0])); + corner[1] = max(fabs(mod->normalmins[1]), fabs(mod->normalmaxs[1])); + mod->yawmaxs[0] = mod->yawmaxs[1] = sqrt(corner[0]*corner[0]+corner[1]*corner[1]); + if (mod->yawmaxs[0] > modelradius) + mod->yawmaxs[0] = mod->yawmaxs[1] = modelradius; + mod->yawmins[0] = mod->yawmins[1] = -mod->yawmaxs[0]; + mod->yawmins[2] = mod->normalmins[2]; + mod->yawmaxs[2] = mod->normalmaxs[2]; + + mod->SERAddEntity = Mod_Alias_SERAddEntity; + mod->DrawEarly = NULL; + mod->DrawLate = R_DrawAliasModel; + mod->DrawShadow = NULL; // move the complete, relocatable alias model to the cache end = Hunk_LowMark (); mod->cachesize = total = end - start; - + Cache_Alloc (&mod->cache, total, loadname); if (!mod->cache.data) return; diff --git a/model_brush.c b/model_brush.c index d2cee3f5..b005563b 100644 --- a/model_brush.c +++ b/model_brush.c @@ -20,7 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "quakedef.h" -byte mod_novis[MAX_MAP_LEAFS/8]; +byte mod_novis[(MAX_MAP_LEAFS + 7)/ 8]; qboolean hlbsp; // LordHavoc: true if it is a HalfLife BSP file (version 30) @@ -38,7 +38,12 @@ void Mod_BrushInit (void) Cvar_RegisterVariable (&gl_subdivide_size); Cvar_RegisterVariable (&halflifebsp); Cvar_RegisterVariable (&r_novis); - memset (mod_novis, 0xff, sizeof(mod_novis)); + memset(mod_novis, 0xff, sizeof(mod_novis)); +} + +void Mod_Brush_SERAddEntity(void) +{ + R_Clip_AddBox(currentrenderentity->mins, currentrenderentity->maxs, R_Entity_Callback, currentrenderentity, NULL); } /* @@ -49,7 +54,7 @@ Mod_PointInLeaf mleaf_t *Mod_PointInLeaf (vec3_t p, model_t *model) { mnode_t *node; - + // if (!model || !model->nodes) // Sys_Error ("Mod_PointInLeaf: bad model"); @@ -66,7 +71,7 @@ mleaf_t *Mod_PointInLeaf (vec3_t p, model_t *model) mnode_t *node; float d; mplane_t *plane; - + if (!model || !model->nodes) Sys_Error ("Mod_PointInLeaf: bad model"); @@ -92,7 +97,7 @@ mleaf_t *Mod_PointInLeaf (vec3_t p, model_t *model) Mod_DecompressVis =================== */ -byte *Mod_DecompressVis (byte *in, model_t *model) +static byte *Mod_DecompressVis (byte *in, model_t *model) { static byte decompressed[MAX_MAP_LEAFS/8]; int c; @@ -110,7 +115,7 @@ byte *Mod_DecompressVis (byte *in, model_t *model) *out++ = 0xff; row--; } - return decompressed; + return decompressed; } */ @@ -121,7 +126,7 @@ byte *Mod_DecompressVis (byte *in, model_t *model) *out++ = *in++; continue; } - + c = in[1]; in += 2; while (c) @@ -130,7 +135,7 @@ byte *Mod_DecompressVis (byte *in, model_t *model) c--; } } while (out - decompressed < row); - + return decompressed; } @@ -187,7 +192,7 @@ void Mod_SetupNoTexture(void) Mod_LoadTextures ================= */ -void Mod_LoadTextures (lump_t *l) +static void Mod_LoadTextures (lump_t *l) { int i, j, k, num, max, altmax, mtwidth, mtheight, *dofs; miptex_t *dmiptex; @@ -204,7 +209,7 @@ void Mod_LoadTextures (lump_t *l) m = (dmiptexlump_t *)(mod_base + l->fileofs); m->nummiptex = LittleLong (m->nummiptex); - + loadmodel->numtextures = m->nummiptex; loadmodel->textures = Hunk_AllocName (m->nummiptex * sizeof(*loadmodel->textures), va("%s texture headers", loadname)); @@ -227,11 +232,14 @@ void Mod_LoadTextures (lump_t *l) Host_Error ("Texture %s is corrupt or incomplete\n", dmiptex->name); mtdata = (byte *)dmiptex + j; } - + if ((mtwidth & 15) || (mtheight & 15)) Host_Error ("Texture %s is not 16 aligned", dmiptex->name); // LordHavoc: rewriting the map texture loader for GLQuake tx = Hunk_AllocName (sizeof(texture_t), va("%s textures", loadname)); + memset(tx, 0, sizeof(texture_t)); + tx->anim_total = 0; + tx->alternate_anims = NULL; loadmodel->textures[i] = tx; // LordHavoc: force all names to lowercase and make sure they are terminated while copying @@ -394,53 +402,31 @@ void Mod_LoadTextures (lump_t *l) // find the number of frames in the animation memset (anims, 0, sizeof(anims)); memset (altanims, 0, sizeof(altanims)); + max = altmax = 0; - max = tx->name[1]; - altmax = 0; - if (max >= '0' && max <= '9') - { - max -= '0'; - altmax = 0; - anims[max] = tx; - max++; - } - else if (max >= 'a' && max <= 'j') - { - altmax = max - 'a'; - max = 0; - altanims[altmax] = tx; - altmax++; - } - else - Host_Error ("Bad animating texture %s", tx->name); - - for (j = i + 1;j < m->nummiptex;j++) + for (j = i;j < m->nummiptex;j++) { tx2 = loadmodel->textures[j]; - if (!tx2 || tx2->name[0] != '+') - continue; - if (strcmp (tx2->name+2, tx->name+2)) + if (!tx2 || tx2->name[0] != '+' || strcmp (tx2->name+2, tx->name+2)) continue; num = tx2->name[1]; if (num >= '0' && num <= '9') - { - num -= '0'; - anims[num] = tx2; - if (num+1 > max) - max = num + 1; - } + anims[num - '0'] = tx2; else if (num >= 'a' && num <= 'j') - { - num = num - 'a'; - altanims[num] = tx2; - if (num+1 > altmax) - altmax = num+1; - } + altanims[num - 'a'] = tx2; else Host_Error ("Bad animating texture %s", tx->name); } + for (j = 0;j < 10;j++) + { + if (anims[j] != NULL) + max = j + 1; + if (altanims[j] != NULL) + altmax = j + 1; + } + // link them all together for (j = 0;j < max;j++) { @@ -448,21 +434,20 @@ void Mod_LoadTextures (lump_t *l) if (!tx2) Host_Error ("Missing frame %i of %s", j, tx->name); tx2->anim_total = max; - if (altmax) - tx2->alternate_anims = altanims[0]; + tx2->alternate_anims = altanims[0]; // NULL if there is no alternate for (k = 0;k < 10;k++) - tx2->anim_frames[k] = anims[j]; + tx2->anim_frames[k] = anims[k]; } + for (j = 0;j < altmax;j++) { tx2 = altanims[j]; if (!tx2) Host_Error ("Missing frame %i of %s", j, tx->name); tx2->anim_total = altmax; - if (max) - tx2->alternate_anims = anims[0]; + tx2->alternate_anims = anims[0]; // NULL if there is no alternate for (k = 0;k < 10;k++) - tx2->anim_frames[k] = altanims[j]; + tx2->anim_frames[k] = altanims[k]; } } } @@ -472,7 +457,7 @@ void Mod_LoadTextures (lump_t *l) Mod_LoadLighting ================= */ -void Mod_LoadLighting (lump_t *l) +static void Mod_LoadLighting (lump_t *l) { int i; byte *in, *out, *data; @@ -531,7 +516,7 @@ void Mod_LoadLighting (lump_t *l) Mod_LoadVisibility ================= */ -void Mod_LoadVisibility (lump_t *l) +static void Mod_LoadVisibility (lump_t *l) { if (!l->filelen) { @@ -547,7 +532,7 @@ void Mod_LoadVisibility (lump_t *l) Mod_LoadEntities ================= */ -void Mod_LoadEntities (lump_t *l) +static void Mod_LoadEntities (lump_t *l) { if (!l->filelen) { @@ -567,7 +552,7 @@ void Mod_LoadEntities (lump_t *l) Mod_LoadVertexes ================= */ -void Mod_LoadVertexes (lump_t *l) +static void Mod_LoadVertexes (lump_t *l) { dvertex_t *in; mvertex_t *out; @@ -595,7 +580,7 @@ void Mod_LoadVertexes (lump_t *l) Mod_LoadSubmodels ================= */ -void Mod_LoadSubmodels (lump_t *l) +static void Mod_LoadSubmodels (lump_t *l) { dmodel_t *in; dmodel_t *out; @@ -632,7 +617,7 @@ void Mod_LoadSubmodels (lump_t *l) Mod_LoadEdges ================= */ -void Mod_LoadEdges (lump_t *l) +static void Mod_LoadEdges (lump_t *l) { dedge_t *in; medge_t *out; @@ -659,7 +644,7 @@ void Mod_LoadEdges (lump_t *l) Mod_LoadTexinfo ================= */ -void Mod_LoadTexinfo (lump_t *l) +static void Mod_LoadTexinfo (lump_t *l) { texinfo_t *in; mtexinfo_t *out; @@ -683,7 +668,7 @@ void Mod_LoadTexinfo (lump_t *l) miptex = LittleLong (in->miptex); out->flags = LittleLong (in->flags); - + if (!loadmodel->textures) { out->texture = &r_notexture_mip; // checkerboard texture @@ -710,7 +695,7 @@ CalcSurfaceExtents Fills in s->texturemins[] and s->extents[] ================ */ -void CalcSurfaceExtents (msurface_t *s) +static void CalcSurfaceExtents (msurface_t *s) { float mins[2], maxs[2], val; int i,j, e; @@ -722,7 +707,7 @@ void CalcSurfaceExtents (msurface_t *s) maxs[0] = maxs[1] = -99999; tex = s->texinfo; - + for (i=0 ; inumedges ; i++) { e = loadmodel->surfedges[s->firstedge+i]; @@ -764,7 +749,7 @@ void GL_SubdivideSurface (msurface_t *fa); Mod_LoadFaces ================= */ -void Mod_LoadFaces (lump_t *l) +static void Mod_LoadFaces (lump_t *l) { dface_t *in; msurface_t *out; @@ -783,13 +768,13 @@ void Mod_LoadFaces (lump_t *l) for ( surfnum=0 ; surfnumfirstedge = LittleLong(in->firstedge); - out->numedges = LittleShort(in->numedges); + out->numedges = LittleShort(in->numedges); out->flags = 0; planenum = LittleShort(in->planenum); side = LittleShort(in->side); if (side) - out->flags |= SURF_PLANEBACK; + out->flags |= SURF_PLANEBACK; out->plane = loadmodel->planes + planenum; @@ -807,10 +792,10 @@ void Mod_LoadFaces (lump_t *l) else if (hlbsp) // LordHavoc: HalfLife map (bsp version 30) out->samples = loadmodel->lightdata + i; else // LordHavoc: white lighting (bsp version 29) - out->samples = loadmodel->lightdata + (i * 3); - + out->samples = loadmodel->lightdata + (i * 3); + // set the drawing flags flag - + // if (!strncmp(out->texinfo->texture->name,"sky",3)) // sky // LordHavoc: faster check if ((out->texinfo->texture->name[0] == 's' || out->texinfo->texture->name[0] == 'S') @@ -822,7 +807,7 @@ void Mod_LoadFaces (lump_t *l) GL_SubdivideSurface (out); // cut up polygon for warps continue; } - + // if (!strncmp(out->texinfo->texture->name,"*",1)) // turbulent if (out->texinfo->texture->name[0] == '*') // LordHavoc: faster check { @@ -831,7 +816,7 @@ void Mod_LoadFaces (lump_t *l) if (!strncmp(out->texinfo->texture->name,"*lava",5) || !strncmp(out->texinfo->texture->name,"*teleport",9) || !strncmp(out->texinfo->texture->name,"*rift",5)) // Scourge of Armagon texture - out->flags |= (SURF_DRAWFULLBRIGHT | SURF_DRAWNOALPHA); + out->flags |= (SURF_DRAWFULLBRIGHT | SURF_DRAWNOALPHA | SURF_CLIPSOLID); for (i=0 ; i<2 ; i++) { out->extents[i] = 16384; @@ -840,8 +825,9 @@ void Mod_LoadFaces (lump_t *l) GL_SubdivideSurface (out); // cut up polygon for warps continue; } - - out->flags |= SURF_CLIPSOLID; + + if (!out->texinfo->texture->transparent) + out->flags |= SURF_CLIPSOLID; } } @@ -851,7 +837,7 @@ void Mod_LoadFaces (lump_t *l) Mod_SetParent ================= */ -void Mod_SetParent (mnode_t *node, mnode_t *parent) +static void Mod_SetParent (mnode_t *node, mnode_t *parent) { node->parent = parent; if (node->contents < 0) @@ -865,7 +851,7 @@ void Mod_SetParent (mnode_t *node, mnode_t *parent) Mod_LoadNodes ================= */ -void Mod_LoadNodes (lump_t *l) +static void Mod_LoadNodes (lump_t *l) { int i, j, count, p; dnode_t *in; @@ -912,7 +898,7 @@ void Mod_LoadNodes (lump_t *l) Mod_LoadLeafs ================= */ -void Mod_LoadLeafs (lump_t *l) +static void Mod_LoadLeafs (lump_t *l) { dleaf_t *in; mleaf_t *out; @@ -941,7 +927,7 @@ void Mod_LoadLeafs (lump_t *l) out->firstmarksurface = loadmodel->marksurfaces + LittleShort(in->firstmarksurface); out->nummarksurfaces = LittleShort(in->nummarksurfaces); - + p = LittleLong(in->visofs); if (p == -1) out->compressed_vis = NULL; @@ -968,7 +954,7 @@ void Mod_LoadLeafs (lump_t *l) Mod_LoadClipnodes ================= */ -void Mod_LoadClipnodes (lump_t *l) +static void Mod_LoadClipnodes (lump_t *l) { dclipnode_t *in, *out; int i, count; @@ -1065,7 +1051,7 @@ Mod_MakeHull0 Duplicate the drawing hull structure as a clipping hull ================= */ -void Mod_MakeHull0 (void) +static void Mod_MakeHull0 (void) { mnode_t *in; dclipnode_t *out; @@ -1073,7 +1059,7 @@ void Mod_MakeHull0 (void) hull_t *hull; hull = &loadmodel->hulls[0]; - + in = loadmodel->nodes; count = loadmodel->numnodes; out = Hunk_AllocName ( count*sizeof(*out), va("%s hull0", loadname)); @@ -1096,12 +1082,12 @@ void Mod_MakeHull0 (void) Mod_LoadMarksurfaces ================= */ -void Mod_LoadMarksurfaces (lump_t *l) -{ +static void Mod_LoadMarksurfaces (lump_t *l) +{ int i, j, count; short *in; msurface_t **out; - + in = (void *)(mod_base + l->fileofs); if (l->filelen % sizeof(*in)) Host_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name); @@ -1125,8 +1111,8 @@ void Mod_LoadMarksurfaces (lump_t *l) Mod_LoadSurfedges ================= */ -void Mod_LoadSurfedges (lump_t *l) -{ +static void Mod_LoadSurfedges (lump_t *l) +{ int i, count; int *in, *out; @@ -1149,13 +1135,13 @@ void Mod_LoadSurfedges (lump_t *l) Mod_LoadPlanes ================= */ -void Mod_LoadPlanes (lump_t *l) +static void Mod_LoadPlanes (lump_t *l) { int i, j; mplane_t *out; dplane_t *in; int count; - + in = (void *)(mod_base + l->fileofs); if (l->filelen % sizeof(*in)) Host_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name); @@ -1191,7 +1177,7 @@ winding_t; NewWinding ================== */ -winding_t *NewWinding (int points) +static winding_t *NewWinding (int points) { winding_t *w; int size; @@ -1206,7 +1192,7 @@ winding_t *NewWinding (int points) return w; } -void FreeWinding (winding_t *w) +static void FreeWinding (winding_t *w) { qfree (w); } @@ -1216,7 +1202,7 @@ void FreeWinding (winding_t *w) BaseWindingForPlane ================= */ -winding_t *BaseWindingForPlane (mplane_t *p) +static winding_t *BaseWindingForPlane (mplane_t *p) { vec3_t org, vright, vup; winding_t *w; @@ -1258,7 +1244,7 @@ If keepon is true, an exactly on-plane winding will be saved, otherwise it will be clipped away. ================== */ -winding_t *ClipWinding (winding_t *in, mplane_t *split, int keepon) +static winding_t *ClipWinding (winding_t *in, mplane_t *split, int keepon) { vec_t dists[MAX_POINTS_ON_WINDING + 1]; int sides[MAX_POINTS_ON_WINDING + 1]; @@ -1359,7 +1345,7 @@ returned winding will be the input winding. If on both sides, two new windings will be created. ================== */ -void DivideWinding (winding_t *in, mplane_t *split, winding_t **front, winding_t **back) +static void DivideWinding (winding_t *in, mplane_t *split, winding_t **front, winding_t **back) { vec_t dists[MAX_POINTS_ON_WINDING + 1]; int sides[MAX_POINTS_ON_WINDING + 1]; @@ -1473,7 +1459,7 @@ static portal_t *portalchain; AllocPortal =========== */ -portal_t *AllocPortal (void) +static portal_t *AllocPortal (void) { portal_t *p; p = qmalloc(sizeof(portal_t)); @@ -1483,7 +1469,7 @@ portal_t *AllocPortal (void) return p; } -void Mod_RecursiveRecalcNodeBBox(mnode_t *node) +static void Mod_RecursiveRecalcNodeBBox(mnode_t *node) { // calculate children first if (node->children[0]->contents >= 0) @@ -1500,7 +1486,7 @@ void Mod_RecursiveRecalcNodeBBox(mnode_t *node) node->maxs[2] = max(node->children[0]->maxs[2], node->children[1]->maxs[2]); } -void Mod_FinalizePortals(void) +static void Mod_FinalizePortals(void) { int i, j, numportals, numpoints; portal_t *p, *pnext; @@ -1643,7 +1629,7 @@ void Mod_FinalizePortals(void) AddPortalToNodes ============= */ -void AddPortalToNodes (portal_t *p, mnode_t *front, mnode_t *back) +static void AddPortalToNodes (portal_t *p, mnode_t *front, mnode_t *back) { if (!front) Host_Error ("AddPortalToNodes: NULL front node"); @@ -1667,7 +1653,7 @@ void AddPortalToNodes (portal_t *p, mnode_t *front, mnode_t *back) RemovePortalFromNode ============= */ -void RemovePortalFromNodes(portal_t *portal) +static void RemovePortalFromNodes(portal_t *portal) { int i; mnode_t *node; @@ -1711,7 +1697,7 @@ void RemovePortalFromNodes(portal_t *portal) } } -void Mod_RecursiveNodePortals (mnode_t *node) +static void Mod_RecursiveNodePortals (mnode_t *node) { int side; mnode_t *front, *back, *other_node; @@ -1872,7 +1858,7 @@ void Mod_MakeOutsidePortals(mnode_t *node) } */ -void Mod_MakePortals(void) +static void Mod_MakePortals(void) { // Con_Printf("building portals for %s\n", loadmodel->name); @@ -1941,6 +1927,15 @@ void Mod_LoadBrushModel (model_t *mod, void *buffer) // for (i = 0;i < mod->numsubmodels;i++) { + int k, l; + float dist, modelyawradius, modelradius, *vec; + msurface_t *surf; + + mod->normalmins[0] = mod->normalmins[1] = mod->normalmins[2] = 1000000000.0f; + mod->normalmaxs[0] = mod->normalmaxs[1] = mod->normalmaxs[2] = -1000000000.0f; + modelyawradius = 0; + modelradius = 0; + bm = &mod->submodels[i]; mod->hulls[0].firstclipnode = bm->headnode[0]; @@ -1953,13 +1948,51 @@ void Mod_LoadBrushModel (model_t *mod, void *buffer) mod->firstmodelsurface = bm->firstface; mod->nummodelsurfaces = bm->numfaces; - VectorCopy (bm->maxs, mod->maxs); - VectorCopy (bm->mins, mod->mins); + // LordHavoc: calculate bmodel bounding box rather than trusting what it says + for (j = 0, surf = &mod->surfaces[mod->firstmodelsurface];j < mod->nummodelsurfaces;j++, surf++) + { + for (k = 0;k < surf->numedges;k++) + { + l = mod->surfedges[k + surf->firstedge]; + if (l > 0) + vec = mod->vertexes[mod->edges[l].v[0]].position; + else + vec = mod->vertexes[mod->edges[-l].v[1]].position; + if (mod->normalmins[0] > vec[0]) mod->normalmins[0] = vec[0]; + if (mod->normalmins[1] > vec[1]) mod->normalmins[1] = vec[1]; + if (mod->normalmins[2] > vec[2]) mod->normalmins[2] = vec[2]; + if (mod->normalmaxs[0] < vec[0]) mod->normalmaxs[0] = vec[0]; + if (mod->normalmaxs[1] < vec[1]) mod->normalmaxs[1] = vec[1]; + if (mod->normalmaxs[2] < vec[2]) mod->normalmaxs[2] = vec[2]; + dist = vec[0]*vec[0]+vec[1]*vec[1]; + if (modelyawradius < dist) + modelyawradius = dist; + dist += vec[2]*vec[2]; + if (modelradius < dist) + modelradius = dist; + } + } + modelyawradius = sqrt(modelyawradius); + modelradius = sqrt(modelradius); + mod->yawmins[0] = mod->yawmins[1] = -(mod->yawmaxs[0] = mod->yawmaxs[1] = modelyawradius); + mod->yawmins[2] = mod->normalmins[2]; + mod->yawmaxs[2] = mod->normalmaxs[2]; + mod->rotatedmins[0] = mod->rotatedmins[1] = mod->rotatedmins[2] = -modelradius; + mod->rotatedmaxs[0] = mod->rotatedmaxs[1] = mod->rotatedmaxs[2] = modelradius; +// mod->modelradius = modelradius; + +// VectorCopy (bm->maxs, mod->maxs); +// VectorCopy (bm->mins, mod->mins); - mod->radius = RadiusFromBounds (mod->mins, mod->maxs); +// mod->radius = RadiusFromBounds (mod->mins, mod->maxs); mod->numleafs = bm->visleafs; + mod->SERAddEntity = Mod_Brush_SERAddEntity; + mod->DrawEarly = R_DrawBrushModel; + mod->DrawLate = NULL; + mod->DrawShadow = NULL; + if (isworldmodel && i < (mod->numsubmodels - 1)) // LordHavoc: only register submodels if it is the world (prevents bsp models from replacing world submodels) { // duplicate the basic information char name[10]; diff --git a/model_brush.h b/model_brush.h index bd233df2..15f73d9c 100644 --- a/model_brush.h +++ b/model_brush.h @@ -102,7 +102,6 @@ typedef struct glpolysizeof_s { struct glpoly_s *next; int numverts; - int flags; // for SURF_UNDERWATER } glpolysizeof_t; typedef struct msurface_s diff --git a/model_shared.h b/model_shared.h index 41b23104..41607664 100644 --- a/model_shared.h +++ b/model_shared.h @@ -8,7 +8,7 @@ of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. @@ -69,8 +69,10 @@ typedef struct model_s int flags2; // engine calculated flags, ones that can not be set in the file // volume occupied by the model graphics - vec3_t mins, maxs; - float radius; + vec3_t normalmins, normalmaxs; // bounding box at angles '0 0 0' + vec3_t yawmins, yawmaxs; // bounding box if yaw angle is not 0, but pitch and roll are + vec3_t rotatedmins, rotatedmaxs; // bounding box if pitch or roll are used +// float modelradius; // usable at any angles // solid volume for clipping qboolean clipbox; @@ -130,13 +132,20 @@ typedef struct model_s // LordHavoc: useful for sprites and models int numtris; int numskins; + int skinanimrange[MAX_SKINS*2]; // array of start and length pairs rtexture_t *skinanim[MAX_SKINS*5]; // texture numbers for each frame (indexed by animrange), note: normal pants shirt glow body (normal contains no shirt/pants/glow colors and body is normal + pants + shirt, but not glow) + int ofs_scenes; // offset from Mod_ExtraData(model) memory to array of animscene_t structs // these are used simply to simplify model/sprite/whatever processing and are specific to each type int ofs_frames; // offset from Mod_ExtraData(model) memory to array of model specific frame structs int framesize; // size of model specific frame structs + void (*SERAddEntity)(void); + void (*DrawEarly)(void); + void (*DrawLate)(void); + void (*DrawShadow)(void); + // additional model data cache_user_t cache; // only access through Mod_Extradata int cachesize; // size of cached data (zero if not cached) diff --git a/model_sprite.c b/model_sprite.c index d2509037..53dbb7c9 100644 --- a/model_sprite.c +++ b/model_sprite.c @@ -56,16 +56,19 @@ void Mod_Sprite_StripExtension(char *in, char *out) Mod_LoadSpriteFrame ================= */ -void * Mod_LoadSpriteFrame (void * pin, mspriteframe_t *frame, int framenum, int bytesperpixel, byte *palette) +void * Mod_LoadSpriteFrame (void * pin, mspriteframe_t *frame, int framenum, int bytesperpixel, byte *palette, float *modelradius) { dspriteframe_t *pinframe; mspriteframe_t *pspriteframe; + float dist; int i, width, height, size, origin[2]; char name[256], tempname[256]; byte *pixbuf, *pixel, *inpixel; pinframe = (dspriteframe_t *)pin; + origin[0] = LittleLong (pinframe->origin[0]); + origin[1] = LittleLong (pinframe->origin[1]); width = LittleLong (pinframe->width); height = LittleLong (pinframe->height); size = width * height * bytesperpixel; @@ -74,15 +77,17 @@ void * Mod_LoadSpriteFrame (void * pin, mspriteframe_t *frame, int framenum, int memset (pspriteframe, 0, sizeof (mspriteframe_t)); -// pspriteframe->width = width; -// pspriteframe->height = height; - origin[0] = LittleLong (pinframe->origin[0]); - origin[1] = LittleLong (pinframe->origin[1]); - + pspriteframe->left = origin[0]; + pspriteframe->right = origin[0] + width; pspriteframe->up = origin[1]; pspriteframe->down = origin[1] - height; - pspriteframe->left = origin[0]; - pspriteframe->right = width + origin[0]; + + dist = pspriteframe->left*pspriteframe->left+pspriteframe->up*pspriteframe->up; + if (*modelradius < dist) + *modelradius = dist; + dist = pspriteframe->right*pspriteframe->right+pspriteframe->down*pspriteframe->down; + if (*modelradius < dist) + *modelradius = dist; Mod_Sprite_StripExtension(loadmodel->name, tempname); sprintf (name, "%s_%i", tempname, framenum); @@ -151,7 +156,7 @@ void *Mod_LoadSpriteGroup (void * pin, mspriteframe_t *frame, int numframes, int // this actually handles both quake sprite and darkplaces sprite32 void Mod_LoadQuakeSprite (model_t *mod, void *buffer) { - int i, j, version, numframes, realframes, size, bytesperpixel, start, end, total, maxwidth, maxheight; + int i, j, version, numframes, realframes, size, bytesperpixel, start, end, total; dsprite_t *pin; msprite_t *psprite; dspriteframetype_t *pframetype; @@ -159,6 +164,9 @@ void Mod_LoadQuakeSprite (model_t *mod, void *buffer) animscene_t *animscenes; mspriteframe_t *frames; dspriteframe_t **framedata; + float modelradius; + + modelradius = 0; start = Hunk_LowMark (); @@ -191,16 +199,16 @@ void Mod_LoadQuakeSprite (model_t *mod, void *buffer) // mod->cache.data = psprite; psprite->type = LittleLong (pin->type); - maxwidth = LittleLong (pin->width); - maxheight = LittleLong (pin->height); +// maxwidth = LittleLong (pin->width); +// maxheight = LittleLong (pin->height); // psprite->beamlength = LittleFloat (pin->beamlength); mod->synctype = LittleLong (pin->synctype); // psprite->numframes = numframes; - mod->mins[0] = mod->mins[1] = -maxwidth/2; - mod->maxs[0] = mod->maxs[1] = maxwidth/2; - mod->mins[2] = -maxheight/2; - mod->maxs[2] = maxheight/2; +// mod->mins[0] = mod->mins[1] = -maxwidth/2; +// mod->maxs[0] = mod->maxs[1] = maxwidth/2; +// mod->mins[2] = -maxheight/2; +// mod->maxs[2] = maxheight/2; // // load the frames @@ -262,7 +270,7 @@ void Mod_LoadQuakeSprite (model_t *mod, void *buffer) { for (j = 0;j < animscenes[i].framecount;j++) { - Mod_LoadSpriteFrame (framedata[realframes], frames + realframes, i, bytesperpixel, (byte *)&d_8to24table); + Mod_LoadSpriteFrame (framedata[realframes], frames + realframes, i, bytesperpixel, (byte *)&d_8to24table, &modelradius); realframes++; } } @@ -273,6 +281,14 @@ void Mod_LoadQuakeSprite (model_t *mod, void *buffer) mod->type = mod_sprite; + modelradius = sqrt(modelradius); + for (i = 0;i < 3;i++) + { + mod->normalmins[i] = mod->yawmins[i] = mod->rotatedmins[i] = -modelradius; + mod->normalmaxs[i] = mod->yawmaxs[i] = mod->rotatedmaxs[i] = modelradius; + } +// mod->modelradius = modelradius; + // move the complete, relocatable sprite model to the cache end = Hunk_LowMark (); mod->cachesize = total = end - start; @@ -287,7 +303,7 @@ void Mod_LoadQuakeSprite (model_t *mod, void *buffer) void Mod_LoadHLSprite (model_t *mod, void *buffer) { - int i, j, numframes, realframes, size, start, end, total, maxwidth, maxheight, rendermode; + int i, j, numframes, realframes, size, start, end, total, rendermode; byte palette[256][4], *in; dspritehl_t *pin; msprite_t *psprite; @@ -296,6 +312,9 @@ void Mod_LoadHLSprite (model_t *mod, void *buffer) animscene_t *animscenes; mspriteframe_t *frames; dspriteframe_t **framedata; + float modelradius; + + modelradius = 0; start = Hunk_LowMark (); @@ -311,15 +330,15 @@ void Mod_LoadHLSprite (model_t *mod, void *buffer) psprite = Hunk_AllocName (sizeof(msprite_t), va("%s info", loadname)); psprite->type = LittleLong (pin->type); - maxwidth = LittleLong (pin->width); - maxheight = LittleLong (pin->height); +// maxwidth = LittleLong (pin->width); +// maxheight = LittleLong (pin->height); mod->synctype = LittleLong (pin->synctype); rendermode = pin->rendermode; - mod->mins[0] = mod->mins[1] = -maxwidth/2; - mod->maxs[0] = mod->maxs[1] = maxwidth/2; - mod->mins[2] = -maxheight/2; - mod->maxs[2] = maxheight/2; +// mod->mins[0] = mod->mins[1] = -maxwidth/2; +// mod->maxs[0] = mod->maxs[1] = maxwidth/2; +// mod->mins[2] = -maxheight/2; +// mod->maxs[2] = maxheight/2; // // load the frames @@ -434,7 +453,7 @@ void Mod_LoadHLSprite (model_t *mod, void *buffer) { for (j = 0;j < animscenes[i].framecount;j++) { - Mod_LoadSpriteFrame (framedata[realframes], frames + realframes, i, 1, &palette[0][0]); + Mod_LoadSpriteFrame (framedata[realframes], frames + realframes, i, 1, &palette[0][0], &modelradius); realframes++; } } @@ -445,6 +464,13 @@ void Mod_LoadHLSprite (model_t *mod, void *buffer) mod->type = mod_sprite; + modelradius = sqrt(modelradius); + for (i = 0;i < 3;i++) + { + mod->normalmins[i] = mod->yawmins[i] = mod->rotatedmins[i] = -modelradius; + mod->normalmaxs[i] = mod->yawmaxs[i] = mod->rotatedmaxs[i] = modelradius; + } + // move the complete, relocatable sprite model to the cache end = Hunk_LowMark (); mod->cachesize = total = end - start; @@ -457,6 +483,11 @@ void Mod_LoadHLSprite (model_t *mod, void *buffer) Hunk_FreeToLowMark (start); } +void Mod_Sprite_SERAddEntity(void) +{ + R_ClipSprite(); +} + /* ================= @@ -480,4 +511,8 @@ void Mod_LoadSpriteModel (model_t *mod, void *buffer) Host_Error ("Mod_LoadSpriteModel: %s has wrong version number (%i should be 1 (quake) or 32 (sprite32) or 2 (halflife)", mod->name, version); break; } + mod->SERAddEntity = Mod_Sprite_SERAddEntity; + mod->DrawEarly = R_DrawSpriteModel; + mod->DrawLate = NULL; + mod->DrawShadow = NULL; } diff --git a/portals.c b/portals.c index 742f6d36..35752988 100644 --- a/portals.c +++ b/portals.c @@ -14,7 +14,7 @@ static int portal_markid = 0; //float viewportalpoints[16*3]; static float boxpoints[4*3]; -int R_ClipPolygonToPlane(float *in, float *out, int inpoints, int maxoutpoints, tinyplane_t *p) +int Portal_ClipPolygonToPlane(float *in, float *out, int inpoints, int maxoutpoints, tinyplane_t *p) { int i, outpoints, prevside, side; float *prevpoint, prevdist, dist, dot; @@ -67,7 +67,7 @@ begin: } /* -void R_TriangleToPlane(vec3_t point1, vec3_t point2, vec3_t point3, tinyplane_t *p) +void Portal_TriangleToPlane(vec3_t point1, vec3_t point2, vec3_t point3, tinyplane_t *p) { vec3_t v1, v2; VectorSubtract(point1, point2, v1); @@ -79,7 +79,7 @@ void R_TriangleToPlane(vec3_t point1, vec3_t point2, vec3_t point3, tinyplane_t } */ -int R_PortalThroughPortalPlanes(tinyplane_t *clipplanes, int clipnumplanes, float *targpoints, int targnumpoints, float *out, int maxpoints) +int Portal_PortalThroughPortalPlanes(tinyplane_t *clipplanes, int clipnumplanes, float *targpoints, int targnumpoints, float *out, int maxpoints) { int numpoints, i; if (targnumpoints < 3) @@ -90,7 +90,7 @@ int R_PortalThroughPortalPlanes(tinyplane_t *clipplanes, int clipnumplanes, floa memcpy(&portaltemppoints[0][0][0], targpoints, numpoints * 3 * sizeof(float)); for (i = 0;i < clipnumplanes;i++) { - numpoints = R_ClipPolygonToPlane(&portaltemppoints[0][0][0], &portaltemppoints[1][0][0], numpoints, 256, clipplanes + i); + numpoints = Portal_ClipPolygonToPlane(&portaltemppoints[0][0][0], &portaltemppoints[1][0][0], numpoints, 256, clipplanes + i); if (numpoints < 3) return numpoints; memcpy(&portaltemppoints[0][0][0], &portaltemppoints[1][0][0], numpoints * 3 * sizeof(float)); @@ -117,7 +117,7 @@ int Portal_RecursiveFlowSearch (mleaf_t *leaf, vec3_t eye, int firstclipplane, i // only flow through portals facing away from the viewer if (PlaneDiff(eye, (&p->plane)) < 0) { - newpoints = R_PortalThroughPortalPlanes(&portalplanes[firstclipplane], numclipplanes, (float *) p->points, p->numpoints, &portaltemppoints2[0][0], 256); + newpoints = Portal_PortalThroughPortalPlanes(&portalplanes[firstclipplane], numclipplanes, (float *) p->points, p->numpoints, &portaltemppoints2[0][0], 256); if (newpoints < 3) continue; else if (firstclipplane + numclipplanes + newpoints > MAXRECURSIVEPORTALPLANES) @@ -134,7 +134,7 @@ int Portal_RecursiveFlowSearch (mleaf_t *leaf, vec3_t eye, int firstclipplane, i newplanes = &portalplanes[firstclipplane + numclipplanes]; for (prev = newpoints - 1, i = 0;i < newpoints;prev = i, i++) { -// R_TriangleToPlane(eye, portaltemppoints2[i], portaltemppoints2[prev], newplanes + i); +// Portal_TriangleToPlane(eye, portaltemppoints2[i], portaltemppoints2[prev], newplanes + i); VectorSubtract(eye, portaltemppoints2[i], v1); VectorSubtract(portaltemppoints2[prev], portaltemppoints2[i], v2); CrossProduct(v1, v2, newplanes[i].normal); @@ -217,7 +217,7 @@ int Portal_CheckPolygon(model_t *model, vec3_t eye, float *polypoints, int numpo // calculate the planes, and make sure the polygon can see it's own center for (prev = numpoints - 1, i = 0;i < numpoints;prev = i, i++) { -// R_TriangleToPlane(eye, portaltemppoints2[i], portaltemppoints2[prev], newplanes + i); +// Portal_TriangleToPlane(eye, portaltemppoints2[i], portaltemppoints2[prev], newplanes + i); VectorSubtract(eye, (&polypoints[i * 3]), v1); VectorSubtract((&polypoints[prev * 3]), (&polypoints[i * 3]), v2); CrossProduct(v1, v2, portalplanes[i].normal); diff --git a/pr_cmds.c b/pr_cmds.c index 49cc08d2..d5ba3329 100644 --- a/pr_cmds.c +++ b/pr_cmds.c @@ -262,7 +262,7 @@ void SetMinMaxSize (edict_t *e, float *min, float *max, qboolean rotate) VectorCopy (min, bounds[0]); VectorCopy (max, bounds[1]); - + rmin[0] = rmin[1] = rmin[2] = 9999; rmax[0] = rmax[1] = rmax[2] = -9999; @@ -350,16 +350,16 @@ void PF_setmodel (void) for (i=0, check = sv.model_precache ; *check ; i++, check++) if (!strcmp(*check, m)) break; - + if (!*check) PR_RunError ("no precache: %s\n", m); - + e->v.model = m - pr_strings; e->v.modelindex = i; //SV_ModelIndex (m); mod = sv.models[ (int)e->v.modelindex]; // Mod_ForName (m, true); - + if (mod) /* { // LordHavoc: corrected model bounding box, but for compatibility that means I have to break it here @@ -374,7 +374,7 @@ void PF_setmodel (void) SetMinMaxSize (e, mod->mins, mod->maxs, true); } */ - SetMinMaxSize (e, mod->mins, mod->maxs, true); + SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true); else SetMinMaxSize (e, vec3_origin, vec3_origin, true); } @@ -764,11 +764,12 @@ void PF_traceline (void) pr_global_struct->trace_inopen = trace.inopen; VectorCopy (trace.endpos, pr_global_struct->trace_endpos); VectorCopy (trace.plane.normal, pr_global_struct->trace_plane_normal); - pr_global_struct->trace_plane_dist = trace.plane.dist; + pr_global_struct->trace_plane_dist = trace.plane.dist; if (trace.ent) pr_global_struct->trace_ent = EDICT_TO_PROG(trace.ent); else pr_global_struct->trace_ent = EDICT_TO_PROG(sv.edicts); + // FIXME: add trace_endcontents } diff --git a/pr_edict.c b/pr_edict.c index c7e722ab..5b348ff5 100644 --- a/pr_edict.c +++ b/pr_edict.c @@ -454,7 +454,7 @@ char *PR_UglyValueString (etype_t type, eval_t *val) case ev_string: sprintf (line, "%s", pr_strings + val->string); break; - case ev_entity: + case ev_entity: sprintf (line, "%i", NUM_FOR_EDICT(PROG_TO_EDICT(val->edict))); break; case ev_function: @@ -501,7 +501,7 @@ char *PR_GlobalString (int ofs) val = (void *)&pr_globals[ofs]; def = ED_GlobalAtOfs(ofs); if (!def) - sprintf (line,"%i(??\?)", ofs); // LordHavoc: escaping the third ? so it is not a trigraph + sprintf (line,"%i(\?\?\?)", ofs); // LordHavoc: escaping the ?s so it is not a trigraph else { s = PR_ValueString (def->type, val); @@ -524,7 +524,7 @@ char *PR_GlobalStringNoContents (int ofs) def = ED_GlobalAtOfs(ofs); if (!def) - sprintf (line,"%i(??\?)", ofs); // LordHavoc: escaping the third ? so it is not a trigraph + sprintf (line,"%i(\?\?\?)", ofs); // LordHavoc: escaping the ?s so it is not a trigraph else sprintf (line,"%i(%s)", ofs, pr_strings + def->s_name); @@ -849,7 +849,7 @@ char *ED_NewString (char *string) else *new_p++ = string[i]; } - + return new; } @@ -870,9 +870,9 @@ qboolean ED_ParseEpair (void *base, ddef_t *key, char *s) char *v, *w; void *d; dfunction_t *func; - + d = (void *)((int *)base + key->ofs); - + switch (key->type & ~DEF_SAVEGLOBAL) { case ev_string: @@ -986,7 +986,7 @@ if (!strcmp(com_token, "light")) n--; } - // parse value + // parse value data = COM_Parse (data); if (!data) Host_Error ("ED_ParseEntity: EOF without closing brace"); @@ -1113,12 +1113,59 @@ void ED_LoadFromFile (char *data) pr_global_struct->self = EDICT_TO_PROG(ent); PR_ExecuteProgram (func - pr_functions, ""); - } + } Con_DPrintf ("%i entities inhibited\n", inhibit); } +typedef struct dpfield_s +{ + int type; + char *string; +} +dpfield_t; + +#define DPFIELDS (sizeof(dpfields) / sizeof(dpfield_t)) + +dpfield_t dpfields[] = +{ + {ev_float, "gravity"}, + {ev_float, "button3"}, + {ev_float, "button4"}, + {ev_float, "button5"}, + {ev_float, "button6"}, + {ev_float, "button7"}, + {ev_float, "button8"}, + {ev_float, "glow_size"}, + {ev_float, "glow_trail"}, + {ev_float, "glow_color"}, + {ev_float, "items2"}, + {ev_float, "scale"}, + {ev_float, "alpha"}, + {ev_float, "renderamt"}, + {ev_float, "rendermode"}, + {ev_float, "fullbright"}, + {ev_float, "ammo_shells1"}, + {ev_float, "ammo_nails1"}, + {ev_float, "ammo_lava_nails"}, + {ev_float, "ammo_rockets1"}, + {ev_float, "ammo_multi_rockets"}, + {ev_float, "ammo_cells1"}, + {ev_float, "ammo_plasma"}, + {ev_float, "idealpitch"}, + {ev_float, "pitch_speed"}, + {ev_entity, "viewmodelforclient"}, + {ev_entity, "nodrawtoclient"}, + {ev_entity, "exteriormodeltoclient"}, + {ev_entity, "drawonlytoclient"}, + {ev_vector, "colormod"}, + {ev_float, "ping"}, + {ev_vector, "movement"}, + {ev_float, "pmodel"}, + {ev_vector, "punchvector"} +}; + /* =============== PR_LoadProgs @@ -1126,8 +1173,9 @@ PR_LoadProgs */ void PR_LoadProgs (void) { - int i; + int i; dstatement_t *st; + ddef_t *infielddefs; // flush the non-C variable lookup cache for (i=0 ; iversion != PROG_VERSION) Host_Error ("progs.dat has wrong version number (%i should be %i)", progs->version, PROG_VERSION); @@ -1152,15 +1200,18 @@ void PR_LoadProgs (void) pr_functions = (dfunction_t *)((byte *)progs + progs->ofs_functions); pr_strings = (char *)progs + progs->ofs_strings; pr_globaldefs = (ddef_t *)((byte *)progs + progs->ofs_globaldefs); - pr_fielddefs = (ddef_t *)((byte *)progs + progs->ofs_fielddefs); + + // we need to expand the fielddefs list to include all the engine fields, + // so allocate a new place for it + infielddefs = (ddef_t *)((byte *)progs + progs->ofs_fielddefs); + pr_fielddefs = Hunk_AllocName((progs->numfielddefs + DPFIELDS) * sizeof(ddef_t), "progs fields\n"); + pr_statements = (dstatement_t *)((byte *)progs + progs->ofs_statements); + // moved edict_size calculation down below field adding code + pr_global_struct = (globalvars_t *)((byte *)progs + progs->ofs_globals); pr_globals = (float *)pr_global_struct; - - pr_edict_size = progs->entityfields * 4 + sizeof (edict_t) - sizeof(entvars_t); - - pr_edictareasize = pr_edict_size * MAX_EDICTS; // byte swap the lumps for (i=0 ; inumstatements ; i++) @@ -1179,7 +1230,7 @@ void PR_LoadProgs (void) pr_functions[i].s_file = LittleLong (pr_functions[i].s_file); pr_functions[i].numparms = LittleLong (pr_functions[i].numparms); pr_functions[i].locals = LittleLong (pr_functions[i].locals); - } + } for (i=0 ; inumglobaldefs ; i++) { @@ -1188,18 +1239,37 @@ void PR_LoadProgs (void) pr_globaldefs[i].s_name = LittleLong (pr_globaldefs[i].s_name); } - for (i=0 ; inumfielddefs ; i++) + // copy the progs fields to the new fields list + for (i = 0;i < progs->numfielddefs;i++) { - pr_fielddefs[i].type = LittleShort (pr_fielddefs[i].type); + pr_fielddefs[i].type = LittleShort (infielddefs[i].type); if (pr_fielddefs[i].type & DEF_SAVEGLOBAL) Host_Error ("PR_LoadProgs: pr_fielddefs[i].type & DEF_SAVEGLOBAL"); - pr_fielddefs[i].ofs = LittleShort (pr_fielddefs[i].ofs); - pr_fielddefs[i].s_name = LittleLong (pr_fielddefs[i].s_name); + pr_fielddefs[i].ofs = LittleShort (infielddefs[i].ofs); + pr_fielddefs[i].s_name = LittleLong (infielddefs[i].s_name); + } + + // append the darkplaces fields + for (i = 0;i < DPFIELDS;i++) + { + pr_fielddefs[progs->numfielddefs].type = dpfields[i].type; + pr_fielddefs[progs->numfielddefs].ofs = progs->entityfields; + pr_fielddefs[progs->numfielddefs].s_name = dpfields[i].string - pr_strings; + if (pr_fielddefs[progs->numfielddefs].type == ev_vector) + progs->entityfields += 3; + else + progs->entityfields++; + progs->numfielddefs++; } for (i=0 ; inumglobals ; i++) ((int *)pr_globals)[i] = LittleLong (((int *)pr_globals)[i]); + // moved edict_size calculation down here, below field adding code + pr_edict_size = progs->entityfields * 4 + sizeof (edict_t) - sizeof(entvars_t); + + pr_edictareasize = pr_edict_size * MAX_EDICTS; + // LordHavoc: bounds check anything static for (i = 0,st = pr_statements;i < progs->numstatements;i++,st++) { @@ -1357,7 +1427,7 @@ void PR_Init (void) // LordHavoc: for DarkPlaces, this overrides the number of decors (shell casings, gibs, etc) Cvar_RegisterVariable (&decors); // LordHavoc: Nehahra uses these to pass data around cutscene demos - if (nehahra) + if (gamemode == GAME_NEHAHRA) { Cvar_RegisterVariable (&nehx00);Cvar_RegisterVariable (&nehx01); Cvar_RegisterVariable (&nehx02);Cvar_RegisterVariable (&nehx03); diff --git a/quakedef.h b/quakedef.h index 24025549..f9fbe204 100644 --- a/quakedef.h +++ b/quakedef.h @@ -21,8 +21,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define QUAKE_GAME // as opposed to utilities -#define VERSION 1.50 - extern int buildnumber; #ifndef FALSE diff --git a/r_clip.c b/r_clip.c index 1f59dc32..eb5f6fa6 100644 --- a/r_clip.c +++ b/r_clip.c @@ -100,8 +100,8 @@ void R_Clip_StartFrame(void) { int i; int newwidth, newheight, newmaxedges, newmaxsurfs; - newwidth = bound(80, (int) r_clipwidth.value, vid.width * 2); - newheight = bound(60, (int) r_clipheight.value, vid.height * 2); + newwidth = bound(80, (int) r_clipwidth.value, vid.realwidth * 2); + newheight = bound(60, (int) r_clipheight.value, vid.realheight * 2); newmaxedges = bound(128, (int) r_clipedges.value, 262144); newmaxsurfs = bound(32, (int) r_clipsurfaces.value, 65536); if (newwidth != clipwidth || newheight != clipheight || maxclipedges != newmaxedges || maxclipsurfs != newmaxsurfs) @@ -910,10 +910,10 @@ void R_Clip_DisplayBuffer(void) } glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, clipwidth, clipheight, GL_LUMINANCE, GL_UNSIGNED_BYTE, clipbuffertex); glBegin (GL_QUADS); - glTexCoord2f (0 , 0 );glVertex2f (0 , 0 ); - glTexCoord2f (clipwidth / 256.0f, 0 );glVertex2f (vid.width, 0 ); - glTexCoord2f (clipwidth / 256.0f, clipheight / 256.0f);glVertex2f (vid.width, vid.height); - glTexCoord2f (0 , clipheight / 256.0f);glVertex2f (0 , vid.height); + glTexCoord2f (0 , 0 );glVertex2f (0 , 0 ); + glTexCoord2f (clipwidth / 256.0f, 0 );glVertex2f (vid.conwidth, 0 ); + glTexCoord2f (clipwidth / 256.0f, clipheight / 256.0f);glVertex2f (vid.conwidth, vid.conheight); + glTexCoord2f (0 , clipheight / 256.0f);glVertex2f (0 , vid.conheight); glEnd (); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); diff --git a/r_crosshairs.c b/r_crosshairs.c index de0c1a08..5872d569 100644 --- a/r_crosshairs.c +++ b/r_crosshairs.c @@ -138,7 +138,6 @@ void DrawCrosshair(int num) { byte *color; float scale, base; -// Draw_Character (r_refdef.vrect.x + r_refdef.vrect.width/2, r_refdef.vrect.y + r_refdef.vrect.height/2, '+'); if (num < 0 || num >= NUMCROSSHAIRS) num = 0; if (cl.viewentity) @@ -158,6 +157,6 @@ void DrawCrosshair(int num) else base = 0.0f; scale = crosshair_brightness.value / 255.0f; - Draw_GenericPic(crosshairtex[num], color[0] * scale + base, color[1] * scale + base, color[2] * scale + base, crosshair_alpha.value, r_refdef.vrect.x + r_refdef.vrect.width * 0.5f - 8.0f, r_refdef.vrect.y + r_refdef.vrect.height * 0.5f - 8.0f, 16.0f, 16.0f); + Draw_GenericPic(crosshairtex[num], color[0] * scale + base, color[1] * scale + base, color[2] * scale + base, crosshair_alpha.value, vid.conwidth * 0.5f - 8.0f, vid.conheight * 0.5f - 8.0f, 16.0f, 16.0f); } diff --git a/r_decals.c b/r_decals.c index 8f8176aa..6c45f70e 100644 --- a/r_decals.c +++ b/r_decals.c @@ -26,6 +26,7 @@ typedef struct decal_s { vec3_t org; vec3_t direction; + vec2_t texcoord[4]; vec3_t vert[4]; byte color[4]; rtexture_t *tex; @@ -85,7 +86,7 @@ loc0: return; ndist = PlaneDiff(decalorg, node->plane); - + if (ndist > 16) { node = node->children[0]; @@ -155,7 +156,7 @@ loc0: } } -void R_Decal(vec3_t org, rtexture_t *tex, float scale, int cred, int cgreen, int cblue, int alpha) +void R_Decal(vec3_t org, rtexture_t *tex, float s1, float t1, float s2, float t2, float scale, int cred, int cgreen, int cblue, int alpha) { vec3_t center, right, up; decal_t *decal; @@ -194,16 +195,24 @@ void R_Decal(vec3_t org, rtexture_t *tex, float scale, int cred, int cgreen, int // set up the 4 corners scale *= 0.5f; VectorVectors(decal->direction, right, up); - decal->vert[0][0] = center[0] - right[0] * scale - up[0] * scale; // texcoords 0 1 + decal->texcoord[0][0] = s1; + decal->texcoord[0][1] = t1; + decal->vert[0][0] = center[0] - right[0] * scale - up[0] * scale; decal->vert[0][1] = center[1] - right[1] * scale - up[1] * scale; decal->vert[0][2] = center[2] - right[2] * scale - up[2] * scale; - decal->vert[1][0] = center[0] - right[0] * scale + up[0] * scale; // texcoords 0 0 + decal->texcoord[1][0] = s1; + decal->texcoord[1][1] = t2; + decal->vert[1][0] = center[0] - right[0] * scale + up[0] * scale; decal->vert[1][1] = center[1] - right[1] * scale + up[1] * scale; decal->vert[1][2] = center[2] - right[2] * scale + up[2] * scale; - decal->vert[2][0] = center[0] + right[0] * scale + up[0] * scale; // texcoords 1 0 + decal->texcoord[2][0] = s2; + decal->texcoord[2][1] = t2; + decal->vert[2][0] = center[0] + right[0] * scale + up[0] * scale; decal->vert[2][1] = center[1] + right[1] * scale + up[1] * scale; decal->vert[2][2] = center[2] + right[2] * scale + up[2] * scale; - decal->vert[3][0] = center[0] + right[0] * scale - up[0] * scale; // texcoords 1 1 + decal->texcoord[3][0] = s2; + decal->texcoord[3][1] = t1; + decal->vert[3][0] = center[0] + right[0] * scale - up[0] * scale; decal->vert[3][1] = center[1] + right[1] * scale - up[1] * scale; decal->vert[3][2] = center[2] + right[2] * scale - up[2] * scale; // store the color @@ -223,8 +232,8 @@ void R_Decal(vec3_t org, rtexture_t *tex, float scale, int cred, int cgreen, int void GL_DrawDecals (void) { decal_t *p; - int i, j, k, dynamiclight, bits, texnum; - float scale, fr, fg, fb, dist, rad, mindist; + int i, j, k, dynamiclight, bits, texnum, iscale, ir, ig, ib, lit, cr, cg, cb; + float /*fscale, */fr, fg, fb, dist, rad, mindist; byte *lightmap; vec3_t v; msurface_t *surf; @@ -241,7 +250,7 @@ void GL_DrawDecals (void) { glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glEnable(GL_BLEND); - glShadeModel(GL_FLAT); +// glShadeModel(GL_FLAT); glDepthMask(0); // disable zbuffer updates glDisable(GL_ALPHA_TEST); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); @@ -268,54 +277,11 @@ void GL_DrawDecals (void) // get the surface lighting surf = p->surface; lightmap = p->lightmapaddress; - fr = fg = fb = 0.0f; - if (lightmap) - { - if (surf->styles[0] != 255) - { - scale = d_lightstylevalue[surf->styles[0]] * (1.0f / 256.0f); - fr += lightmap[0] * scale; - fg += lightmap[1] * scale; - fb += lightmap[2] * scale; - if (surf->styles[1] != 255) - { - lightmap += p->lightmapstep; - scale = d_lightstylevalue[surf->styles[1]] * (1.0f / 256.0f); - fr += lightmap[0] * scale; - fg += lightmap[1] * scale; - fb += lightmap[2] * scale; - if (surf->styles[2] != 255) - { - lightmap += p->lightmapstep; - scale = d_lightstylevalue[surf->styles[2]] * (1.0f / 256.0f); - fr += lightmap[0] * scale; - fg += lightmap[1] * scale; - fb += lightmap[2] * scale; - if (surf->styles[3] != 255) - { - lightmap += p->lightmapstep; - scale = d_lightstylevalue[surf->styles[3]] * (1.0f / 256.0f); - fr += lightmap[0] * scale; - fg += lightmap[1] * scale; - fb += lightmap[2] * scale; - } - } - } - } - /* - for (j = 0;j < MAXLIGHTMAPS && surf->styles[j] != 255;j++) - { - scale = d_lightstylevalue[surf->styles[j]] * (1.0f / 256.0f); - fr += lightmap[0] * scale; - fg += lightmap[1] * scale; - fb += lightmap[2] * scale; - lightmap += p->lightmapstep; - } - */ - } // dynamic lighting + lit = false; if (dynamiclight) { + fr = fg = fb = 0.0f; if (surf->dlightframe == r_framecount) { for (j = 0;j < 8;j++) @@ -337,6 +303,7 @@ void GL_DrawDecals (void) fr += rad * dl->color[0]; fg += rad * dl->color[1]; fb += rad * dl->color[2]; + lit = true; } } } @@ -344,6 +311,105 @@ void GL_DrawDecals (void) } } } + if (lit) + { +#if SLOWMATH + ir = fr * 256.0f; + ig = fg * 256.0f; + ib = fb * 256.0f; +#else + fr += 8388608.0f; + fg += 8388608.0f; + fb += 8388608.0f; + ir = (*((long *)&fr) & 0x7FFFFF) << 8; + ig = (*((long *)&fg) & 0x7FFFFF) << 8; + ib = (*((long *)&fb) & 0x7FFFFF) << 8; +#endif + } + else + ir = ig = ib = 0; +#if 1 + if (lightmap) + { + if (surf->styles[0] != 255) + { + iscale = d_lightstylevalue[surf->styles[0]]; + ir += lightmap[0] * iscale; + ig += lightmap[1] * iscale; + ib += lightmap[2] * iscale; + if (surf->styles[1] != 255) + { + lightmap += p->lightmapstep; + iscale = d_lightstylevalue[surf->styles[1]]; + ir += lightmap[0] * iscale; + ig += lightmap[1] * iscale; + ib += lightmap[2] * iscale; + if (surf->styles[2] != 255) + { + lightmap += p->lightmapstep; + iscale = d_lightstylevalue[surf->styles[2]]; + ir += lightmap[0] * iscale; + ig += lightmap[1] * iscale; + ib += lightmap[2] * iscale; + if (surf->styles[3] != 255) + { + lightmap += p->lightmapstep; + iscale = d_lightstylevalue[surf->styles[3]]; + ir += lightmap[0] * iscale; + ig += lightmap[1] * iscale; + ib += lightmap[2] * iscale; + } + } + } + } + } +#else + fr = fg = fb = 0.0f; + if (lightmap) + { + if (surf->styles[0] != 255) + { + fscale = d_lightstylevalue[surf->styles[0]] * (1.0f / 256.0f); + fr += lightmap[0] * fscale; + fg += lightmap[1] * fscale; + fb += lightmap[2] * fscale; + if (surf->styles[1] != 255) + { + lightmap += p->lightmapstep; + fscale = d_lightstylevalue[surf->styles[1]] * (1.0f / 256.0f); + fr += lightmap[0] * fscale; + fg += lightmap[1] * fscale; + fb += lightmap[2] * fscale; + if (surf->styles[2] != 255) + { + lightmap += p->lightmapstep; + fscale = d_lightstylevalue[surf->styles[2]] * (1.0f / 256.0f); + fr += lightmap[0] * fscale; + fg += lightmap[1] * fscale; + fb += lightmap[2] * fscale; + if (surf->styles[3] != 255) + { + lightmap += p->lightmapstep; + fscale = d_lightstylevalue[surf->styles[3]] * (1.0f / 256.0f); + fr += lightmap[0] * fscale; + fg += lightmap[1] * fscale; + fb += lightmap[2] * fscale; + } + } + } + } + /* + for (j = 0;j < MAXLIGHTMAPS && surf->styles[j] != 255;j++) + { + fscale = d_lightstylevalue[surf->styles[j]] * (1.0f / 256.0f); + fr += lightmap[0] * fscale; + fg += lightmap[1] * fscale; + fb += lightmap[2] * fscale; + lightmap += p->lightmapstep; + } + */ + } +#endif /* { int ir, ig, ib; @@ -376,21 +442,40 @@ void GL_DrawDecals (void) glBindTexture(GL_TEXTURE_2D, texnum); glBegin(GL_QUADS); } + /* if (lighthalf) glColor4f(fr * p->color[0] * (1.0f / 255.0f / 256.0f), fg * p->color[1] * (1.0f / 255.0f / 256.0f), fb * p->color[2] * (1.0f / 255.0f / 256.0f), p->color[3] * (1.0f / 255.0f)); else glColor4f(fr * p->color[0] * (1.0f / 255.0f / 128.0f), fg * p->color[1] * (1.0f / 255.0f / 128.0f), fb * p->color[2] * (1.0f / 255.0f / 128.0f), p->color[3] * (1.0f / 255.0f)); - glTexCoord2f(0, 1); + */ + if (lighthalf) + { + cr = (ir * p->color[0]) >> 16; + cg = (ig * p->color[1]) >> 16; + cb = (ib * p->color[2]) >> 16; + } + else + { + cr = (ir * p->color[0]) >> 15; + cg = (ig * p->color[1]) >> 15; + cb = (ib * p->color[2]) >> 15; + } + cr = min(cr, 255); + cg = min(cg, 255); + cb = min(cb, 255); + glColor4ub(cr, cg, cb, p->color[3]); + + glTexCoord2f(p->texcoord[0][0], p->texcoord[0][1]); glVertex3fv(p->vert[0]); - glTexCoord2f(0, 0); + glTexCoord2f(p->texcoord[1][0], p->texcoord[1][1]); glVertex3fv(p->vert[1]); - glTexCoord2f(1, 0); + glTexCoord2f(p->texcoord[2][0], p->texcoord[2][1]); glVertex3fv(p->vert[2]); - glTexCoord2f(1, 1); + glTexCoord2f(p->texcoord[3][0], p->texcoord[3][1]); glVertex3fv(p->vert[3]); } } - + if (r_render.value) { glEnd(); diff --git a/r_decals.h b/r_decals.h index 9d2924cb..87939658 100644 --- a/r_decals.h +++ b/r_decals.h @@ -3,4 +3,4 @@ void R_Decals_Init(void); void GL_DrawDecals(void); -void R_Decal(vec3_t org, rtexture_t *tex, float scale, int cred, int cgreen, int cblue, int alpha); +void R_Decal(vec3_t org, rtexture_t *tex, float s1, float t1, float s2, float t2, float scale, int cred, int cgreen, int cblue, int alpha); diff --git a/r_explosion.c b/r_explosion.c index db67b390..8061b606 100644 --- a/r_explosion.c +++ b/r_explosion.c @@ -8,7 +8,7 @@ of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. @@ -20,16 +20,32 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "quakedef.h" -float TraceLine (vec3_t start, vec3_t end, vec3_t impact, vec3_t normal); - #define MAX_EXPLOSIONS 64 #define EXPLOSIONGRID 16 #define EXPLOSIONVERTS ((EXPLOSIONGRID+1)*(EXPLOSIONGRID+1)) #define EXPLOSIONTRIS (EXPLOSIONVERTS*2) -#define EXPLOSIONSTARTRADIUS (0.0f) -#define EXPLOSIONSTARTVELOCITY (500.0f) +#define EXPLOSIONSTARTRADIUS (20.0f) +#define EXPLOSIONSTARTVELOCITY (256.0f) #define EXPLOSIONFADESTART (1.5f) -#define EXPLOSIONFADERATE (6.0f) +#define EXPLOSIONFADERATE (4.5f) +/* +#define MAX_EXPLOSIONGAS (MAX_EXPLOSIONS * EXPLOSIONGAS) +#define EXPLOSIONGAS 8 +#define EXPLOSIONGASSTARTRADIUS (15.0f) +#define EXPLOSIONGASSTARTVELOCITY (50.0f) +#define GASDENSITY_SCALER (32768.0f / EXPLOSIONGAS) +#define GASFADERATE (GASDENSITY_SCALER * EXPLOSIONGAS * 2) + +typedef struct explosiongas_s +{ + float pressure; + vec3_t origin; + vec3_t velocity; +} +explosiongas_t; + +explosiongas_t explosiongas[MAX_EXPLOSIONGAS]; +*/ vec3_t explosionspherevert[EXPLOSIONVERTS]; vec3_t explosionspherevertvel[EXPLOSIONVERTS]; @@ -47,7 +63,7 @@ typedef struct explosion_s } explosion_t; -explosion_t explosion[128]; +explosion_t explosion[MAX_EXPLOSIONS]; rtexture_t *explosiontexture; rtexture_t *explosiontexturefog; @@ -75,19 +91,20 @@ int R_ExplosionVert(int column, int row) void r_explosion_start(void) { int x, y; - byte noise1[128][128], noise2[128][128], data[128][128][4]; - fractalnoise(&noise1[0][0], 128, 2); - fractalnoise(&noise2[0][0], 128, 2); + byte noise1[128][128], noise2[128][128], noise3[128][128], data[128][128][4]; + fractalnoise(&noise1[0][0], 128, 32); + fractalnoise(&noise2[0][0], 128, 4); + fractalnoise(&noise3[0][0], 128, 4); for (y = 0;y < 128;y++) { for (x = 0;x < 128;x++) { int j, r, g, b, a; - j = noise1[y][x] * 3 - 128; + j = (noise1[y][x] * noise2[y][x]) * 3 / 256 - 128; r = (j * 512) / 256; g = (j * 256) / 256; b = (j * 128) / 256; - a = noise2[y][x]; + a = noise3[y][x] * 3 - 128; data[y][x][0] = bound(0, r, 255); data[y][x][1] = bound(0, g, 255); data[y][x][2] = bound(0, b, 255); @@ -108,6 +125,7 @@ void r_explosion_shutdown(void) void r_explosion_newmap(void) { memset(explosion, 0, sizeof(explosion)); +// memset(explosiongas, 0, sizeof(explosiongas)); } void R_Explosion_Init(void) @@ -147,9 +165,9 @@ void R_Explosion_Init(void) void R_NewExplosion(vec3_t org) { int i, j; - float dist; + float dist, v[3]; byte noise[EXPLOSIONGRID*EXPLOSIONGRID]; - fractalnoise(noise, EXPLOSIONGRID, 2); + fractalnoise(noise, EXPLOSIONGRID, 4); for (i = 0;i < MAX_EXPLOSIONS;i++) { if (explosion[i].alpha <= 0.0f) @@ -157,17 +175,35 @@ void R_NewExplosion(vec3_t org) explosion[i].alpha = EXPLOSIONFADESTART; for (j = 0;j < EXPLOSIONVERTS;j++) { - dist = noise[explosionnoiseindex[j]] * (1.0f / 512.0f) + 0.5; - explosion[i].vert[j][0] = explosionspherevert[j][0] * dist + org[0]; - explosion[i].vert[j][1] = explosionspherevert[j][1] * dist + org[1]; - explosion[i].vert[j][2] = explosionspherevert[j][2] * dist + org[2]; - explosion[i].vertvel[j][0] = explosionspherevertvel[j][0] * dist; - explosion[i].vertvel[j][1] = explosionspherevertvel[j][1] * dist; - explosion[i].vertvel[j][2] = explosionspherevertvel[j][2] * dist; + dist = noise[explosionnoiseindex[j]] * (1.0f / 256.0f) + 0.5; + VectorMA(org, dist, explosionspherevert[j], v); + TraceLine(org, v, explosion[i].vert[j], NULL, 0); + VectorScale(explosionspherevertvel[j], dist, explosion[i].vertvel[j]); } break; } } + + /* + i = 0; + j = EXPLOSIONGAS; + while (i < MAX_EXPLOSIONGAS && j > 0) + { + while (explosiongas[i].pressure > 0) + { + i++; + if (i >= MAX_EXPLOSIONGAS) + return; + } + VectorRandom(v); + VectorMA(org, EXPLOSIONGASSTARTRADIUS, v, v); + TraceLine(org, v, explosiongas[i].origin, NULL, 0); + VectorRandom(v); + VectorScale(v, EXPLOSIONGASSTARTVELOCITY, explosiongas[i].velocity); + explosiongas[i].pressure = j * GASDENSITY_SCALER; + j--; + } + */ } void R_DrawExplosion(explosion_t *e) @@ -205,11 +241,19 @@ void R_DrawExplosion(explosion_t *e) } } -void R_MoveExplosion(explosion_t *e, float frametime) +void R_MoveExplosion(explosion_t *e, /*explosiongas_t **list, explosiongas_t **listend, */float frametime) { int i; vec3_t end; + vec_t frictionscale; + /* + vec3_t diff; + vec_t dist; + explosiongas_t **l; + */ e->alpha -= frametime * EXPLOSIONFADERATE; + frictionscale = 1 - frametime; + frictionscale = bound(0, frictionscale, 1); for (i = 0;i < EXPLOSIONVERTS;i++) { if (e->vertvel[i][0] || e->vertvel[i][1] || e->vertvel[i][2]) @@ -221,12 +265,12 @@ void R_MoveExplosion(explosion_t *e, float frametime) { float f, dot; vec3_t impact, normal; - f = TraceLine(e->vert[i], end, impact, normal); + f = TraceLine(e->vert[i], end, impact, normal, 0); VectorCopy(impact, e->vert[i]); if (f < 1) { // clip velocity against the wall - dot = -DotProduct(e->vertvel[i], normal); + dot = DotProduct(e->vertvel[i], normal) * -1.125f; e->vertvel[i][0] += normal[0] * dot; e->vertvel[i][1] += normal[1] * dot; e->vertvel[i][2] += normal[2] * dot; @@ -236,15 +280,97 @@ void R_MoveExplosion(explosion_t *e, float frametime) { VectorCopy(end, e->vert[i]); } + e->vertvel[i][2] += sv_gravity.value * frametime * -0.25f; + VectorScale(e->vertvel[i], frictionscale, e->vertvel[i]); + } + /* + for (l = list;l < listend;l++) + { + VectorSubtract(e->vert[i], (*l)->origin, diff); + dist = DotProduct(diff, diff); + if (dist < 4096 && dist >= 1) + { + dist = (*l)->pressure * frametime / dist; + VectorMA(e->vertvel[i], dist, diff, e->vertvel[i]); + } + } + */ + } +} + +/* +void R_MoveExplosionGas(explosiongas_t *e, explosiongas_t **list, explosiongas_t **listend, float frametime) +{ + vec3_t end, diff; + vec_t dist, frictionscale; + explosiongas_t **l; + frictionscale = 1 - frametime; + frictionscale = bound(0, frictionscale, 1); + if (e->velocity[0] || e->velocity[1] || e->velocity[2]) + { + end[0] = e->origin[0] + frametime * e->velocity[0]; + end[1] = e->origin[1] + frametime * e->velocity[1]; + end[2] = e->origin[2] + frametime * e->velocity[2]; + if (r_explosionclip.value) + { + float f, dot; + vec3_t impact, normal; + f = TraceLine(e->origin, end, impact, normal, 0); + VectorCopy(impact, e->origin); + if (f < 1) + { + // clip velocity against the wall + dot = DotProduct(e->velocity, normal) * -1.3f; + e->velocity[0] += normal[0] * dot; + e->velocity[1] += normal[1] * dot; + e->velocity[2] += normal[2] * dot; + } + } + else + { + VectorCopy(end, e->origin); + } + e->velocity[2] += sv_gravity.value * frametime; + VectorScale(e->velocity, frictionscale, e->velocity); + } + for (l = list;l < listend;l++) + { + if (*l != e) + { + VectorSubtract(e->origin, (*l)->origin, diff); + dist = DotProduct(diff, diff); + if (dist < 4096 && dist >= 1) + { + dist = (*l)->pressure * frametime / dist; + VectorMA(e->velocity, dist, diff, e->velocity); + } } } } +*/ void R_MoveExplosions(void) { int i; float frametime; +// explosiongas_t *gaslist[MAX_EXPLOSIONGAS], **l, **end; frametime = cl.time - cl.oldtime; + /* + l = &gaslist[0]; + for (i = 0;i < MAX_EXPLOSIONGAS;i++) + { + if (explosiongas[i].pressure > 0) + { + explosiongas[i].pressure -= frametime * GASFADERATE; + if (explosiongas[i].pressure > 0) + *l++ = &explosiongas[i]; + } + } + end = l; + for (l = gaslist;l < end;l++) + R_MoveExplosionGas(*l, gaslist, end, frametime); + */ + for (i = 0;i < MAX_EXPLOSIONS;i++) { if (explosion[i].alpha > 0.0f) @@ -254,7 +380,7 @@ void R_MoveExplosions(void) explosion[i].alpha = 0; continue; } - R_MoveExplosion(&explosion[i], frametime); + R_MoveExplosion(&explosion[i], /*gaslist, end, */frametime); } } } diff --git a/r_lerpanim.c b/r_lerpanim.c index 7ac1c62e..7e44e373 100644 --- a/r_lerpanim.c +++ b/r_lerpanim.c @@ -1,183 +1,165 @@ - #include "quakedef.h" // LordHavoc: quite tempting to break apart this function to reuse the // duplicated code, but I suspect it is better for performance // this way -void R_LerpAnimation(model_t *mod, int frame1, int frame2, double frame1start, double frame2start, double framelerp, frameblend_t *blend) +// LordHavoc: later note: made FRAMEBLENDINSERT macro +void R_LerpAnimation(entity_render_t *r) { int sub1, sub2, numframes, f, i, data; - double sublerp, lerp, l; + double sublerp, lerp, d; animscene_t *scene, *scenes; + frameblend_t *blend; + blend = r->frameblend; - data = (int) Mod_Extradata(mod); - if (!data) - Host_Error("R_LerpAnimation: model not loaded\n"); - scenes = (animscene_t *) (mod->ofs_scenes + data); - - numframes = mod->numframes; + numframes = r->model->numframes; - if ((frame1 >= numframes)) + if ((r->frame1 >= numframes)) { - Con_Printf ("R_LerpAnimation: no such frame %d\n", frame1); - frame1 = 0; + Con_Printf ("CL_LerpAnimation: no such frame %d\n", r->frame1); + r->frame1 = 0; } - if ((frame2 >= numframes)) + if ((r->frame2 >= numframes)) { - Con_Printf ("R_LerpAnimation: no such frame %d\n", frame2); - frame2 = 0; + Con_Printf ("CL_LerpAnimation: no such frame %d\n", r->frame2); + r->frame2 = 0; } - if (frame1 < 0) - Host_Error ("R_LerpAnimation: frame1 is NULL\n"); + // note: this could be removed, if the rendering code allows an empty blend array + if (r->frame1 < 0) + Host_Error ("CL_LerpAnimation: frame1 is NULL\n"); // round off very close blend percentages - if (framelerp < (1.0f / 65536.0f)) - framelerp = 0; - if (framelerp >= (65535.0f / 65536.0f)) - framelerp = 1; + if (r->framelerp < (1.0f / 65536.0f)) + r->framelerp = 0; + if (r->framelerp >= (65535.0f / 65536.0f)) + r->framelerp = 1; blend[0].frame = blend[1].frame = blend[2].frame = blend[3].frame = -1; blend[0].lerp = blend[1].lerp = blend[2].lerp = blend[3].lerp = 0; - if (framelerp < 1) + if (r->model->ofs_scenes) { - scene = scenes + frame1; - lerp = 1 - framelerp; + if (r->model->cachesize) + { + data = (int) Mod_Extradata(r->model); + if (!data) + Host_Error("CL_LerpAnimation: model not loaded\n"); + scenes = (animscene_t *) (r->model->ofs_scenes + data); + } + else + scenes = (animscene_t *) r->model->ofs_scenes; - if (scene->framecount > 1) + if (r->framelerp < 1 && r->frame1 >= 0) { - sublerp = scene->framerate * (cl.time - frame1start); - sub1 = (int) (sublerp); - sub2 = sub1 + 1; - sublerp -= sub1; - if (sublerp < (1.0f / 65536.0f)) - sublerp = 0; - if (sublerp >= (65535.0f / 65536.0f)) - sublerp = 1; - if (scene->loop) + scene = scenes + r->frame1; + lerp = 1 - r->framelerp; + + if (scene->framecount > 1) { - sub1 = (sub1 % scene->framecount) + scene->firstframe; - sub2 = (sub2 % scene->framecount) + scene->firstframe; + sublerp = scene->framerate * (cl.time - r->frame1time); + sub1 = (int) (sublerp); + sub2 = sub1 + 1; + sublerp -= sub1; + if (sublerp < (1.0f / 65536.0f)) + sublerp = 0; + if (sublerp >= (65535.0f / 65536.0f)) + sublerp = 1; + if (scene->loop) + { + sub1 = (sub1 % scene->framecount) + scene->firstframe; + sub2 = (sub2 % scene->framecount) + scene->firstframe; + } + else + { + sub1 = bound(0, sub1, (scene->framecount - 1)) + scene->firstframe; + sub2 = bound(0, sub2, (scene->framecount - 1)) + scene->firstframe; + } + f = sub1; + d = (1 - sublerp) * lerp; +#define FRAMEBLENDINSERT\ + if (d > 0)\ + {\ + for (i = 0;i < 4;i++)\ + {\ + if (blend[i].frame == f)\ + {\ + blend[i].lerp += d;\ + break;\ + }\ + if (blend[i].lerp <= 0)\ + {\ + blend[i].frame = f;\ + blend[i].lerp = d;\ + break;\ + }\ + }\ + } + FRAMEBLENDINSERT + f = sub2; + d = sublerp * lerp; } else { - sub1 = bound(0, sub1, (scene->framecount - 1)) + scene->firstframe; - sub2 = bound(0, sub2, (scene->framecount - 1)) + scene->firstframe; - } - f = sub1; - l = (1 - sublerp) * lerp; - if (l > 0) - { - for (i = 0;i < 4;i++) - { - if (blend[i].frame == f) - { - blend[i].lerp += l; - break; - } - if (blend[i].lerp <= 0) - { - blend[i].frame = f; - blend[i].lerp = l; - break; - } - } + f = scene->firstframe; + d = lerp; } - f = sub2; - l = sublerp * lerp; + FRAMEBLENDINSERT } - else - { - f = scene->firstframe; - l = lerp; - } - if (l > 0) + if (r->framelerp > 0 && r->frame2 >= 0) { - for (i = 0;i < 4;i++) + scene = scenes + r->frame2; + lerp = r->framelerp; + + if (scene->framecount > 1) { - if (blend[i].frame == f) + sublerp = scene->framerate * (cl.time - r->frame1time); + sub1 = (int) (sublerp); + sub2 = sub1 + 1; + sublerp -= sub1; + if (sublerp < (1.0f / 65536.0f)) + sublerp = 0; + if (sublerp >= (65535.0f / 65536.0f)) + sublerp = 1; + if (scene->loop) { - blend[i].lerp += l; - break; + sub1 = (sub1 % scene->framecount) + scene->firstframe; + sub2 = (sub2 % scene->framecount) + scene->firstframe; } - if (blend[i].lerp <= 0) + else { - blend[i].frame = f; - blend[i].lerp = l; - break; + sub1 = bound(0, sub1, (scene->framecount - 1)) + scene->firstframe; + sub2 = bound(0, sub2, (scene->framecount - 1)) + scene->firstframe; } - } - } - } - if (framelerp > 0 && frame2 >= 0) - { - scene = scenes + frame2; - lerp = framelerp; - - if (scene->framecount > 1) - { - sublerp = scene->framerate * (cl.time - frame1start); - sub1 = (int) (sublerp); - sub2 = sub1 + 1; - sublerp -= sub1; - if (sublerp < (1.0f / 65536.0f)) - sublerp = 0; - if (sublerp >= (65535.0f / 65536.0f)) - sublerp = 1; - if (scene->loop) - { - sub1 = (sub1 % scene->framecount) + scene->firstframe; - sub2 = (sub2 % scene->framecount) + scene->firstframe; + f = sub1; + d = (1 - sublerp) * lerp; + FRAMEBLENDINSERT + f = sub2; + d = sublerp * lerp; } else { - sub1 = bound(0, sub1, (scene->framecount - 1)) + scene->firstframe; - sub2 = bound(0, sub2, (scene->framecount - 1)) + scene->firstframe; - } - f = sub1; - l = (1 - sublerp) * lerp; - if (l > 0) - { - for (i = 0;i < 4;i++) - { - if (blend[i].frame == f) - { - blend[i].lerp += l; - break; - } - if (blend[i].lerp <= 0) - { - blend[i].frame = f; - blend[i].lerp = l; - break; - } - } + f = scene->firstframe; + d = lerp; } - f = sub2; - l = sublerp * lerp; + FRAMEBLENDINSERT } - else + } + else + { + // if there are no scenes, assume it is all single-frame groups + if (r->framelerp < 1 && r->frame1 >= 0) { - f = scene->firstframe; - l = lerp; + f = r->frame1; + d = 1 - r->framelerp; + FRAMEBLENDINSERT } - if (l > 0) + if (r->framelerp > 0 && r->frame2 >= 0) { - for (i = 0;i < 4;i++) - { - if (blend[i].frame == f) - { - blend[i].lerp += l; - break; - } - if (blend[i].lerp <= 0) - { - blend[i].frame = f; - blend[i].lerp = l; - break; - } - } + f = r->frame2; + d = r->framelerp; + FRAMEBLENDINSERT } } } + diff --git a/r_lerpanim.h b/r_lerpanim.h index 83eec6f7..a90101cf 100644 --- a/r_lerpanim.h +++ b/r_lerpanim.h @@ -1,9 +1,2 @@ -typedef struct -{ - int frame; - float lerp; -} -frameblend_t; - -void R_LerpAnimation(model_t *mod, int frame1, int frame2, double frame1start, double frame2start, double framelerp, frameblend_t *blend); +void R_LerpAnimation(entity_render_t *r); diff --git a/r_light.c b/r_light.c index f8f797c4..db05fdea 100644 --- a/r_light.c +++ b/r_light.c @@ -8,7 +8,7 @@ of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. @@ -49,7 +49,7 @@ R_AnimateLight void R_AnimateLight (void) { int i,j,k; - + // // light animations // 'm' is normal light, 'a' is no light, 'z' is double bright @@ -131,7 +131,7 @@ loc0: surf = cl.worldmodel->surfaces + node->firstsurface; for (i=0 ; inumsurfaces ; i++, surf++) { - int d; + int d, impacts, impactt; float dist, dist2, impact[3]; if (surf->visframe != r_framecount) continue; @@ -150,6 +150,22 @@ loc0: impact[1] = light->origin[1] - surf->plane->normal[1] * dist; impact[2] = light->origin[2] - surf->plane->normal[2] * dist; + impacts = DotProduct (impact, surf->texinfo->vecs[0]) + surf->texinfo->vecs[0][3] - surf->texturemins[0]; + + d = bound(0, impacts, surf->extents[0] + 16) - impacts; + dist2 += d * d; + if (dist2 > maxdist) + continue; + + impactt = DotProduct (impact, surf->texinfo->vecs[1]) + surf->texinfo->vecs[1][3] - surf->texturemins[1]; + + d = bound(0, impactt, surf->extents[1] + 16) - impactt; + dist2 += d * d; + if (dist2 > maxdist) + continue; + + + /* d = DotProduct (impact, surf->texinfo->vecs[0]) + surf->texinfo->vecs[0][3] - surf->texturemins[0]; if (d < 0) @@ -187,6 +203,7 @@ loc0: continue; } } + */ if (surf->dlightframe != r_framecount) // not dynamic until now { @@ -280,6 +297,7 @@ void R_VisMarkLights (vec3_t lightorigin, dlight_t *light, int bit, int bitindex { if (c & (1< model->numleafs) return; @@ -317,7 +335,7 @@ void R_VisMarkLights (vec3_t lightorigin, dlight_t *light, int bit, int bitindex // LordHavoc: make sure it is infront of the surface and not too far away if (dist < radius && (dist > -0.25f || ((surf->flags & SURF_LIGHTBOTHSIDES) && dist > -radius))) { - int d; + int d, impacts, impactt; float dist2, impact[3]; dist2 = dist * dist; @@ -326,6 +344,21 @@ void R_VisMarkLights (vec3_t lightorigin, dlight_t *light, int bit, int bitindex impact[1] = light->origin[1] - surf->plane->normal[1] * dist; impact[2] = light->origin[2] - surf->plane->normal[2] * dist; + impacts = DotProduct (impact, surf->texinfo->vecs[0]) + surf->texinfo->vecs[0][3] - surf->texturemins[0]; + + d = bound(0, impacts, surf->extents[0] + 16) - impacts; + dist2 += d * d; + if (dist2 > maxdist) + continue; + + impactt = DotProduct (impact, surf->texinfo->vecs[1]) + surf->texinfo->vecs[1][3] - surf->texturemins[1]; + + d = bound(0, impactt, surf->extents[1] + 16) - impactt; + dist2 += d * d; + if (dist2 > maxdist) + continue; + + /* d = DotProduct (impact, surf->texinfo->vecs[0]) + surf->texinfo->vecs[0][3] - surf->texturemins[0]; if (d < 0) @@ -363,6 +396,7 @@ void R_VisMarkLights (vec3_t lightorigin, dlight_t *light, int bit, int bitindex continue; } } + */ if (surf->dlightframe != r_framecount) // not dynamic until now { @@ -379,7 +413,7 @@ void R_VisMarkLights (vec3_t lightorigin, dlight_t *light, int bit, int bitindex k++; continue; } - + k += *in++; } } @@ -624,10 +658,10 @@ loc0: if (ds < surf->texturemins[0] || dt < surf->texturemins[1]) continue; - + ds -= surf->texturemins[0]; dt -= surf->texturemins[1]; - + if (ds > surf->extents[0] || dt > surf->extents[1]) continue; @@ -730,10 +764,11 @@ void R_DynamicLightPoint(vec3_t color, vec3_t org, int *dlightbits) } } -void R_CompleteLightPoint (vec3_t color, vec3_t p, int dynamic) +void R_CompleteLightPoint (vec3_t color, vec3_t p, int dynamic, mleaf_t *leaf) { - mleaf_t *leaf; - leaf = Mod_PointInLeaf(p, cl.worldmodel); + if (leaf == NULL) + leaf = Mod_PointInLeaf(p, cl.worldmodel); + if (leaf->contents == CONTENTS_SOLID) { color[0] = color[1] = color[2] = 0; @@ -770,7 +805,7 @@ void R_ModelLightPoint (vec3_t color, vec3_t p, int *dlightbits) dlightbits[0] = dlightbits[1] = dlightbits[2] = dlightbits[3] = dlightbits[4] = dlightbits[5] = dlightbits[6] = dlightbits[7] = 0; return; } - + color[0] = color[1] = color[2] = r_ambient.value * 2.0f; RecursiveLightPoint (color, cl.worldmodel->nodes, p[0], p[1], p[2], p[2] - 65536); @@ -819,12 +854,12 @@ void R_DynamicLightPointNoMask(vec3_t color, vec3_t org) } */ -void R_LightModel(entity_t *ent, int numverts, vec3_t center, vec3_t basecolor) +void R_LightModel(int numverts) { // LordHavoc: warning: reliance on int being 4 bytes here (of course the d_8to24table relies on that too...) int i, j, nearlights = 0, color; - vec3_t dist, mod; - float t, t1, t2, t3, *avn; + vec3_t dist, mod, basecolor, center; + float t, t1, t2, t3, *avn, number; byte r,g,b,a, *avc; struct { @@ -834,29 +869,35 @@ void R_LightModel(entity_t *ent, int numverts, vec3_t center, vec3_t basecolor) int modeldlightbits[8]; avc = aliasvertcolor; avn = aliasvertnorm; - a = (byte) bound((int) 0, (int) (modelalpha * 255.0f), (int) 255); + VectorCopy(currentrenderentity->origin, center); + a = (byte) bound((int) 0, (int) (currentrenderentity->alpha * 255.0f), (int) 255); if (lighthalf) { - mod[0] = ent->render.colormod[0] * 0.5f; - mod[1] = ent->render.colormod[1] * 0.5f; - mod[2] = ent->render.colormod[2] * 0.5f; + mod[0] = currentrenderentity->colormod[0] * 0.5f; + mod[1] = currentrenderentity->colormod[1] * 0.5f; + mod[2] = currentrenderentity->colormod[2] * 0.5f; } else { - mod[0] = ent->render.colormod[0]; - mod[1] = ent->render.colormod[1]; - mod[2] = ent->render.colormod[2]; + mod[0] = currentrenderentity->colormod[0]; + mod[1] = currentrenderentity->colormod[1]; + mod[2] = currentrenderentity->colormod[2]; } - if (ent->render.effects & EF_FULLBRIGHT) + if (currentrenderentity->effects & EF_FULLBRIGHT) { - ((byte *)&color)[0] = (byte) (255.0f * mod[0]); - ((byte *)&color)[1] = (byte) (255.0f * mod[1]); - ((byte *)&color)[2] = (byte) (255.0f * mod[2]); - ((byte *)&color)[3] = a; - for (i = 0;i < numverts;i++) + if (a == 255) + memset(avc, 0, 4 * numverts); + else { - *((int *)avc) = color; - avc += 4; + ((byte *)&color)[0] = (byte) (255.0f * mod[0]); + ((byte *)&color)[1] = (byte) (255.0f * mod[1]); + ((byte *)&color)[2] = (byte) (255.0f * mod[2]); + ((byte *)&color)[3] = a; + for (i = 0;i < numverts;i++) + { + *((int *)avc) = color; + avc += 4; + } } return; } @@ -879,24 +920,36 @@ void R_LightModel(entity_t *ent, int numverts, vec3_t center, vec3_t basecolor) t1 = cl_dlights[i].radius*cl_dlights[i].radius; if (t2 < t1) { - // transform the light into the model's coordinate system - if (gl_transform.value) - softwareuntransform(cl_dlights[i].origin, nearlight[nearlights].origin); - else - { - VectorCopy(cl_dlights[i].origin, nearlight[nearlights].origin); - } - nearlight[nearlights].color[0] = cl_dlights[i].color[0] * t1 * mod[0]; - nearlight[nearlights].color[1] = cl_dlights[i].color[1] * t1 * mod[1]; - nearlight[nearlights].color[2] = cl_dlights[i].color[2] * t1 * mod[2]; - if (r_lightmodels.value && (ent == NULL || ent != cl_dlights[i].ent)) - nearlights++; - else + if (TraceLine(center, cl_dlights[i].origin, NULL, NULL, 0)) { - t1 = 1.0f / t2; - basecolor[0] += nearlight[nearlights].color[0] * t1; - basecolor[1] += nearlight[nearlights].color[1] * t1; - basecolor[2] += nearlight[nearlights].color[2] * t1; + // transform the light into the model's coordinate system + if (gl_transform.value) + softwareuntransform(cl_dlights[i].origin, nearlight[nearlights].origin); + else + VectorCopy(cl_dlights[i].origin, nearlight[nearlights].origin); + nearlight[nearlights].color[0] = cl_dlights[i].color[0] * t1 * mod[0]; + nearlight[nearlights].color[1] = cl_dlights[i].color[1] * t1 * mod[1]; + nearlight[nearlights].color[2] = cl_dlights[i].color[2] * t1 * mod[2]; + if (r_lightmodels.value && currentrenderentity != cl_dlights[i].ent) + { + // boost color, to compensate for dark lighting calcs + VectorScale(nearlight[nearlights].color, cl_dlights[i].radius * 16.0f, nearlight[nearlights].color); + nearlights++; + } + else + { +#if SLOWMATH + t1 = 1.0f / sqrt(t2); +#else + number = t1; + *((long *)&t1) = 0x5f3759df - ((* (long *) &number) >> 1); + t1 = t1 * (1.5f - (number * 0.5f * t1 * t1)); +#endif + t1 = t1 * t1; + basecolor[0] += nearlight[nearlights].color[0] * t1; + basecolor[1] += nearlight[nearlights].color[1] * t1; + basecolor[2] += nearlight[nearlights].color[2] * t1; + } } } } @@ -909,73 +962,61 @@ void R_LightModel(entity_t *ent, int numverts, vec3_t center, vec3_t basecolor) ((byte *)&color)[3] = a; if (nearlights) { - int temp; + int i1, i2, i3; vec3_t v; - float *av; + float *av, number; av = aliasvert; - if (nearlights == 1) + for (i = 0;i < numverts;i++) { - for (i = 0;i < numverts;i++) + t1 = basecolor[0]; + t2 = basecolor[1]; + t3 = basecolor[2]; + for (j = 0;j < nearlights;j++) { - VectorSubtract(nearlight[0].origin, av, v); + VectorSubtract(nearlight[j].origin, av, v); t = DotProduct(avn,v); if (t > 0) { - t /= (DotProduct(v,v) + LIGHTOFFSET); - temp = (int) ((float) (basecolor[0] + nearlight[0].color[0] * t)); - avc[0] = bound(0, temp, 255); - temp = (int) ((float) (basecolor[1] + nearlight[0].color[1] * t)); - avc[1] = bound(0, temp, 255); - temp = (int) ((float) (basecolor[2] + nearlight[0].color[2] * t)); - avc[2] = bound(0, temp, 255); - avc[3] = a; +#if SLOWMATH + t = 1.0f / sqrt(DotProduct(v,v) + 1.0f); +#else + number = DotProduct(v, v) + LIGHTOFFSET; + *((long *)&t) = 0x5f3759df - ((* (long *) &number) >> 1); + t = t * (1.5f - (number * 0.5f * t * t)); +#endif + t = t * t * t; + t1 += nearlight[j].color[0] * t; + t2 += nearlight[j].color[1] * t; + t3 += nearlight[j].color[2] * t; } - else - *((int *)avc) = color; - avc += 4; - av += 3; - avn += 3; - } - } - else - { - for (i = 0;i < numverts;i++) - { - int lit; - t1 = basecolor[0]; - t2 = basecolor[1]; - t3 = basecolor[2]; - lit = false; - for (j = 0;j < nearlights;j++) - { - VectorSubtract(nearlight[j].origin, av, v); - t = DotProduct(avn,v); - if (t > 0) - { - t /= (DotProduct(v,v) + LIGHTOFFSET); - t1 += nearlight[j].color[0] * t; - t2 += nearlight[j].color[1] * t; - t3 += nearlight[j].color[2] * t; - lit = true; - } - } - if (lit) - { - int i1, i2, i3; - i1 = (int) t1; - avc[0] = bound(0, i1, 255); - i2 = (int) t2; - avc[1] = bound(0, i2, 255); - i3 = (int) t3; - avc[2] = bound(0, i3, 255); - avc[3] = a; - } - else // dodge the costly float -> int conversions - *((int *)avc) = color; - avc += 4; - av += 3; - avn += 3; } + + // FIXME: float to int conversions are very slow on x86 because of + // mode switchs (switch from nearest rounding to down, then back, + // each time), reimplement this part in assembly, SSE and 3DNow! + // versions recommended as well +#if SLOWMATH + i1 = (int) t1; + i2 = (int) t2; + i3 = (int) t3; +#else + // later note: implemented bit hacking float to integer, + // probably makes the issue irrelevant + t1 += 8388608.0f; + i1 = *((long *)&t1) & 0x007FFFFF; + t2 += 8388608.0f; + i2 = *((long *)&t2) & 0x007FFFFF; + t3 += 8388608.0f; + i3 = *((long *)&t3) & 0x007FFFFF; +#endif + + avc[0] = bound(0, i1, 255); + avc[1] = bound(0, i2, 255); + avc[2] = bound(0, i3, 255); + avc[3] = a; + avc += 4; + av += 3; + avn += 3; } } else diff --git a/r_light.h b/r_light.h index 6e29e589..0507c425 100644 --- a/r_light.h +++ b/r_light.h @@ -1,20 +1,7 @@ -// LordHavoc: 256 dynamic lights -#define MAX_DLIGHTS 256 -typedef struct -{ - vec3_t origin; - float radius; - float die; // stop lighting after this time - float decay; // drop this each second - entity_t *ent; // the entity that spawned this light (can be NULL if it is not to be replaced repeatedly) - vec3_t color; // LordHavoc: colored lighting -} dlight_t; - -// LordHavoc: this affects the lighting scale of the whole game -#define LIGHTOFFSET 4096.0f - -extern void R_CompleteLightPoint (vec3_t color, vec3_t p, int dynamic); +extern void R_CompleteLightPoint (vec3_t color, vec3_t p, int dynamic, mleaf_t *leaf); extern void R_DynamicLightPoint(vec3_t color, vec3_t org, int *dlightbits); extern void R_DynamicLightPointNoMask(vec3_t color, vec3_t org); extern void R_LightPoint (vec3_t color, vec3_t p); +extern void R_AnimateLight (void); +extern void R_LightModel (int numverts); diff --git a/r_part.c b/r_part.c index 790a4218..9ee7f9bb 100644 --- a/r_part.c +++ b/r_part.c @@ -8,7 +8,7 @@ of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. @@ -23,23 +23,24 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define MAX_PARTICLES 16384 // default max # of particles at one time #define ABSOLUTE_MIN_PARTICLES 512 // no fewer than this no matter what's on the command line -// LordHavoc: added dust, smoke, snow, bloodcloud, and many others typedef enum { - pt_static, pt_grav, pt_slowgrav, pt_blob, pt_blob2, pt_bulletsmoke, pt_smoke, pt_snow, pt_rain, pt_spark, pt_bubble, pt_fade, pt_steam, pt_splash, pt_splashpuff, pt_flame/*, pt_decal*/, pt_blood, pt_oneframe, pt_lavasplash + pt_static, pt_grav, pt_blob, pt_blob2, pt_bulletsmoke, pt_smoke, pt_snow, pt_rain, pt_spark, pt_bubble, pt_fade, pt_steam, pt_splash, pt_splashpuff, pt_flame, pt_blood, pt_oneframe, pt_lavasplash, pt_raindropsplash, pt_underwaterspark, pt_explosionsplash } ptype_t; +typedef struct +{ + float s1, t1, s2, t2; +} +particletexture_t; + typedef struct particle_s { ptype_t type; vec3_t org; vec3_t vel; - rtexture_t *tex; - byte dynlight; // if set the particle will be dynamically lit (if r_dynamicparticles is on), used for smoke and blood - byte rendermode; // a TPOLYTYPE_ value - byte color; - byte pad2; + particletexture_t *tex; float die; float scale; float alpha; // 0-255 @@ -47,43 +48,80 @@ typedef struct particle_s float bounce; // how much bounce-back from a surface the particle hits (0 = no physics, 1 = stop and slide, 2 = keep bouncing forever, 1.5 is typical) vec3_t oldorg; vec3_t vel2; // used for snow fluttering (base velocity, wind for instance) -// vec3_t direction; // used by decals -// vec3_t decalright; // used by decals -// vec3_t decalup; // used by decals + float friction; // how much air friction affects this object (objects with a low mass/size ratio tend to get more air friction) + float pressure; // if non-zero, apply pressure to other particles + int dynlight; // if set the particle will be dynamically lit (if r_dynamicparticles is on), used for smoke and blood + int rendermode; // a TPOLYTYPE_ value + byte color[4]; } particle_t; -float TraceLine (vec3_t start, vec3_t end, vec3_t impact, vec3_t normal); - -int ramp1[8] = {0x6f, 0x6d, 0x6b, 0x69, 0x67, 0x65, 0x63, 0x61}; -int ramp2[8] = {0x6f, 0x6e, 0x6d, 0x6c, 0x6b, 0x6a, 0x68, 0x66}; -int ramp3[8] = {0x6d, 0x6b, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01}; - -rtexture_t *particletexture; -rtexture_t *smokeparticletexture[8]; -rtexture_t *rainparticletexture; -rtexture_t *bubbleparticletexture; -rtexture_t *bulletholetexture[8]; -rtexture_t *rocketglowparticletexture; - -particle_t *particles; -int r_numparticles; - -vec3_t r_pright, r_pup, r_ppn; - -int numparticles; -particle_t **freeparticles; // list used only in compacting particles array - -cvar_t r_particles = {CVAR_SAVE, "r_particles", "1"}; -cvar_t r_drawparticles = {0, "r_drawparticles", "1"}; -cvar_t r_particles_lighting = {CVAR_SAVE, "r_particles_lighting", "1"}; -cvar_t r_particles_bloodshowers = {CVAR_SAVE, "r_particles_bloodshowers", "1"}; -cvar_t r_particles_blood = {CVAR_SAVE, "r_particles_blood", "1"}; -cvar_t r_particles_smoke = {CVAR_SAVE, "r_particles_smoke", "1"}; -cvar_t r_particles_sparks = {CVAR_SAVE, "r_particles_sparks", "1"}; -cvar_t r_particles_bubbles = {CVAR_SAVE, "r_particles_bubbles", "1"}; - -byte shadebubble(float dx, float dy, vec3_t light) +static int particlepalette[256] = +{ + 0x000000,0x0f0f0f,0x1f1f1f,0x2f2f2f,0x3f3f3f,0x4b4b4b,0x5b5b5b,0x6b6b6b, + 0x7b7b7b,0x8b8b8b,0x9b9b9b,0xababab,0xbbbbbb,0xcbcbcb,0xdbdbdb,0xebebeb, + 0x0f0b07,0x170f0b,0x1f170b,0x271b0f,0x2f2313,0x372b17,0x3f2f17,0x4b371b, + 0x533b1b,0x5b431f,0x634b1f,0x6b531f,0x73571f,0x7b5f23,0x836723,0x8f6f23, + 0x0b0b0f,0x13131b,0x1b1b27,0x272733,0x2f2f3f,0x37374b,0x3f3f57,0x474767, + 0x4f4f73,0x5b5b7f,0x63638b,0x6b6b97,0x7373a3,0x7b7baf,0x8383bb,0x8b8bcb, + 0x000000,0x070700,0x0b0b00,0x131300,0x1b1b00,0x232300,0x2b2b07,0x2f2f07, + 0x373707,0x3f3f07,0x474707,0x4b4b0b,0x53530b,0x5b5b0b,0x63630b,0x6b6b0f, + 0x070000,0x0f0000,0x170000,0x1f0000,0x270000,0x2f0000,0x370000,0x3f0000, + 0x470000,0x4f0000,0x570000,0x5f0000,0x670000,0x6f0000,0x770000,0x7f0000, + 0x131300,0x1b1b00,0x232300,0x2f2b00,0x372f00,0x433700,0x4b3b07,0x574307, + 0x5f4707,0x6b4b0b,0x77530f,0x835713,0x8b5b13,0x975f1b,0xa3631f,0xaf6723, + 0x231307,0x2f170b,0x3b1f0f,0x4b2313,0x572b17,0x632f1f,0x733723,0x7f3b2b, + 0x8f4333,0x9f4f33,0xaf632f,0xbf772f,0xcf8f2b,0xdfab27,0xefcb1f,0xfff31b, + 0x0b0700,0x1b1300,0x2b230f,0x372b13,0x47331b,0x533723,0x633f2b,0x6f4733, + 0x7f533f,0x8b5f47,0x9b6b53,0xa77b5f,0xb7876b,0xc3937b,0xd3a38b,0xe3b397, + 0xab8ba3,0x9f7f97,0x937387,0x8b677b,0x7f5b6f,0x775363,0x6b4b57,0x5f3f4b, + 0x573743,0x4b2f37,0x43272f,0x371f23,0x2b171b,0x231313,0x170b0b,0x0f0707, + 0xbb739f,0xaf6b8f,0xa35f83,0x975777,0x8b4f6b,0x7f4b5f,0x734353,0x6b3b4b, + 0x5f333f,0x532b37,0x47232b,0x3b1f23,0x2f171b,0x231313,0x170b0b,0x0f0707, + 0xdbc3bb,0xcbb3a7,0xbfa39b,0xaf978b,0xa3877b,0x977b6f,0x876f5f,0x7b6353, + 0x6b5747,0x5f4b3b,0x533f33,0x433327,0x372b1f,0x271f17,0x1b130f,0x0f0b07, + 0x6f837b,0x677b6f,0x5f7367,0x576b5f,0x4f6357,0x475b4f,0x3f5347,0x374b3f, + 0x2f4337,0x2b3b2f,0x233327,0x1f2b1f,0x172317,0x0f1b13,0x0b130b,0x070b07, + 0xfff31b,0xefdf17,0xdbcb13,0xcbb70f,0xbba70f,0xab970b,0x9b8307,0x8b7307, + 0x7b6307,0x6b5300,0x5b4700,0x4b3700,0x3b2b00,0x2b1f00,0x1b0f00,0x0b0700, + 0x0000ff,0x0b0bef,0x1313df,0x1b1bcf,0x2323bf,0x2b2baf,0x2f2f9f,0x2f2f8f, + 0x2f2f7f,0x2f2f6f,0x2f2f5f,0x2b2b4f,0x23233f,0x1b1b2f,0x13131f,0x0b0b0f, + 0x2b0000,0x3b0000,0x4b0700,0x5f0700,0x6f0f00,0x7f1707,0x931f07,0xa3270b, + 0xb7330f,0xc34b1b,0xcf632b,0xdb7f3b,0xe3974f,0xe7ab5f,0xefbf77,0xf7d38b, + 0xa77b3b,0xb79b37,0xc7c337,0xe7e357,0x7fbfff,0xabe7ff,0xd7ffff,0x670000, + 0x8b0000,0xb30000,0xd70000,0xff0000,0xfff393,0xfff7c7,0xffffff,0x9f5b53 +}; + +static int explosparkramp[8] = {0x4b0700, 0x6f0f00, 0x931f07, 0xb7330f, 0xcf632b, 0xe3974f, 0xffe7b5, 0xffffff}; +//static int explounderwatersparkramp[8] = {0x00074b, 0x000f6f, 0x071f93, 0x0f33b7, 0x2b63cf, 0x4f97e3, 0xb5e7ff, 0xffffff}; + +static rtexture_t *particlefonttexture; + +static particletexture_t particletexture; +static particletexture_t smokeparticletexture[8]; +static particletexture_t rainparticletexture; +static particletexture_t bubbleparticletexture; +static particletexture_t bulletholetexture[8]; +static particletexture_t rocketglowparticletexture; +static particletexture_t raindropsplashparticletexture[16]; + +static particle_t *particles; +static int r_numparticles; + +static int numparticles; +static particle_t **freeparticles; // list used only in compacting particles array + +static cvar_t r_particles = {CVAR_SAVE, "r_particles", "1"}; +static cvar_t r_drawparticles = {0, "r_drawparticles", "1"}; +static cvar_t r_particles_lighting = {CVAR_SAVE, "r_particles_lighting", "1"}; +static cvar_t r_particles_bloodshowers = {CVAR_SAVE, "r_particles_bloodshowers", "1"}; +static cvar_t r_particles_blood = {CVAR_SAVE, "r_particles_blood", "1"}; +static cvar_t r_particles_smoke = {CVAR_SAVE, "r_particles_smoke", "1"}; +static cvar_t r_particles_sparks = {CVAR_SAVE, "r_particles_sparks", "1"}; +static cvar_t r_particles_bubbles = {CVAR_SAVE, "r_particles_bubbles", "1"}; +static cvar_t r_particles_explosions = {CVAR_SAVE, "r_particles_explosions", "0"}; + +static byte shadebubble(float dx, float dy, vec3_t light) { float dz, f, dot; vec3_t normal; @@ -116,12 +154,34 @@ byte shadebubble(float dx, float dy, vec3_t light) return 0; } -void R_InitParticleTexture (void) +static void R_InitParticleTexture (void) { - int x,y,d,i,m; - float dx, dy; + int x,y,d,i,m, texnum; + float dx, dy, radius, f, f2; byte data[32][32][4], noise1[64][64], noise2[64][64]; vec3_t light; + byte particletexturedata[256][256][4]; + + memset(&particletexturedata[0][0][0], 255, sizeof(particletexturedata)); + texnum = 0; + #define SETUPTEX(var)\ + {\ + int basex, basey, y;\ + if (texnum >= 64)\ + {\ + Sys_Error("R_InitParticleTexture: ran out of textures (64)\n");\ + return; /* only to hush compiler */ \ + }\ + basex = (texnum & 7) * 32;\ + basey = ((texnum >> 3) & 7) * 32;\ + var.s1 = (basex + 1) / 256.0f;\ + var.t1 = (basey + 1) / 256.0f;\ + var.s2 = (basex + 31) / 256.0f;\ + var.t2 = (basey + 31) / 256.0f;\ + for (y = 0;y < 32;y++)\ + memcpy(&particletexturedata[basey + y][basex][0], &data[y][0][0], 32*4);\ + texnum++;\ + } for (y = 0;y < 32;y++) { @@ -135,7 +195,8 @@ void R_InitParticleTexture (void) data[y][x][3] = (byte) d; } } - particletexture = R_LoadTexture ("particletexture", 32, 32, &data[0][0][0], TEXF_MIPMAP | TEXF_ALPHA | TEXF_RGBA | TEXF_PRECACHE); + SETUPTEX(particletexture) +// particletexture = R_LoadTexture ("particletexture", 32, 32, &data[0][0][0], TEXF_MIPMAP | TEXF_ALPHA | TEXF_RGBA | TEXF_PRECACHE); for (i = 0;i < 8;i++) { @@ -149,11 +210,11 @@ void R_InitParticleTexture (void) dy = y - 16; for (x = 0;x < 32;x++) { - d = (noise1[y][x] - 128) * 2 + 128; + d = (noise1[y][x] - 128) * 2 + 64; // was + 128 d = bound(0, d, 255); data[y][x][0] = data[y][x][1] = data[y][x][2] = d; dx = x - 16; - d = (noise2[y][x] - 128) * 4 + 128; + d = (noise2[y][x] - 128) * 3 + 192; if (d > 0) d = (d * (256 - (int) (dx*dx+dy*dy))) >> 8; d = bound(0, d, 255); @@ -165,7 +226,8 @@ void R_InitParticleTexture (void) } while (m < 224); - smokeparticletexture[i] = R_LoadTexture (va("smokeparticletexture%d", i), 32, 32, &data[0][0][0], TEXF_MIPMAP | TEXF_ALPHA | TEXF_RGBA | TEXF_PRECACHE); + SETUPTEX(smokeparticletexture[i]) +// smokeparticletexture[i] = R_LoadTexture (va("smokeparticletexture%02d", i), 32, 32, &data[0][0][0], TEXF_MIPMAP | TEXF_ALPHA | TEXF_RGBA | TEXF_PRECACHE); } light[0] = 1;light[1] = 1;light[2] = 1; @@ -178,7 +240,8 @@ void R_InitParticleTexture (void) data[y][x][3] = shadebubble((x - 16) * (1.0 / 8.0), y < 24 ? (y - 24) * (1.0 / 24.0) : (y - 24) * (1.0 / 8.0), light); } } - rainparticletexture = R_LoadTexture ("rainparticletexture", 32, 32, &data[0][0][0], TEXF_MIPMAP | TEXF_ALPHA | TEXF_RGBA | TEXF_PRECACHE); + SETUPTEX(rainparticletexture) +// rainparticletexture = R_LoadTexture ("rainparticletexture", 32, 32, &data[0][0][0], TEXF_MIPMAP | TEXF_ALPHA | TEXF_RGBA | TEXF_PRECACHE); light[0] = 1;light[1] = 1;light[2] = 1; VectorNormalize(light); @@ -190,7 +253,8 @@ void R_InitParticleTexture (void) data[y][x][3] = shadebubble((x - 16) * (1.0 / 16.0), (y - 16) * (1.0 / 16.0), light); } } - bubbleparticletexture = R_LoadTexture ("bubbleparticletexture", 32, 32, &data[0][0][0], TEXF_MIPMAP | TEXF_ALPHA | TEXF_RGBA | TEXF_PRECACHE); + SETUPTEX(bubbleparticletexture) +// bubbleparticletexture = R_LoadTexture ("bubbleparticletexture", 32, 32, &data[0][0][0], TEXF_MIPMAP | TEXF_ALPHA | TEXF_RGBA | TEXF_PRECACHE); for (i = 0;i < 8;i++) { @@ -243,7 +307,8 @@ void R_InitParticleTexture (void) } } - bulletholetexture[i] = R_LoadTexture (va("bulletholetexture%d", i), 32, 32, &data[0][0][0], TEXF_MIPMAP | TEXF_ALPHA | TEXF_RGBA | TEXF_PRECACHE); + SETUPTEX(bulletholetexture[i]) +// bulletholetexture[i] = R_LoadTexture (va("bulletholetexture%02d", i), 32, 32, &data[0][0][0], TEXF_MIPMAP | TEXF_ALPHA | TEXF_RGBA | TEXF_PRECACHE); } for (y = 0;y < 32;y++) @@ -259,10 +324,33 @@ void R_InitParticleTexture (void) data[y][x][3] = bound(0, d * 1.0f, 255); } } - rocketglowparticletexture = R_LoadTexture ("glowparticletexture", 32, 32, &data[0][0][0], TEXF_MIPMAP | TEXF_ALPHA | TEXF_RGBA | TEXF_PRECACHE); + SETUPTEX(rocketglowparticletexture) +// rocketglowparticletexture = R_LoadTexture ("glowparticletexture", 32, 32, &data[0][0][0], TEXF_MIPMAP | TEXF_ALPHA | TEXF_RGBA | TEXF_PRECACHE); + + for (i = 0;i < 16;i++) + { + radius = i * 3.0f / 16.0f; + f2 = 255.0f * ((15.0f - i) / 15.0f); + for (y = 0;y < 32;y++) + { + dy = (y - 16) * 0.25f; + for (x = 0;x < 32;x++) + { + dx = (x - 16) * 0.25f; + data[y][x][0] = data[y][x][1] = data[y][x][2] = 255; + f = (1.0 - fabs(radius - sqrt(dx*dx+dy*dy))) * f2; + f = bound(0.0f, f, 255.0f); + data[y][x][3] = (int) f; + } + } + SETUPTEX(raindropsplashparticletexture[i]) +// raindropsplashparticletexture[i] = R_LoadTexture (va("raindropslashparticletexture%02d", i), 32, 32, &data[0][0][0], TEXF_MIPMAP | TEXF_ALPHA | TEXF_RGBA | TEXF_PRECACHE); + } + + particlefonttexture = R_LoadTexture ("particlefont", 256, 256, &particletexturedata[0][0][0], TEXF_ALPHA | TEXF_RGBA | TEXF_PRECACHE); } -void r_part_start(void) +static void r_part_start(void) { particles = (particle_t *) qmalloc(r_numparticles * sizeof(particle_t)); freeparticles = (void *) qmalloc(r_numparticles * sizeof(particle_t *)); @@ -270,14 +358,14 @@ void r_part_start(void) R_InitParticleTexture (); } -void r_part_shutdown(void) +static void r_part_shutdown(void) { numparticles = 0; qfree(particles); qfree(freeparticles); } -void r_part_newmap(void) +static void r_part_newmap(void) { numparticles = 0; } @@ -305,7 +393,7 @@ void R_Particles_Init (void) r_numparticles = MAX_PARTICLES; } - Cmd_AddCommand ("pointfile", R_ReadPointFile_f); + Cmd_AddCommand ("pointfile", R_ReadPointFile_f); Cvar_RegisterVariable (&r_particles); Cvar_RegisterVariable (&r_drawparticles); @@ -315,96 +403,26 @@ void R_Particles_Init (void) Cvar_RegisterVariable (&r_particles_smoke); Cvar_RegisterVariable (&r_particles_sparks); Cvar_RegisterVariable (&r_particles_bubbles); + Cvar_RegisterVariable (&r_particles_explosions); R_RegisterModule("R_Particles", r_part_start, r_part_shutdown, r_part_newmap); } //void particle(int ptype, int pcolor, int ptex, int prendermode, int plight, float pscale, float palpha, float ptime, float pbounce, float px, float py, float pz, float pvx, float pvy, float pvz) -#define particle(ptype, pcolor, ptex, prendermode, plight, pscale, palpha, ptime, pbounce, px, py, pz, pvx, pvy, pvz)\ +#define particle(ptype, pcolor, ptex, prendermode, plight, pscale, palpha, ptime, pbounce, px, py, pz, pvx, pvy, pvz, ptime2, pvx2, pvy2, pvz2, pfriction, ppressure)\ {\ particle_t *part;\ + int tempcolor;\ if (numparticles >= r_numparticles)\ return;\ part = &particles[numparticles++];\ part->type = (ptype);\ - part->color = (pcolor);\ - part->tex = (ptex);\ - part->dynlight = (plight);\ - part->rendermode = (prendermode);\ - part->scale = (pscale);\ - part->alpha = (palpha);\ - part->die = cl.time + (ptime);\ - part->bounce = (pbounce);\ - part->org[0] = (px);\ - part->org[1] = (py);\ - part->org[2] = (pz);\ - part->vel[0] = (pvx);\ - part->vel[1] = (pvy);\ - part->vel[2] = (pvz);\ - part->time2 = 0;\ - part->vel2[0] = part->vel2[1] = part->vel2[2] = 0;\ -} -/* -#define particle2(ptype, pcolor, ptex, prendermode, plight, pscale, palpha, ptime, pbounce, pbase, poscale, pvscale)\ -{\ - particle_t *part;\ - if (numparticles >= r_numparticles)\ - return;\ - part = &particles[numparticles++];\ - part->type = (ptype);\ - part->color = (pcolor);\ - part->tex = (ptex);\ - part->dynlight = (plight);\ - part->rendermode = (prendermode);\ - part->scale = (pscale);\ - part->alpha = (palpha);\ - part->die = cl.time + (ptime);\ - part->bounce = (pbounce);\ - part->org[0] = lhrandom(-(poscale), (poscale)) + (pbase)[0];\ - part->org[1] = lhrandom(-(poscale), (poscale)) + (pbase)[1];\ - part->org[2] = lhrandom(-(poscale), (poscale)) + (pbase)[2];\ - part->vel[0] = lhrandom(-(pvscale), (pvscale));\ - part->vel[1] = lhrandom(-(pvscale), (pvscale));\ - part->vel[2] = lhrandom(-(pvscale), (pvscale));\ - part->time2 = 0;\ - part->vel2[0] = part->vel2[1] = part->vel2[2] = 0;\ -} -*/ -/* -#define particle3(ptype, pcolor, ptex, prendermode, plight, pscale, palpha, ptime, pbounce, pbase, pscalex, pscaley, pscalez, pvscalex, pvscaley, pvscalez)\ -{\ - particle_t *part;\ - if (numparticles >= r_numparticles)\ - return;\ - part = &particles[numparticles++];\ - part->type = (ptype);\ - part->color = (pcolor);\ - part->tex = (ptex);\ - part->dynlight = (plight);\ - part->rendermode = (prendermode);\ - part->scale = (pscale);\ - part->alpha = (palpha);\ - part->die = cl.time + (ptime);\ - part->bounce = (pbounce);\ - part->org[0] = lhrandom(-(pscalex), (pscalex)) + (pbase)[0];\ - part->org[1] = lhrandom(-(pscaley), (pscaley)) + (pbase)[1];\ - part->org[2] = lhrandom(-(pscalez), (pscalez)) + (pbase)[2];\ - part->vel[0] = lhrandom(-(pvscalex), (pvscalex));\ - part->vel[1] = lhrandom(-(pvscaley), (pvscaley));\ - part->vel[2] = lhrandom(-(pvscalez), (pvscalez));\ - part->time2 = 0;\ - part->vel2[0] = part->vel2[1] = part->vel2[2] = 0;\ -} -*/ -#define particle4(ptype, pcolor, ptex, prendermode, plight, pscale, palpha, ptime, pbounce, px, py, pz, pvx, pvy, pvz, ptime2, pvx2, pvy2, pvz2)\ -{\ - particle_t *part;\ - if (numparticles >= r_numparticles)\ - return;\ - part = &particles[numparticles++];\ - part->type = (ptype);\ - part->color = (pcolor);\ - part->tex = (ptex);\ + tempcolor = (pcolor);\ + part->color[0] = ((tempcolor) >> 16) & 0xFF;\ + part->color[1] = ((tempcolor) >> 8) & 0xFF;\ + part->color[2] = (tempcolor) & 0xFF;\ + part->color[3] = 0xFF;\ + part->tex = (&ptex);\ part->dynlight = (plight);\ part->rendermode = (prendermode);\ part->scale = (pscale);\ @@ -421,6 +439,8 @@ void R_Particles_Init (void) part->vel2[0] = (pvx2);\ part->vel2[1] = (pvy2);\ part->vel2[2] = (pvz2);\ + part->friction = (pfriction);\ + part->pressure = (ppressure);\ } /* @@ -438,7 +458,7 @@ void R_EntityParticles (entity_t *ent) float beamlength; static vec3_t avelocities[NUMVERTEXNORMALS]; if (!r_particles.value) return; // LordHavoc: particles are optional - + dist = 64; beamlength = 16; @@ -454,12 +474,12 @@ void R_EntityParticles (entity_t *ent) angle = cl.time * avelocities[i][1]; sp = sin(angle); cp = cos(angle); - + forward[0] = cp*cy; forward[1] = cp*sy; forward[2] = -sp; - particle(pt_oneframe, 0x6f, particletexture, TPOLYTYPE_ALPHA, false, 2, 255, 9999, 0, ent->render.origin[0] + m_bytenormals[i][0]*dist + forward[0]*beamlength, ent->render.origin[1] + m_bytenormals[i][1]*dist + forward[1]*beamlength, ent->render.origin[2] + m_bytenormals[i][2]*dist + forward[2]*beamlength, 0, 0, 0); + particle(pt_oneframe, particlepalette[0x6f], particletexture, TPOLYTYPE_ALPHA, false, 2, 255, 9999, 0, ent->render.origin[0] + m_bytenormals[i][0]*dist + forward[0]*beamlength, ent->render.origin[1] + m_bytenormals[i][1]*dist + forward[1]*beamlength, ent->render.origin[2] + m_bytenormals[i][2]*dist + forward[2]*beamlength, 0, 0, 0, 0, 0, 0, 0, 0, 0); } } @@ -471,7 +491,7 @@ void R_ReadPointFile_f (void) int r; int c; char name[MAX_OSPATH]; - + sprintf (name,"maps/%s.pts", sv.name); COM_FOpenFile (name, &f, false, true); @@ -480,7 +500,7 @@ void R_ReadPointFile_f (void) Con_Printf ("couldn't open %s\n", name); return; } - + Con_Printf ("Reading %s...\n", name); c = 0; for (;;) @@ -490,13 +510,13 @@ void R_ReadPointFile_f (void) if (r != 3) break; c++; - + if (numparticles >= r_numparticles) { Con_Printf ("Not enough free particles\n"); break; } - particle(pt_static, (-c)&15, particletexture, TPOLYTYPE_ALPHA, false, 2, 255, 99999, 0, org[0], org[1], org[2], 0, 0, 0); + particle(pt_static, particlepalette[(-c)&15], particletexture, TPOLYTYPE_ALPHA, false, 2, 255, 99999, 0, org[0], org[1], org[2], 0, 0, 0, 0, 0, 0, 0, 0, 0); } Qclose (f); @@ -514,7 +534,7 @@ void R_ParseParticleEffect (void) { vec3_t org, dir; int i, count, msgcount, color; - + for (i=0 ; i<3 ; i++) org[i] = MSG_ReadCoord (); for (i=0 ; i<3 ; i++) @@ -522,14 +542,14 @@ void R_ParseParticleEffect (void) msgcount = MSG_ReadByte (); color = MSG_ReadByte (); -if (msgcount == 255) - count = 1024; -else - count = msgcount; - + if (msgcount == 255) + count = 1024; + else + count = msgcount; + R_RunParticleEffect (org, dir, color, count); } - + /* =============== R_ParticleExplosion @@ -538,58 +558,69 @@ R_ParticleExplosion */ void R_ParticleExplosion (vec3_t org, int smoke) { - int i; - if (!r_particles.value) return; // LordHavoc: particles are optional - -// particle(pt_smoke, (rand()&7) + 8, smokeparticletexture[rand()&7], TPOLYTYPE_ALPHA, true, 30, 255, 2, org[0], org[1], org[2], 0, 0, 0); + int i, j; + float f; + vec3_t v, end, ang; + byte noise1[32*32], noise2[32*32]; - i = Mod_PointInLeaf(org, cl.worldmodel)->contents; - if (i == CONTENTS_SLIME || i == CONTENTS_WATER) - { - for (i = 0;i < 128;i++) - particle(pt_bubble, 254, bubbleparticletexture, TPOLYTYPE_ADD, false, lhrandom(1, 2), 255, 9999, 1.5, org[0] + lhrandom(-16, 16), org[1] + lhrandom(-16, 16), org[2] + lhrandom(-16, 16), lhrandom(-96, 96), lhrandom(-96, 96), lhrandom(-96, 96)); - } - else - R_NewExplosion(org); - /* - else + if (r_particles.value && r_particles_explosions.value) { - int j; -// int color; - float f, forg[3], fvel[3], fvel2[3]; -// for (i = 0;i < 256;i++) -// particle(pt_fallfadespark, ramp3[rand()%6], particletexture, TPOLYTYPE_ALPHA, false, 1.5, lhrandom(128, 255), 5, org[0] + lhrandom(-16, 16), org[1] + lhrandom(-16, 16), org[2] + lhrandom(-16, 16), lhrandom(-192, 192), lhrandom(-192, 192), lhrandom(0, 384)); -// for (i = 0;i < 256;i++) -// particle(pt_fallfadespark, ramp3[rand()%6], particletexture, TPOLYTYPE_ALPHA, false, 1.5, lhrandom(128, 255), 5, org[0] + lhrandom(-16, 16), org[1] + lhrandom(-16, 16), org[2] + lhrandom(-16, 16), lhrandom(-150, 150), lhrandom(-150, 150), lhrandom(-150, 150)); - for (i = 0;i < 32;i++) + i = Mod_PointInLeaf(org, cl.worldmodel)->contents; + if (i == CONTENTS_SLIME || i == CONTENTS_WATER) + { + for (i = 0;i < 128;i++) + particle(pt_bubble, 0xFFFFFF, bubbleparticletexture, TPOLYTYPE_ALPHA, false, lhrandom(1, 2), 255, 9999, 1.5, org[0] + lhrandom(-16, 16), org[1] + lhrandom(-16, 16), org[2] + lhrandom(-16, 16), lhrandom(-96, 96), lhrandom(-96, 96), lhrandom(-96, 96), 0, 0, 0, 0, 0, 0); + + ang[2] = lhrandom(0, 360); + fractalnoise(noise1, 32, 4); + fractalnoise(noise2, 32, 8); + for (i = 0;i < 32;i++) + { + for (j = 0;j < 32;j++) + { + VectorRandom(v); + VectorMA(org, 16, v, v); + TraceLine(org, v, end, NULL, 0); + ang[0] = (j + 0.5f) * (360.0f / 32.0f); + ang[1] = (i + 0.5f) * (360.0f / 32.0f); + AngleVectors(ang, v, NULL, NULL); + f = noise1[j*32+i] * 1.5f; + VectorScale(v, f, v); + particle(pt_underwaterspark, noise2[j*32+i] * 0x010101, smokeparticletexture[rand()&7], TPOLYTYPE_ALPHA, false, 10, lhrandom(128, 255), 9999, 1.5, end[0], end[1], end[2], v[0], v[1], v[2], 512.0f, 0, 0, 0, 2, 0); + VectorScale(v, 0.75, v); + particle(pt_underwaterspark, explosparkramp[(noise2[j*32+i] >> 5)], particletexture, TPOLYTYPE_ALPHA, false, 10, lhrandom(128, 255), 9999, 1.5, end[0], end[1], end[2], v[0], v[1], v[2], 512.0f, 0, 0, 0, 2, 0); + } + } + } + else { - fvel[0] = lhrandom(-150, 150); - fvel[1] = lhrandom(-150, 150); - fvel[2] = lhrandom(-150, 150) + 80; -// particle(pt_flamefall, 106 + (rand()%6), particletexture, TPOLYTYPE_ALPHA, false, 3, 255, 5, forg[0] + lhrandom(-5, 5), forg[1] + lhrandom(-5, 5), forg[2] + lhrandom(-5, 5), fvel2[0], fvel2[1], fvel2[2]); - for (j = 0;j < 64;j++) + ang[2] = lhrandom(0, 360); + fractalnoise(noise1, 32, 4); + fractalnoise(noise2, 32, 8); + for (i = 0;i < 32;i++) { - forg[0] = lhrandom(-20, 20) + org[0]; - forg[1] = lhrandom(-20, 20) + org[1]; - forg[2] = lhrandom(-20, 20) + org[2]; - fvel2[0] = fvel[0] + lhrandom(-30, 30); - fvel2[1] = fvel[1] + lhrandom(-30, 30); - fvel2[2] = fvel[2] + lhrandom(-30, 30); - f = lhrandom(0.2, 1); - fvel2[0] *= f; - fvel2[1] *= f; - fvel2[2] *= f; - particle(pt_flamefall, 106 + (rand()%6), particletexture, TPOLYTYPE_ALPHA, false, 5, lhrandom(96, 192), 5, forg[0], forg[1], forg[2], fvel2[0], fvel2[1], fvel2[2]); + for (j = 0;j < 32;j++) + { + VectorRandom(v); + VectorMA(org, 16, v, v); + TraceLine(org, v, end, NULL, 0); + ang[0] = (j + 0.5f) * (360.0f / 32.0f); + ang[1] = (i + 0.5f) * (360.0f / 32.0f); + AngleVectors(ang, v, NULL, NULL); + f = noise1[j*32+i] * 1.5f; + VectorScale(v, f, v); + particle(pt_spark, noise2[j*32+i] * 0x010101, smokeparticletexture[rand()&7], TPOLYTYPE_ALPHA, false, 10, lhrandom(128, 255), 9999, 1.5, end[0], end[1], end[2], v[0], v[1], v[2] + 160.0f, 512.0f, 0, 0, 0, 2, 0); + VectorScale(v, 0.75, v); + particle(pt_spark, explosparkramp[(noise2[j*32+i] >> 5)], particletexture, TPOLYTYPE_ALPHA, false, 10, lhrandom(128, 255), 9999, 1.5, end[0], end[1], end[2], v[0], v[1], v[2] + 160.0f, 512.0f, 0, 0, 0, 2, 0); + // VectorRandom(v); + // VectorScale(v, 384, v); + // particle(pt_spark, explosparkramp[rand()&7], particletexture, TPOLYTYPE_ALPHA, false, 2, lhrandom(16, 255), 9999, 1.5, end[0], end[1], end[2], v[0], v[1], v[2] + 160.0f, 512.0f, 0, 0, 0, 2, 0); + } } } -// for (i = 0;i < 16;i++) -// particle(pt_smoke, 12+(rand()&3), smokeparticletexture[rand()&7], TPOLYTYPE_ALPHA, true, 20, 192, 99, org[0] + lhrandom(-20, 20), org[1] + lhrandom(-20, 20), org[2] + lhrandom(-20, 20), 0, 0, 0); -// for (i = 0;i < 50;i++) -// particle(pt_flamingdebris, ramp3[rand()%6], particletexture, TPOLYTYPE_ALPHA, false, 3, 255, 99, org[0] + lhrandom(-10, 10), org[1] + lhrandom(-10, 10), org[2] + lhrandom(-10, 10), lhrandom(-200, 200), lhrandom(-200, 200), lhrandom(-200, 200)); -// for (i = 0;i < 30;i++) -// particle(pt_smokingdebris, 10 + (rand()%6), particletexture, TPOLYTYPE_ALPHA, false, 2, 255, 99, org[0] + lhrandom(-10, 10), org[1] + lhrandom(-10, 10), org[2] + lhrandom(-10, 10), lhrandom(-100, 100), lhrandom(-100, 100), lhrandom(-100, 100)); } - */ + else + R_NewExplosion(org); } /* @@ -604,7 +635,7 @@ void R_ParticleExplosion2 (vec3_t org, int colorStart, int colorLength) if (!r_particles.value) return; // LordHavoc: particles are optional for (i = 0;i < 512;i++) - particle(pt_fade, colorStart + (i % colorLength), particletexture, TPOLYTYPE_ALPHA, false, 1.5, 255, 0.3, 0, org[0] + lhrandom(-8, 8), org[1] + lhrandom(-8, 8), org[2] + lhrandom(-8, 8), lhrandom(-192, 192), lhrandom(-192, 192), lhrandom(-192, 192)); + particle(pt_fade, particlepalette[colorStart + (i % colorLength)], particletexture, TPOLYTYPE_ALPHA, false, 1.5, 255, 0.3, 0, org[0] + lhrandom(-8, 8), org[1] + lhrandom(-8, 8), org[2] + lhrandom(-8, 8), lhrandom(-192, 192), lhrandom(-192, 192), lhrandom(-192, 192), 0, 0, 0, 0, 0.1f, 0); } /* @@ -617,11 +648,11 @@ void R_BlobExplosion (vec3_t org) { int i; if (!r_particles.value) return; // LordHavoc: particles are optional - + for (i = 0;i < 256;i++) - particle(pt_blob, 66+(rand()%6), particletexture, TPOLYTYPE_ALPHA, false, 4, 255, 9999, 0, org[0] + lhrandom(-16, 16), org[1] + lhrandom(-16, 16), org[2] + lhrandom(-16, 16), lhrandom(-4, 4), lhrandom(-4, 4), lhrandom(-128, 128)); + particle(pt_blob , particlepalette[ 66+(rand()%6)], particletexture, TPOLYTYPE_ALPHA, false, 4, 255, 9999, 0, org[0] + lhrandom(-16, 16), org[1] + lhrandom(-16, 16), org[2] + lhrandom(-16, 16), lhrandom(-4, 4), lhrandom(-4, 4), lhrandom(-128, 128), 0, 0, 0, 0, 0, 0); for (i = 0;i < 256;i++) - particle(pt_blob2, 150+(rand()%6), particletexture, TPOLYTYPE_ALPHA, false, 4, 255, 9999, 0, org[0] + lhrandom(-16, 16), org[1] + lhrandom(-16, 16), org[2] + lhrandom(-16, 16), lhrandom(-4, 4), lhrandom(-4, 4), lhrandom(-128, 128)); + particle(pt_blob2, particlepalette[150+(rand()%6)], particletexture, TPOLYTYPE_ALPHA, false, 4, 255, 9999, 0, org[0] + lhrandom(-16, 16), org[1] + lhrandom(-16, 16), org[2] + lhrandom(-16, 16), lhrandom(-4, 4), lhrandom(-4, 4), lhrandom(-128, 128), 0, 0, 0, 0, 0, 0); } /* @@ -633,14 +664,14 @@ R_RunParticleEffect void R_RunParticleEffect (vec3_t org, vec3_t dir, int color, int count) { if (!r_particles.value) return; // LordHavoc: particles are optional - + if (count == 1024) { R_ParticleExplosion(org, false); return; } while (count--) - particle(pt_fade, color + (rand()&7), particletexture, TPOLYTYPE_ALPHA, false, 1, 128, 9999, 0, org[0] + lhrandom(-8, 8), org[1] + lhrandom(-8, 8), org[2] + lhrandom(-8, 8), lhrandom(-15, 15), lhrandom(-15, 15), lhrandom(-15, 15)); + particle(pt_fade, particlepalette[color + (rand()&7)], particletexture, TPOLYTYPE_ALPHA, false, 1, 128, 9999, 0, org[0] + lhrandom(-8, 8), org[1] + lhrandom(-8, 8), org[2] + lhrandom(-8, 8), lhrandom(-15, 15), lhrandom(-15, 15), lhrandom(-15, 15), 0, 0, 0, 0, 0, 0); } // LordHavoc: added this for spawning sparks/dust (which have strong gravity) @@ -651,19 +682,21 @@ R_SparkShower */ void R_SparkShower (vec3_t org, vec3_t dir, int count) { + particletexture_t *tex; if (!r_particles.value) return; // LordHavoc: particles are optional - R_Decal(org, bulletholetexture[rand()&7], 16, 0, 0, 0, 255); + tex = &bulletholetexture[rand()&7]; + R_Decal(org, particlefonttexture, tex->s1, tex->t1, tex->s2, tex->t2, 16, 0, 0, 0, 255); // smoke puff if (r_particles_smoke.value) - particle(pt_bulletsmoke, 10, smokeparticletexture[rand()&7], TPOLYTYPE_ALPHA, true, 5, 255, 9999, 0, org[0], org[1], org[2], lhrandom(-8, 8), lhrandom(-8, 8), lhrandom(0, 16)); + particle(pt_bulletsmoke, 0xA0A0A0, smokeparticletexture[rand()&7], TPOLYTYPE_ALPHA, true, 5, 255, 9999, 0, org[0], org[1], org[2], lhrandom(-8, 8), lhrandom(-8, 8), lhrandom(0, 16), 0, 0, 0, 0, 0, 0); if (r_particles_sparks.value) { // sparks while(count--) - particle(pt_spark, ramp3[rand()%6], particletexture, TPOLYTYPE_ADD, false, 1, lhrandom(0, 255), 9999, 1.5, org[0], org[1], org[2], lhrandom(-64, 64), lhrandom(-64, 64), lhrandom(0, 128)); + particle(pt_spark, particlepalette[0x68 + (rand() & 7)], particletexture, TPOLYTYPE_ALPHA, false, 1, lhrandom(0, 255), 9999, 1.5, org[0], org[1], org[2], lhrandom(-64, 64), lhrandom(-64, 64), lhrandom(0, 128), 512.0f, 0, 0, 0, 0.2f, 0); } } @@ -679,7 +712,7 @@ void R_BloodPuff (vec3_t org, vec3_t vel, int count) bloodcount += count; while(bloodcount >= 10) { - particle(pt_blood, 68+(rand()&3), smokeparticletexture[rand()&7], TPOLYTYPE_ALPHA, true, 24, 255, 9999, -1, org[0], org[1], org[2], vel[0] + lhrandom(-64, 64), vel[1] + lhrandom(-64, 64), vel[2] + lhrandom(-64, 64)); + particle(pt_blood, 0x300000, smokeparticletexture[rand()&7], TPOLYTYPE_ALPHA, true, 24, 255, 9999, -1, org[0], org[1], org[2], vel[0] + lhrandom(-64, 64), vel[1] + lhrandom(-64, 64), vel[2] + lhrandom(-64, 64), 0, 0, 0, 0, 1.0f, 0); bloodcount -= 10; } } @@ -701,7 +734,7 @@ void R_BloodShower (vec3_t mins, vec3_t maxs, float velspeed, int count) velscale[0] = velspeed * 2.0 / diff[0]; velscale[1] = velspeed * 2.0 / diff[1]; velscale[2] = velspeed * 2.0 / diff[2]; - + while (count--) { vec3_t org, vel; @@ -711,7 +744,7 @@ void R_BloodShower (vec3_t mins, vec3_t maxs, float velspeed, int count) vel[0] = (org[0] - center[0]) * velscale[0]; vel[1] = (org[1] - center[1]) * velscale[1]; vel[2] = (org[2] - center[2]) * velscale[2]; - particle(pt_blood, 68+(rand()&3), smokeparticletexture[rand()&7], TPOLYTYPE_ALPHA, true, 24, 255, 9999, -1, org[0], org[1], org[2], vel[0], vel[1], vel[2]); + particle(pt_blood, 0x300000, smokeparticletexture[rand()&7], TPOLYTYPE_ALPHA, true, 24, 255, 9999, -1, org[0], org[1], org[2], vel[0], vel[1], vel[2], 0, 0, 0, 0, 1.0f, 0); } } @@ -724,7 +757,7 @@ void R_ParticleCube (vec3_t mins, vec3_t maxs, vec3_t dir, int count, int colorb if (maxs[2] <= mins[2]) {t = mins[2];mins[2] = maxs[2];maxs[2] = t;} while (count--) - particle(gravity ? pt_grav : pt_static, colorbase + (rand()&3), particletexture, TPOLYTYPE_ALPHA, false, 2, 255, lhrandom(1, 2), 0, lhrandom(mins[0], maxs[0]), lhrandom(mins[1], maxs[1]), lhrandom(mins[2], maxs[2]), dir[0] + lhrandom(-randomvel, randomvel), dir[1] + lhrandom(-randomvel, randomvel), dir[2] + lhrandom(-randomvel, randomvel)); + particle(gravity ? pt_grav : pt_static, particlepalette[colorbase + (rand()&3)], particletexture, TPOLYTYPE_ALPHA, false, 2, 255, lhrandom(1, 2), 0, lhrandom(mins[0], maxs[0]), lhrandom(mins[1], maxs[1]), lhrandom(mins[2], maxs[2]), dir[0] + lhrandom(-randomvel, randomvel), dir[1] + lhrandom(-randomvel, randomvel), dir[2] + lhrandom(-randomvel, randomvel), 0, 0, 0, 0, 0, 0); } void R_ParticleRain (vec3_t mins, vec3_t maxs, vec3_t dir, int count, int colorbase, int type) @@ -756,7 +789,7 @@ void R_ParticleRain (vec3_t mins, vec3_t maxs, vec3_t dir, int count, int colorb vel[0] = dir[0] + lhrandom(-16, 16); vel[1] = dir[1] + lhrandom(-16, 16); vel[2] = dir[2] + lhrandom(-32, 32); - particle4(pt_rain, colorbase + (rand()&3), rainparticletexture, TPOLYTYPE_ALPHA, true, 3, 255, t, 0, lhrandom(mins[0], maxs[0]), lhrandom(mins[1], maxs[1]), z, vel[0], vel[1], vel[2], 0, vel[0], vel[1], vel[2]); + particle(pt_rain, particlepalette[colorbase + (rand()&3)], rainparticletexture, TPOLYTYPE_ALPHA, true, 3, 255, t, 0, lhrandom(mins[0], maxs[0]), lhrandom(mins[1], maxs[1]), z, vel[0], vel[1], vel[2], 0, vel[0], vel[1], vel[2], 0, 0); } break; case 1: @@ -765,7 +798,7 @@ void R_ParticleRain (vec3_t mins, vec3_t maxs, vec3_t dir, int count, int colorb vel[0] = dir[0] + lhrandom(-16, 16); vel[1] = dir[1] + lhrandom(-16, 16); vel[2] = dir[2] + lhrandom(-32, 32); - particle4(pt_snow, colorbase + (rand()&3), particletexture, TPOLYTYPE_ALPHA, false, 2, 255, t, 0, lhrandom(mins[0], maxs[0]), lhrandom(mins[1], maxs[1]), z, vel[0], vel[1], vel[2], 0, vel[0], vel[1], vel[2]); + particle(pt_snow, particlepalette[colorbase + (rand()&3)], particletexture, TPOLYTYPE_ALPHA, false, 2, 255, t, 0, lhrandom(mins[0], maxs[0]), lhrandom(mins[1], maxs[1]), z, vel[0], vel[1], vel[2], 0, vel[0], vel[1], vel[2], 0, 0); } break; default: @@ -782,7 +815,7 @@ void R_FlameCube (vec3_t mins, vec3_t maxs, int count) if (maxs[2] <= mins[2]) {t = mins[2];mins[2] = maxs[2];maxs[2] = t;} while (count--) - particle(pt_flame, 224 + (rand()&15), smokeparticletexture[rand()&7], TPOLYTYPE_ADD, false, 8, 255, 9999, 1.1, lhrandom(mins[0], maxs[0]), lhrandom(mins[1], maxs[1]), lhrandom(mins[2], maxs[2]), lhrandom(-32, 32), lhrandom(-32, 32), lhrandom(-32, 64)); + particle(pt_flame, particlepalette[224 + (rand()&15)], smokeparticletexture[rand()&7], TPOLYTYPE_ALPHA, false, 8, 255, 9999, 1.1, lhrandom(mins[0], maxs[0]), lhrandom(mins[1], maxs[1]), lhrandom(mins[2], maxs[2]), lhrandom(-32, 32), lhrandom(-32, 32), lhrandom(-32, 64), 0, 0, 0, 0, 0.1f, 0); } void R_Flames (vec3_t org, vec3_t vel, int count) @@ -790,7 +823,7 @@ void R_Flames (vec3_t org, vec3_t vel, int count) if (!r_particles.value) return; // LordHavoc: particles are optional while (count--) - particle(pt_flame, 224 + (rand()&15), smokeparticletexture[rand()&7], TPOLYTYPE_ADD, false, 8, 255, 9999, 1.1, org[0], org[1], org[2], vel[0] + lhrandom(-128, 128), vel[1] + lhrandom(-128, 128), vel[2] + lhrandom(-128, 128)); + particle(pt_flame, particlepalette[224 + (rand()&15)], smokeparticletexture[rand()&7], TPOLYTYPE_ALPHA, false, 8, 255, 9999, 1.1, org[0], org[1], org[2], vel[0] + lhrandom(-128, 128), vel[1] + lhrandom(-128, 128), vel[2] + lhrandom(-128, 128), 0, 0, 0, 0, 0.1f, 0); } @@ -819,8 +852,7 @@ void R_LavaSplash (vec3_t origin) org[1] = origin[1] + dir[1]; org[2] = origin[2] + lhrandom(0, 64); vel = lhrandom(50, 120) / VectorLength(dir); // normalize and scale - particle(pt_lavasplash, 224 + (rand()&7), particletexture, TPOLYTYPE_ALPHA, false, 7, 255, 9999, 0, org[0], org[1], org[2], dir[0] * vel, dir[1] * vel, dir[2] * vel); -// particle(pt_lavasplash, 224 + (rand()&7), particletexture, TPOLYTYPE_ALPHA, false, 7, 255, 9999, 0, origin[0] + i, origin[1] + j, origin[2] + lhrandom(0, 63), i * lhrandom(0.125, 0.25), j * lhrandom(0.125, 0.25), lhrandom(64, 128)); + particle(pt_lavasplash, particlepalette[224 + (rand()&7)], particletexture, TPOLYTYPE_ALPHA, false, 7, 255, 9999, 0, org[0], org[1], org[2], dir[0] * vel, dir[1] * vel, dir[2] * vel, 0, 0, 0, 0, 0, 0); } } } @@ -839,7 +871,7 @@ void R_TeleportSplash (vec3_t org) for (i=-16 ; i<16 ; i+=8) for (j=-16 ; j<16 ; j+=8) for (k=-24 ; k<32 ; k+=8) - particle(pt_fade, 254, particletexture, TPOLYTYPE_ADD, false, 1, lhrandom(64, 128), 9999, 0, org[0] + i + lhrandom(0, 8), org[1] + j + lhrandom(0, 8), org[2] + k + lhrandom(0, 8), i*2 + lhrandom(-12.5, 12.5), j*2 + lhrandom(-12.5, 12.5), k*2 + lhrandom(27.5, 52.5)); + particle(pt_fade, 0xFFFFFF, particletexture, TPOLYTYPE_ALPHA, false, 1, lhrandom(64, 128), 9999, 0, org[0] + i + lhrandom(0, 8), org[1] + j + lhrandom(0, 8), org[2] + k + lhrandom(0, 8), i*2 + lhrandom(-12.5, 12.5), j*2 + lhrandom(-12.5, 12.5), k*2 + lhrandom(27.5, 52.5), 0, 0, 0, 0, 0.1f, -512.0f); } void R_RocketTrail (vec3_t start, vec3_t end, int type, entity_t *ent) @@ -854,9 +886,9 @@ void R_RocketTrail (vec3_t start, vec3_t end, int type, entity_t *ent) VectorNormalize(dir); if (type == 0 && host_frametime != 0) // rocket glow - particle(pt_oneframe, 254, rocketglowparticletexture, TPOLYTYPE_ADD, false, 24, 255, 9999, 0, end[0] - 12 * dir[0], end[1] - 12 * dir[1], end[2] - 12 * dir[2], 0, 0, 0); + particle(pt_oneframe, 0xFFFFFF, rocketglowparticletexture, TPOLYTYPE_ALPHA, false, 24, 255, 9999, 0, end[0] - 12 * dir[0], end[1] - 12 * dir[1], end[2] - 12 * dir[2], 0, 0, 0, 0, 0, 0, 0, 0, 0); - t = ent->render.trail_time; + t = ent->persistent.trail_time; if (t >= cl.time) return; // no particles to spawn this frame (sparse trail) @@ -868,7 +900,7 @@ void R_RocketTrail (vec3_t start, vec3_t end, int type, entity_t *ent) if (len <= 0.01f) { // advance the trail time - ent->render.trail_time = cl.time; + ent->persistent.trail_time = cl.time; return; } speed = len / (cl.time - cl.oldtime); @@ -883,7 +915,7 @@ void R_RocketTrail (vec3_t start, vec3_t end, int type, entity_t *ent) if (contents == CONTENTS_SKY || contents == CONTENTS_LAVA) { // advance the trail time - ent->render.trail_time = cl.time; + ent->persistent.trail_time = cl.time; return; } @@ -902,19 +934,19 @@ void R_RocketTrail (vec3_t start, vec3_t end, int type, entity_t *ent) dec = cl.time - t; else if (bubbles && r_particles_bubbles.value) { - dec = 0.01f; - particle(pt_bubble, 254, bubbleparticletexture, polytype, false, lhrandom(1, 2), 255, 9999, 1.5, start[0], start[1], start[2], lhrandom(-16, 16), lhrandom(-16, 16), lhrandom(-16, 16)); - particle(pt_bubble, 254, bubbleparticletexture, polytype, false, lhrandom(1, 2), 255, 9999, 1.5, start[0], start[1], start[2], lhrandom(-16, 16), lhrandom(-16, 16), lhrandom(-16, 16)); - particle(pt_smoke, 254, smokeparticletexture[rand()&7], polytype, false, 2, 160, 9999, 0, start[0], start[1], start[2], 0, 0, 0); + dec = 0.005f; + particle(pt_bubble, 0xFFFFFF, bubbleparticletexture, polytype, false, lhrandom(1, 2), 255, 9999, 1.5, start[0], start[1], start[2], lhrandom(-16, 16), lhrandom(-16, 16), lhrandom(-16, 16), 0, 0, 0, 0, 0, 0); + particle(pt_bubble, 0xFFFFFF, bubbleparticletexture, polytype, false, lhrandom(1, 2), 255, 9999, 1.5, start[0], start[1], start[2], lhrandom(-16, 16), lhrandom(-16, 16), lhrandom(-16, 16), 0, 0, 0, 0, 0, 0); + particle(pt_smoke, 0xFFFFFF, smokeparticletexture[rand()&7], polytype, false, 2, 160, 9999, 0, start[0], start[1], start[2], 0, 0, 0, 0, 0, 0, 0, 0, 0); } else { - dec = 0.01f; - particle(pt_smoke, 12, smokeparticletexture[rand()&7], polytype, true, 2, 160, 9999, 0, start[0], start[1], start[2], 0, 0, 0); -// particle(pt_spark, 0x68 + (rand() & 7), particletexture, TPOLYTYPE_ADD, false, 1, lhrandom(128, 255), 9999, 1.5, start[0], start[1], start[2], lhrandom(-64, 64) - vel[0] * 0.25, lhrandom(-64, 64) - vel[1] * 0.25, lhrandom(-64, 64) - vel[2] * 0.25); -// particle(pt_spark, 0x68 + (rand() & 7), particletexture, TPOLYTYPE_ADD, false, 1, lhrandom(128, 255), 9999, 1.5, start[0], start[1], start[2], lhrandom(-64, 64) - vel[0] * 0.25, lhrandom(-64, 64) - vel[1] * 0.25, lhrandom(-64, 64) - vel[2] * 0.25); -// particle(pt_spark, 0x68 + (rand() & 7), particletexture, TPOLYTYPE_ADD, false, 1, lhrandom(128, 255), 9999, 1.5, start[0], start[1], start[2], lhrandom(-64, 64) - vel[0] * 0.25, lhrandom(-64, 64) - vel[1] * 0.25, lhrandom(-64, 64) - vel[2] * 0.25); -// particle(pt_spark, 0x68 + (rand() & 7), particletexture, TPOLYTYPE_ADD, false, 1, lhrandom(128, 255), 9999, 1.5, start[0], start[1], start[2], lhrandom(-64, 64) - vel[0] * 0.25, lhrandom(-64, 64) - vel[1] * 0.25, lhrandom(-64, 64) - vel[2] * 0.25); + dec = 0.005f; + particle(pt_smoke, 0xC0C0C0, smokeparticletexture[rand()&7], polytype, true, 2, 160, 9999, 0, start[0], start[1], start[2], 0, 0, 0, 0, 0, 0, 0, 0, 0); + //particle(pt_spark, particlepalette[0x68 + (rand() & 7)], particletexture, TPOLYTYPE_ALPHA, false, 1, lhrandom(128, 255), 9999, 1.5, start[0], start[1], start[2], lhrandom(-64, 64) - vel[0] * 0.0625, lhrandom(-64, 64) - vel[1] * 0.0625, lhrandom(-64, 64) - vel[2] * 0.0625, 512.0f, 0, 0, 0, 0.1f, 0); + //particle(pt_spark, particlepalette[0x68 + (rand() & 7)], particletexture, TPOLYTYPE_ALPHA, false, 1, lhrandom(128, 255), 9999, 1.5, start[0], start[1], start[2], lhrandom(-64, 64) - vel[0] * 0.0625, lhrandom(-64, 64) - vel[1] * 0.0625, lhrandom(-64, 64) - vel[2] * 0.0625, 512.0f, 0, 0, 0, 0.1f, 0); + //particle(pt_spark, particlepalette[0x68 + (rand() & 7)], particletexture, TPOLYTYPE_ALPHA, false, 1, lhrandom(128, 255), 9999, 1.5, start[0], start[1], start[2], lhrandom(-64, 64) - vel[0] * 0.0625, lhrandom(-64, 64) - vel[1] * 0.0625, lhrandom(-64, 64) - vel[2] * 0.0625, 512.0f, 0, 0, 0, 0.1f, 0); + //particle(pt_spark, particlepalette[0x68 + (rand() & 7)], particletexture, TPOLYTYPE_ALPHA, false, 1, lhrandom(128, 255), 9999, 1.5, start[0], start[1], start[2], lhrandom(-64, 64) - vel[0] * 0.0625, lhrandom(-64, 64) - vel[1] * 0.0625, lhrandom(-64, 64) - vel[2] * 0.0625, 512.0f, 0, 0, 0, 0.1f, 0); } break; @@ -925,14 +957,14 @@ void R_RocketTrail (vec3_t start, vec3_t end, int type, entity_t *ent) else if (bubbles && r_particles_bubbles.value) { dec = 0.02f; - particle(pt_bubble, 254, bubbleparticletexture, polytype, false, lhrandom(1, 2), 255, 9999, 1.5, start[0], start[1], start[2], lhrandom(-16, 16), lhrandom(-16, 16), lhrandom(-16, 16)); - particle(pt_bubble, 254, bubbleparticletexture, polytype, false, lhrandom(1, 2), 255, 9999, 1.5, start[0], start[1], start[2], lhrandom(-16, 16), lhrandom(-16, 16), lhrandom(-16, 16)); - particle(pt_smoke, 254, smokeparticletexture[rand()&7], polytype, false, 2, 160, 9999, 0, start[0], start[1], start[2], 0, 0, 0); + particle(pt_bubble, 0xFFFFFF, bubbleparticletexture, polytype, false, lhrandom(1, 2), 255, 9999, 1.5, start[0], start[1], start[2], lhrandom(-16, 16), lhrandom(-16, 16), lhrandom(-16, 16), 0, 0, 0, 0, 0, 0); + particle(pt_bubble, 0xFFFFFF, bubbleparticletexture, polytype, false, lhrandom(1, 2), 255, 9999, 1.5, start[0], start[1], start[2], lhrandom(-16, 16), lhrandom(-16, 16), lhrandom(-16, 16), 0, 0, 0, 0, 0, 0); + particle(pt_smoke, 0xFFFFFF, smokeparticletexture[rand()&7], polytype, false, 2, 160, 9999, 0, start[0], start[1], start[2], 0, 0, 0, 0, 0, 0, 0, 0, 0); } else { dec = 0.02f; - particle(pt_smoke, 8, smokeparticletexture[rand()&7], polytype, true, 2, 160, 9999, 0, start[0], start[1], start[2], 0, 0, 0); + particle(pt_smoke, 0x808080, smokeparticletexture[rand()&7], polytype, true, 2, 160, 9999, 0, start[0], start[1], start[2], 0, 0, 0, 0, 0, 0, 0, 0, 0); } break; @@ -942,8 +974,8 @@ void R_RocketTrail (vec3_t start, vec3_t end, int type, entity_t *ent) dec = cl.time - t; else { - dec = 0.2f; - particle(pt_blood, 67+(rand()&3), smokeparticletexture[rand()&7], polytype, true, 24, 255, 9999, -1, start[0], start[1], start[2], vel[0] + lhrandom(-64, 64), vel[1] + lhrandom(-64, 64), vel[2] + lhrandom(-64, 64)); + dec = 0.1f; + particle(pt_blood, 0x300000, smokeparticletexture[rand()&7], polytype, true, 24, 255, 9999, -1, start[0], start[1], start[2], vel[0] + lhrandom(-64, 64), vel[1] + lhrandom(-64, 64), vel[2] + lhrandom(-64, 64), 0, 0, 0, 0, 1.0f, 0); } break; @@ -952,24 +984,24 @@ void R_RocketTrail (vec3_t start, vec3_t end, int type, entity_t *ent) dec = cl.time - t; else { - dec = 0.3f; - particle(pt_blood, 67+(rand()&3), smokeparticletexture[rand()&7], polytype, true, 24, 255, 9999, -1, start[0], start[1], start[2], vel[0] + lhrandom(-64, 64), vel[1] + lhrandom(-64, 64), vel[2] + lhrandom(-64, 64)); + dec = 0.15f; + particle(pt_blood, 0x300000, smokeparticletexture[rand()&7], polytype, true, 24, 255, 9999, -1, start[0], start[1], start[2], vel[0] + lhrandom(-64, 64), vel[1] + lhrandom(-64, 64), vel[2] + lhrandom(-64, 64), 0, 0, 0, 0, 1.0f, 0); } break; case 3: // green tracer dec = 0.02f; - particle(pt_fade, 56, smokeparticletexture[rand()&7], polytype, false, 4, 255, 9999, 0, start[0], start[1], start[2], 0, 0, 0); + particle(pt_fade, 0x373707, smokeparticletexture[rand()&7], polytype, false, 4, 255, 9999, 0, start[0], start[1], start[2], 0, 0, 0, 0, 0, 0, 0, 0, 0); break; case 5: // flame tracer dec = 0.02f; - particle(pt_fade, 234, smokeparticletexture[rand()&7], polytype, false, 4, 255, 9999, 0, start[0], start[1], start[2], 0, 0, 0); + particle(pt_fade, 0xCF632B, smokeparticletexture[rand()&7], polytype, false, 4, 255, 9999, 0, start[0], start[1], start[2], 0, 0, 0, 0, 0, 0, 0, 0, 0); break; case 6: // voor trail dec = 0.05f; // sparse trail - particle(pt_fade, 152 + (rand()&3), smokeparticletexture[rand()&7], polytype, false, 4, 255, 9999, 0, start[0], start[1], start[2], 0, 0, 0); + particle(pt_fade, 0x47232B, smokeparticletexture[rand()&7], polytype, false, 4, 255, 9999, 0, start[0], start[1], start[2], 0, 0, 0, 0, 0, 0, 0, 0, 0); break; case 7: // Nehahra smoke tracer @@ -978,7 +1010,7 @@ void R_RocketTrail (vec3_t start, vec3_t end, int type, entity_t *ent) else { dec = 0.14f; - particle(pt_smoke, 12, smokeparticletexture[rand()&7], polytype, true, 10, 64, 9999, 0, start[0], start[1], start[2], 0, 0, 0); + particle(pt_smoke, 0xC0C0C0, smokeparticletexture[rand()&7], polytype, true, 10, 64, 9999, 0, start[0], start[1], start[2], 0, 0, 0, 0, 0, 0, 0, 0, 0); } break; } @@ -988,7 +1020,7 @@ void R_RocketTrail (vec3_t start, vec3_t end, int type, entity_t *ent) dec *= speed; VectorMA (start, dec, vec, start); } - ent->render.trail_time = t; + ent->persistent.trail_time = t; } void R_RocketTrail2 (vec3_t start, vec3_t end, int color, entity_t *ent) @@ -1001,9 +1033,10 @@ void R_RocketTrail2 (vec3_t start, vec3_t end, int color, entity_t *ent) VectorSubtract (end, start, vec); len = (int) (VectorNormalizeLength (vec) * (1.0f / 3.0f)); VectorScale(vec, 3, vec); + color = particlepalette[color]; while (len--) { - particle(pt_smoke, color, particletexture, TPOLYTYPE_ALPHA, false, 8, 192, 9999, 0, start[0], start[1], start[2], 0, 0, 0); + particle(pt_smoke, color, particletexture, TPOLYTYPE_ALPHA, false, 8, 192, 9999, 0, start[0], start[1], start[2], 0, 0, 0, 0, 0, 0, 0, 0, 0); VectorAdd (start, vec, start); } } @@ -1017,9 +1050,9 @@ R_DrawParticles void R_MoveParticles (void) { particle_t *p; - int i, activeparticles, maxparticle, j, a; - vec3_t v; - float gravity, dvel, frametime; + int i, activeparticles, maxparticle, j, a, b, pressureused = false; + vec3_t v, org, o, normal; + float gravity, dvel, frametime, f; // LordHavoc: early out condition if (!numparticles) @@ -1043,44 +1076,37 @@ void R_MoveParticles (void) } VectorCopy(p->org, p->oldorg); - p->org[0] += p->vel[0]*frametime; - p->org[1] += p->vel[1]*frametime; - p->org[2] += p->vel[2]*frametime; + VectorMA(p->org, frametime, p->vel, p->org); + if (p->friction) + { + f = 1.0f - (p->friction * frametime); + VectorScale(p->vel, f, p->vel); + } + VectorCopy(p->org, org); if (p->bounce) { vec3_t normal; float dist; - if (TraceLine(p->oldorg, p->org, v, normal) < 1) + if (TraceLine(p->oldorg, p->org, v, normal, 0) < 1) { VectorCopy(v, p->org); if (p->bounce < 0) { - byte *color24 = (byte *) &d_8to24table[(int)p->color]; - R_Decal(v, p->tex, p->scale, color24[0], color24[1], color24[2], p->alpha); + R_Decal(v, particlefonttexture, p->tex->s1, p->tex->t1, p->tex->s2, p->tex->t2, p->scale, p->color[0], p->color[1], p->color[2], p->alpha); p->die = -1; freeparticles[j++] = p; continue; - /* - VectorClear(p->vel); - p->type = pt_decal; - // have to negate the direction (why?) - VectorNegate(normal, p->direction); - VectorVectors(p->direction, p->decalright, p->decalup); - VectorSubtract(p->org, p->direction, p->org); // push off the surface a bit so it doesn't flicker - p->bounce = 0; - p->time2 = cl.time + 30; - */ } else { dist = DotProduct(p->vel, normal) * -p->bounce; - VectorMAQuick(p->vel, dist, normal, p->vel); + VectorMA(p->vel, dist, normal, p->vel); if (DotProduct(p->vel, p->vel) < 0.03) VectorClear(p->vel); } } } - + switch (p->type) { case pt_static: @@ -1100,9 +1126,6 @@ void R_MoveParticles (void) case pt_grav: p->vel[2] -= gravity; break; - case pt_slowgrav: - p->vel[2] -= gravity * 0.05; - break; case pt_lavasplash: p->vel[2] -= gravity * 0.05; p->alpha -= frametime * 192; @@ -1129,23 +1152,23 @@ void R_MoveParticles (void) { case CONTENTS_LAVA: case CONTENTS_SLIME: - p->tex = smokeparticletexture[rand()&7]; + p->tex = &smokeparticletexture[rand()&7]; p->type = pt_steam; p->alpha = 96; p->scale = 5; p->vel[2] = 96; break; case CONTENTS_WATER: - p->tex = smokeparticletexture[rand()&7]; + p->tex = &smokeparticletexture[rand()&7]; p->type = pt_splash; p->alpha = 96; p->scale = 5; p->vel[2] = 96; break; default: // CONTENTS_SOLID and any others - TraceLine(p->oldorg, p->org, v, normal); + TraceLine(p->oldorg, p->org, v, normal, 0); VectorCopy(v, p->org); - p->tex = smokeparticletexture[rand()&7]; + p->tex = &smokeparticletexture[rand()&7]; p->type = pt_fade; VectorClear(p->vel); break; @@ -1153,16 +1176,57 @@ void R_MoveParticles (void) } break; case pt_blood: - if (Mod_PointInLeaf(p->org, cl.worldmodel)->contents != CONTENTS_EMPTY) + p->friction = 1; + a = Mod_PointInLeaf(p->org, cl.worldmodel)->contents; + if (a != CONTENTS_EMPTY) { - p->die = -1; - break; + if (a == CONTENTS_WATER || a == CONTENTS_SLIME) + { + p->friction = 5; + p->scale += frametime * 32.0f; + p->alpha -= frametime * 128.0f; + p->vel[2] += gravity * 0.125f; + if (p->alpha < 1) + p->die = -1; + break; + } + else + { + p->die = -1; + break; + } } p->vel[2] -= gravity * 0.5; break; case pt_spark: - p->alpha -= frametime * 512; + p->alpha -= frametime * p->time2; p->vel[2] -= gravity; + if (p->alpha < 1) + p->die = -1; + else if (Mod_PointInLeaf(p->org, cl.worldmodel)->contents != CONTENTS_EMPTY) + p->type = pt_underwaterspark; + break; + case pt_underwaterspark: + if (Mod_PointInLeaf(p->org, cl.worldmodel)->contents == CONTENTS_EMPTY) + { + p->tex = &smokeparticletexture[rand()&7]; + p->color[0] = p->color[1] = p->color[2] = 255; + p->scale = 16; + p->type = pt_explosionsplash; + } + else + p->vel[2] += gravity * 0.5f; + p->alpha -= frametime * p->time2; + if (p->alpha < 1) + p->die = -1; + break; + case pt_explosionsplash: + if (Mod_PointInLeaf(p->org, cl.worldmodel)->contents == CONTENTS_EMPTY) + p->vel[2] -= gravity; + else + p->alpha = 0; + p->scale += frametime * 64.0f; + p->alpha -= frametime * 1024.0f; if (p->alpha < 1) p->die = -1; break; @@ -1175,7 +1239,7 @@ void R_MoveParticles (void) a = Mod_PointInLeaf(p->org, cl.worldmodel)->contents; if (a != CONTENTS_WATER && a != CONTENTS_SLIME) { - p->tex = smokeparticletexture[rand()&7]; + p->tex = &smokeparticletexture[rand()&7]; p->type = pt_splashpuff; p->scale = 4; p->vel[0] = p->vel[1] = p->vel[2] = 0; @@ -1199,14 +1263,14 @@ void R_MoveParticles (void) case pt_bulletsmoke: p->scale += frametime * 16; p->alpha -= frametime * 1024; - p->vel[2] += gravity * 0.05; + p->vel[2] += gravity * 0.1; if (p->alpha < 1) p->die = -1; break; case pt_smoke: - p->scale += frametime * 32; - p->alpha -= frametime * 512; - p->vel[2] += gravity * 0.05; + p->scale += frametime * 24; + p->alpha -= frametime * 256; + p->vel[2] += gravity * 0.1; if (p->alpha < 1) p->die = -1; break; @@ -1218,97 +1282,60 @@ void R_MoveParticles (void) p->die = -1; break; case pt_splashpuff: -// p->scale += frametime * 24; p->alpha -= frametime * 1024; if (p->alpha < 1) p->die = -1; break; case pt_rain: - a = Mod_PointInLeaf(p->org, cl.worldmodel)->contents; - if (a != CONTENTS_EMPTY && a != CONTENTS_SKY) + f = 0; + b = Mod_PointInLeaf(p->oldorg, cl.worldmodel)->contents; + VectorCopy(p->oldorg, o); + while (f < 1) { - vec3_t normal; - if (a == CONTENTS_SOLID && Mod_PointInLeaf(p->oldorg, cl.worldmodel)->contents == CONTENTS_SOLID) - break; // still in solid - p->die = cl.time + 1000; - p->vel[0] = p->vel[1] = p->vel[2] = 0; - switch (a) + a = b; + f = TraceLine(o, p->org, v, normal, a); + b = traceline_endcontents; + if (f < 1 && b != CONTENTS_EMPTY && b != CONTENTS_SKY) { - case CONTENTS_LAVA: - case CONTENTS_SLIME: - p->tex = smokeparticletexture[rand()&7]; - p->type = pt_steam; - p->scale = 3; - p->vel[2] = 96; - break; - case CONTENTS_WATER: - p->tex = smokeparticletexture[rand()&7]; - p->type = pt_splashpuff; - p->scale = 4; - break; - default: // CONTENTS_SOLID and any others - TraceLine(p->oldorg, p->org, v, normal); + p->die = cl.time + 1000; + p->vel[0] = p->vel[1] = p->vel[2] = 0; VectorCopy(v, p->org); - p->tex = smokeparticletexture[rand()&7]; - p->type = pt_splashpuff; - p->scale = 4; - break; + switch (b) + { + case CONTENTS_LAVA: + case CONTENTS_SLIME: + p->tex = &smokeparticletexture[rand()&7]; + p->type = pt_steam; + p->scale = 3; + p->vel[2] = 96; + break; + default: // water, solid, and anything else + p->tex = &raindropsplashparticletexture[0]; + p->time2 = 0; + VectorCopy(normal, p->vel2); + // VectorAdd(p->org, normal, p->org); + p->type = pt_raindropsplash; + p->scale = 8; + break; + } } } break; - case pt_flame: - p->alpha -= frametime * 512; - p->vel[2] += gravity; -// p->scale -= frametime * 16; - if (p->alpha < 16) - p->die = -1; - break; - /* - case pt_flamingdebris: - if (cl.time >= p->time2) + case pt_raindropsplash: + p->time2 += frametime * 64.0f; + if (p->time2 >= 16.0f) { - p->time2 = cl.time + 0.01; - particle(pt_flame, p->color, particletexture, TPOLYTYPE_ADD, false, 4, p->alpha, 9999, 0, org[0], org[1], org[2], lhrandom(-50, 50), lhrandom(-50, 50), lhrandom(-50, 50)); - } - p->alpha -= frametime * 512; - p->vel[2] -= gravity * 0.5f; - if (Mod_PointInLeaf(p->org, cl.worldmodel)->contents != CONTENTS_EMPTY) - p->die = -1; - if (p->alpha < 1) p->die = -1; - break; - case pt_smokingdebris: - if (cl.time >= p->time2) - { - p->time2 = cl.time + 0.01; - particle2(pt_flame, 15, smokeparticletexture[rand()&7], TPOLYTYPE_ALPHA, false, 4, p->alpha, 9999, 0, org[0], org[1], org[2], lhrandom(-50, 50), lhrandom(-50, 50), lhrandom(-50, 50)); + break; } - p->alpha -= frametime * 512; - p->vel[2] -= gravity * 0.5f; - if (Mod_PointInLeaf(p->org, cl.worldmodel)->contents != CONTENTS_EMPTY) - p->die = -1; - if (p->alpha < 1) - p->die = -1; + p->tex = &raindropsplashparticletexture[(int) p->time2]; break; - case pt_flamefall: + case pt_flame: p->alpha -= frametime * 512; - p->vel[2] -= gravity * 0.5f; - if (p->alpha < 1) - p->die = -1; - break; - */ - /* - case pt_decal: - if (cl.time > p->time2) - { - p->alpha -= frametime * 256; - if (p->alpha < 1) - p->die = -1; - } - if (p->alpha < 64) + p->vel[2] += gravity; + if (p->alpha < 16) p->die = -1; break; - */ case pt_oneframe: if (p->time2) p->die = -1; @@ -1327,6 +1354,8 @@ void R_MoveParticles (void) { maxparticle = i; activeparticles++; + if (p->pressure) + pressureused = true; } } // fill in gaps to compact the array @@ -1338,17 +1367,46 @@ void R_MoveParticles (void) maxparticle--; } numparticles = activeparticles; + + if (pressureused) + { + activeparticles = 0; + for (i = 0, p = particles;i < numparticles;i++, p++) + if (p->pressure) + freeparticles[activeparticles++] = p; + + if (activeparticles) + { + for (i = 0, p = particles;i < numparticles;i++, p++) + { + for (j = 0;j < activeparticles;j++) + { + if (freeparticles[j] != p) + { + float dist, diff[3]; + VectorSubtract(p->org, freeparticles[j]->org, diff); + dist = DotProduct(diff, diff); + if (dist < 4096 && dist >= 1) + { + dist = freeparticles[j]->scale * 4.0f * frametime / sqrt(dist); + VectorMA(p->vel, dist, diff, p->vel); + //dist = freeparticles[j]->scale * 4.0f * frametime / dist; + //VectorMA(p->vel, dist, freeparticles[j]->vel, p->vel); + } + } + } + } + } + } } void R_DrawParticles (void) { particle_t *p; - int i, dynamiclight, staticlight, r, g, b; - byte br, bg, bb, ba; - float scale, scale2, minparticledist; - byte *color24; - vec3_t uprightangles, up2, right2, tempcolor, corner; -// mleaf_t *leaf; + int i, dynamiclight, staticlight, r, g, b, texnum; + float minparticledist; + vec3_t uprightangles, up2, right2, v, right, up; + mleaf_t *leaf; // LordHavoc: early out condition if ((!numparticles) || (!r_drawparticles.value)) @@ -1366,78 +1424,55 @@ void R_DrawParticles (void) minparticledist = DotProduct(r_origin, vpn) + 16.0f; + texnum = R_GetTexture(particlefonttexture); for (i = 0, p = particles;i < numparticles;i++, p++) { - // LordHavoc: unnecessary (array was already compacted) -// if (p->die < cl.time) -// continue; + if (p->tex == NULL || p->alpha < 1 || p->scale < 0.1f) + continue; // LordHavoc: only render if not too close if (DotProduct(p->org, vpn) < minparticledist) continue; // LordHavoc: check if it's in a visible leaf -// leaf = Mod_PointInLeaf(p->org, cl.worldmodel); -// if (leaf->visframe != r_framecount) -// continue; - - /* - if (p->type == pt_decal) - { - VectorSubtract(p->org, r_origin, v); - if (DotProduct(p->direction, v) < 0) - continue; - } - */ + leaf = leaf = Mod_PointInLeaf(p->org, cl.worldmodel); + if (leaf->visframe != r_framecount) + continue; - color24 = (byte *) &d_8to24table[(int)p->color]; - r = color24[0]; - g = color24[1]; - b = color24[2]; + r = p->color[0]; + g = p->color[1]; + b = p->color[2]; if (staticlight && (p->dynlight || staticlight >= 2)) // LordHavoc: only light blood and smoke { - R_CompleteLightPoint(tempcolor, p->org, dynamiclight); - r = (r * (int) tempcolor[0]) >> 7; - g = (g * (int) tempcolor[1]) >> 7; - b = (b * (int) tempcolor[2]) >> 7; + R_CompleteLightPoint(v, p->org, dynamiclight, leaf); +#if SLOWMATH + r = (r * (int) v[0]) >> 7; + g = (g * (int) v[1]) >> 7; + b = (b * (int) v[2]) >> 7; +#else + v[0] += 8388608.0f; + v[1] += 8388608.0f; + v[2] += 8388608.0f; + r = (r * (*((long *) &v[0]) & 0x7FFFFF)) >> 7; + g = (g * (*((long *) &v[1]) & 0x7FFFFF)) >> 7; + b = (b * (*((long *) &v[2]) & 0x7FFFFF)) >> 7; +#endif } - br = (byte) min(r, 255); - bg = (byte) min(g, 255); - bb = (byte) min(b, 255); - ba = (byte) p->alpha; - transpolybegin(R_GetTexture(p->tex), 0, R_GetTexture(p->tex), p->rendermode); - scale = p->scale * -0.5;scale2 = p->scale; - /* - if (p->type == pt_decal) + if (p->type == pt_raindropsplash) { - corner[0] = p->org[0] + p->decalup[0]*scale + p->decalright[0]*scale; - corner[1] = p->org[1] + p->decalup[1]*scale + p->decalright[1]*scale; - corner[2] = p->org[2] + p->decalup[2]*scale + p->decalright[2]*scale; - transpolyvertub(corner[0] , corner[1] , corner[2] , 0,1,br,bg,bb,ba); - transpolyvertub(corner[0] + p->decalup[0]*scale2 , corner[1] + p->decalup[1]*scale2 , corner[2] + p->decalup[2]*scale2 , 0,0,br,bg,bb,ba); - transpolyvertub(corner[0] + p->decalup[0]*scale2 + p->decalright[0]*scale2, corner[1] + p->decalup[1]*scale2 + p->decalright[1]*scale2, corner[2] + p->decalup[2]*scale2 + p->decalright[2]*scale2, 1,0,br,bg,bb,ba); - transpolyvertub(corner[0] + p->decalright[0]*scale2, corner[1] + p->decalright[1]*scale2, corner[2] + p->decalright[2]*scale2, 1,1,br,bg,bb,ba); - } - else*/ if (p->tex == rainparticletexture) // rain streak - { - corner[0] = p->org[0] + up2[0]*scale + right2[0]*scale; - corner[1] = p->org[1] + up2[1]*scale + right2[1]*scale; - corner[2] = p->org[2] + up2[2]*scale + right2[2]*scale; - transpolyvertub(corner[0] , corner[1] , corner[2] , 0,1,br,bg,bb,ba); - transpolyvertub(corner[0] + up2[0]*scale2 , corner[1] + up2[1]*scale2 , corner[2] + up2[2]*scale2 , 0,0,br,bg,bb,ba); - transpolyvertub(corner[0] + up2[0]*scale2 + right2[0]*scale2, corner[1] + up2[1]*scale2 + right2[1]*scale2, corner[2] + up2[2]*scale2 + right2[2]*scale2, 1,0,br,bg,bb,ba); - transpolyvertub(corner[0] + right2[0]*scale2, corner[1] + right2[1]*scale2, corner[2] + right2[2]*scale2, 1,1,br,bg,bb,ba); + // treat as double-sided + if (DotProduct(p->vel2, r_origin) > DotProduct(p->vel2, p->org)) + { + VectorNegate(p->vel2, v); + VectorVectors(v, right, up); + } + else + VectorVectors(p->vel2, right, up); + transpolyparticle(p->org, right, up, p->scale, texnum, p->rendermode, r, g, b, p->alpha, p->tex->s1, p->tex->t1, p->tex->s2, p->tex->t2); } + else if (p->tex == &rainparticletexture) // rain streak + transpolyparticle(p->org, right2, up2, p->scale, texnum, p->rendermode, r, g, b, p->alpha, p->tex->s1, p->tex->t1, p->tex->s2, p->tex->t2); else - { - corner[0] = p->org[0] + vup[0]*scale + vright[0]*scale; - corner[1] = p->org[1] + vup[1]*scale + vright[1]*scale; - corner[2] = p->org[2] + vup[2]*scale + vright[2]*scale; - transpolyvertub(corner[0] , corner[1] , corner[2] , 0,1,br,bg,bb,ba); - transpolyvertub(corner[0] + vup[0]*scale2 , corner[1] + vup[1]*scale2 , corner[2] + vup[2]*scale2 , 0,0,br,bg,bb,ba); - transpolyvertub(corner[0] + vup[0]*scale2 + vright[0]*scale2, corner[1] + vup[1]*scale2 + vright[1]*scale2, corner[2] + vup[2]*scale2 + vright[2]*scale2, 1,0,br,bg,bb,ba); - transpolyvertub(corner[0] + vright[0]*scale2, corner[1] + vright[1]*scale2, corner[2] + vright[2]*scale2, 1,1,br,bg,bb,ba); - } - transpolyend(); + transpolyparticle(p->org, vright, vup, p->scale, texnum, p->rendermode, r, g, b, p->alpha, p->tex->s1, p->tex->t1, p->tex->s2, p->tex->t2); } } diff --git a/r_sprites.c b/r_sprites.c index e7f56117..f9b43ead 100644 --- a/r_sprites.c +++ b/r_sprites.c @@ -1,19 +1,19 @@ #include "quakedef.h" -void R_ClipSpriteImage (entity_t *e, msprite_t *psprite, frameblend_t *blend, vec3_t origin, vec3_t up, vec3_t right) +void R_ClipSpriteImage (msprite_t *psprite, vec3_t origin, vec3_t right, vec3_t up) { int i; mspriteframe_t *frame; vec3_t points[4]; float fleft, fright, fdown, fup; - frame = ((mspriteframe_t *)(psprite->ofs_frames + (int) psprite)) + blend[0].frame; + frame = ((mspriteframe_t *)(psprite->ofs_frames + (int) psprite)) + currentrenderentity->frameblend[0].frame; fleft = frame->left; fdown = frame->down; fright = frame->right; fup = frame->up; - for (i = 1;i < 4 && blend[i].lerp;i++) + for (i = 1;i < 4 && currentrenderentity->frameblend[i].lerp;i++) { - frame = ((mspriteframe_t *)(psprite->ofs_frames + (int) psprite)) + blend[i].frame; + frame = ((mspriteframe_t *)(psprite->ofs_frames + (int) psprite)) + currentrenderentity->frameblend[i].frame; fleft = min(fleft , frame->left ); fdown = min(fdown , frame->down ); fright = max(fright, frame->right); @@ -23,56 +23,97 @@ void R_ClipSpriteImage (entity_t *e, msprite_t *psprite, frameblend_t *blend, ve points[1][0] = origin[0] + fup * up[0] + fleft * right[0];points[1][1] = origin[1] + fup * up[1] + fleft * right[1];points[1][2] = origin[2] + fup * up[2] + fleft * right[2]; points[2][0] = origin[0] + fup * up[0] + fright * right[0];points[2][1] = origin[1] + fup * up[1] + fright * right[1];points[2][2] = origin[2] + fup * up[2] + fright * right[2]; points[3][0] = origin[0] + fdown * up[0] + fright * right[0];points[3][1] = origin[1] + fdown * up[1] + fright * right[1];points[3][2] = origin[2] + fdown * up[2] + fright * right[2]; - R_Clip_AddPolygon(&points[0][0], 4, sizeof(float[3]), false, R_Entity_Callback, e, NULL, NULL); + R_Clip_AddPolygon(&points[0][0], 4, sizeof(float[3]), false, R_Entity_Callback, currentrenderentity, NULL, NULL); } -void R_ClipSprite (entity_t *e, frameblend_t *blend) +int R_SpriteSetup (int type, float org[3], float right[3], float up[3]) { - vec3_t forward, right, up, org; - msprite_t *psprite; - - if (!blend[0].lerp) - return; - - psprite = Mod_Extradata(e->render.model); + float matrix1[3][3], matrix2[3][3], matrix3[3][3]; - if (psprite->type == SPR_ORIENTED) + VectorCopy(currentrenderentity->origin, org); + switch(type) { + case SPR_VP_PARALLEL_UPRIGHT: + // flames and such + // vertical beam sprite, faces view plane + VectorNegate(vpn, matrix3[0]); + matrix3[0][2] = 0; + VectorNormalizeFast(matrix3[0]); + VectorVectors(matrix3[0], matrix3[1], matrix3[2]); + break; + case SPR_FACING_UPRIGHT: + // flames and such + // vertical beam sprite, faces viewer's origin (not the view plane) + VectorSubtract(r_origin, currentrenderentity->origin, matrix3[0]); + matrix3[0][2] = 0; + VectorNormalizeFast(matrix3[0]); + VectorVectors(matrix3[0], matrix3[1], matrix3[2]); + break; + default: + Con_Printf("R_SpriteSetup: unknown sprite type %i\n", type); + // fall through to normal sprite + case SPR_VP_PARALLEL: + // normal sprite + // faces view plane + VectorCopy(vpn, matrix3[0]); + VectorCopy(vright, matrix3[1]); + VectorCopy(vup, matrix3[2]); + break; + case SPR_ORIENTED: // bullet marks on walls - AngleVectors (e->render.angles, forward, right, up); + // ignores viewer entirely + AngleVectors (currentrenderentity->angles, matrix3[0], matrix3[1], matrix3[2]); // nudge it toward the view, so it will be infront of the wall - VectorSubtract(e->render.origin, vpn, org); - // don't draw if it's a backface - if (DotProduct(r_origin, forward) > (DotProduct(org, forward) - 1.0f)) - return; - } - else - { - // normal sprite - VectorCopy(vup, up); - VectorCopy(vright, right); - VectorCopy(e->render.origin, org); - // don't draw if it's a backface - if (DotProduct(org, vpn) < (DotProduct(r_origin, vpn) + 1.0f)) - return; + VectorSubtract(org, vpn, org); + break; + case SPR_VP_PARALLEL_ORIENTED: + // I have no idea what people would use this for + // oriented relative to view space + // FIXME: test this and make sure it mimicks software + AngleVectors (currentrenderentity->angles, matrix1[0], matrix1[1], matrix1[2]); + VectorCopy(vpn, matrix2[0]); + VectorCopy(vright, matrix2[1]); + VectorCopy(vup, matrix2[2]); + R_ConcatRotations (matrix1, matrix2, matrix3); + break; } + // don't draw if view origin is behind it + if (DotProduct(org, matrix3[0]) < (DotProduct(r_origin, matrix3[0]) - 1.0f)) + return true; - if (e->render.scale != 1) + if (currentrenderentity->scale != 1) { - VectorScale(up, e->render.scale, up); - VectorScale(right, e->render.scale, right); + VectorScale(matrix3[1], currentrenderentity->scale, matrix3[1]); + VectorScale(matrix3[2], currentrenderentity->scale, matrix3[2]); } + VectorCopy(matrix3[1], right); + VectorCopy(matrix3[2], up); + return false; +} + +void R_ClipSprite (void) +{ + vec3_t org, right, up; + msprite_t *psprite; + + if (currentrenderentity->frameblend[0].frame < 0) + return; + + psprite = Mod_Extradata(currentrenderentity->model); + if (R_SpriteSetup(psprite->type, org, right, up)) + return; + // LordHavoc: interpolated sprite rendering - R_ClipSpriteImage(e, psprite, blend, org, up, right); + R_ClipSpriteImage(psprite, org, right, up); } void GL_DrawSpriteImage (mspriteframe_t *frame, vec3_t origin, vec3_t up, vec3_t right, byte red, byte green, byte blue, int alpha) { byte alphaub; alphaub = bound(0, alpha, 255); - transpolybegin(R_GetTexture(frame->texture), 0, R_GetTexture(frame->fogtexture), ((currententity->render.effects & EF_ADDITIVE) || (currententity->render.model->flags & EF_ADDITIVE)) ? TPOLYTYPE_ADD : TPOLYTYPE_ALPHA); + transpolybegin(R_GetTexture(frame->texture), 0, R_GetTexture(frame->fogtexture), ((currentrenderentity->effects & EF_ADDITIVE) || (currentrenderentity->model->flags & EF_ADDITIVE)) ? TPOLYTYPE_ADD : TPOLYTYPE_ALPHA); transpolyvertub(origin[0] + frame->down * up[0] + frame->left * right[0], origin[1] + frame->down * up[1] + frame->left * right[1], origin[2] + frame->down * up[2] + frame->left * right[2], 0, 1, red, green, blue, alphaub); transpolyvertub(origin[0] + frame->up * up[0] + frame->left * right[0], origin[1] + frame->up * up[1] + frame->left * right[1], origin[2] + frame->up * up[2] + frame->left * right[2], 0, 0, red, green, blue, alphaub); transpolyvertub(origin[0] + frame->up * up[0] + frame->right * right[0], origin[1] + frame->up * up[1] + frame->right * right[1], origin[2] + frame->up * up[2] + frame->right * right[2], 1, 0, red, green, blue, alphaub); @@ -85,67 +126,38 @@ void GL_DrawSpriteImage (mspriteframe_t *frame, vec3_t origin, vec3_t up, vec3_t R_DrawSpriteModel ================= */ -void R_DrawSpriteModel (entity_t *e, frameblend_t *blend) +void R_DrawSpriteModel () { - vec3_t forward, right, up, org, color, mins, maxs; + int i; + vec3_t right, up, org, color; byte colorub[4]; msprite_t *psprite; - if (!blend[0].lerp) + if (currentrenderentity->frameblend[0].frame < 0) return; - VectorAdd (e->render.origin, e->render.model->mins, mins); - VectorAdd (e->render.origin, e->render.model->maxs, maxs); - -// if (R_CullBox (mins, maxs)) -// return; + psprite = Mod_Extradata(currentrenderentity->model); + if (R_SpriteSetup(psprite->type, org, right, up)) + return; c_sprites++; - psprite = Mod_Extradata(e->render.model); - //psprite = e->model->cache.data; - - if (psprite->type == SPR_ORIENTED) - { - // bullet marks on walls - AngleVectors (e->render.angles, forward, right, up); - VectorSubtract(e->render.origin, vpn, org); - } - else - { - // normal sprite - VectorCopy(vup, up); - VectorCopy(vright, right); - VectorCopy(e->render.origin, org); - } - - if (e->render.scale != 1) - { - VectorScale(up, e->render.scale, up); - VectorScale(right, e->render.scale, right); - } - - if (e->render.model->flags & EF_FULLBRIGHT || e->render.effects & EF_FULLBRIGHT) + if ((currentrenderentity->model->flags & EF_FULLBRIGHT) || (currentrenderentity->effects & EF_FULLBRIGHT)) { - color[0] = e->render.colormod[0] * 255; - color[1] = e->render.colormod[1] * 255; - color[2] = e->render.colormod[2] * 255; + color[0] = currentrenderentity->colormod[0] * 255; + color[1] = currentrenderentity->colormod[1] * 255; + color[2] = currentrenderentity->colormod[2] * 255; } else - R_CompleteLightPoint(color, e->render.origin, true); + R_CompleteLightPoint(color, currentrenderentity->origin, true, NULL); colorub[0] = bound(0, color[0], 255); colorub[1] = bound(0, color[1], 255); colorub[2] = bound(0, color[2], 255); // LordHavoc: interpolated sprite rendering - if (blend[0].lerp) - GL_DrawSpriteImage(((mspriteframe_t *)(psprite->ofs_frames + (int) psprite)) + blend[0].frame, org, up, right, colorub[0],colorub[1],colorub[2], e->render.alpha*255*blend[0].lerp); - if (blend[1].lerp) - GL_DrawSpriteImage(((mspriteframe_t *)(psprite->ofs_frames + (int) psprite)) + blend[1].frame, org, up, right, colorub[0],colorub[1],colorub[2], e->render.alpha*255*blend[1].lerp); - if (blend[2].lerp) - GL_DrawSpriteImage(((mspriteframe_t *)(psprite->ofs_frames + (int) psprite)) + blend[2].frame, org, up, right, colorub[0],colorub[1],colorub[2], e->render.alpha*255*blend[2].lerp); - if (blend[3].lerp) - GL_DrawSpriteImage(((mspriteframe_t *)(psprite->ofs_frames + (int) psprite)) + blend[3].frame, org, up, right, colorub[0],colorub[1],colorub[2], e->render.alpha*255*blend[3].lerp); + for (i = 0;i < 4;i++) + if (currentrenderentity->frameblend[i].lerp) + GL_DrawSpriteImage(((mspriteframe_t *)(psprite->ofs_frames + (int) psprite)) + currentrenderentity->frameblend[i].frame, org, up, right, colorub[0],colorub[1],colorub[2], currentrenderentity->alpha*255*currentrenderentity->frameblend[i].lerp); } diff --git a/render.h b/render.h index 9d1fb636..7950e9f6 100644 --- a/render.h +++ b/render.h @@ -48,7 +48,6 @@ extern float lightscale; extern float *aliasvert; extern float *aliasvertnorm; extern byte *aliasvertcolor; -extern float modelalpha; // vis stuff extern cvar_t r_novis; @@ -64,67 +63,121 @@ extern float ixtable[4096]; //============================================================================= -typedef struct entity_render_s +typedef struct frameblend_s { - vec3_t origin; - vec3_t angles; + int frame; + float lerp; +} +frameblend_t; - int visframe; // last frame this entity was found in an active leaf +// LordHavoc: nothing in this structure is persistant, it may be overwritten by the client every frame, for persistant data use entity_lerp_t. +typedef struct entity_render_s +{ + vec3_t origin; // location + vec3_t angles; // orientation + float colormod[3]; // color tint for model + float alpha; // opacity (alpha) of the model + float scale; // size the model is shown model_t *model; // NULL = no model - int frame; // current desired frame (usually identical to frame2, but frame2 is not always used) + int frame; // current uninterpolated animation frame (for things which do not use interpolation) int colormap; // entity shirt and pants colors int effects; // light, particles, etc int skinnum; // for Alias models int flags; // render flags - float alpha; // opacity (alpha) of the model - float scale; // size the model is shown - float trail_time; // last time for trail rendering - float colormod[3]; // color tint for model - - model_t *lerp_model; // lerp resets when model changes + // these are copied from the persistent data int frame1; // frame that the model is interpolating from int frame2; // frame that the model is interpolating to - double lerp_starttime; // start of this transition - double framelerp; // interpolation factor, usually computed from lerp_starttime - double frame1start; // time frame1 began playing (for framegroup animations) - double frame2start; // time frame2 began playing (for framegroup animations) + double framelerp; // interpolation factor, usually computed from frame2time + double frame1time; // time frame1 began playing (for framegroup animations) + double frame2time; // time frame2 began playing (for framegroup animations) + + // calculated by the renderer (but not persistent) + int visframe; // if visframe == r_framecount, it is visible + vec3_t mins, maxs; // calculated during R_AddModelEntities + frameblend_t frameblend[4]; // 4 frame numbers (-1 if not used) and their blending scalers (0-1), if interpolation is not desired, use frame instead } entity_render_t; +typedef struct entity_persistent_s +{ + // particles + vec3_t trail_origin; // trail rendering + float trail_time; // trail rendering + + // interpolated animation + int modelindex; // lerp resets when model changes + int frame1; // frame that the model is interpolating from + int frame2; // frame that the model is interpolating to + double framelerp; // interpolation factor, usually computed from frame2time + double frame1time; // time frame1 began playing (for framegroup animations) + double frame2time; // time frame2 began playing (for framegroup animations) +} +entity_persistent_t; + typedef struct entity_s { - entity_state_t state_baseline; // baseline for entity + entity_state_t state_baseline; // baseline state (default values) entity_state_t state_previous; // previous state (interpolating from this) entity_state_t state_current; // current state (interpolating to this) - entity_render_t render; -} entity_t; + entity_persistent_t persistent; // used for regenerating parts of render + + entity_render_t render; // the only data the renderer should know about +} +entity_t; typedef struct { - vrect_t vrect; // subwindow in video for refresh + // area to render in + int x, y, width, height; + float fov_x, fov_y; - vec3_t vieworg; - vec3_t viewangles; + // view point + vec3_t vieworg; + vec3_t viewangles; +} +refdef_t; - float fov_x, fov_y; -} refdef_t; +extern qboolean hlbsp; +//extern qboolean r_cache_thrash; // compatability +extern vec3_t modelorg; +extern entity_render_t *currentrenderentity; +extern int r_framecount; +extern mplane_t frustum[4]; +extern int c_brush_polys, c_alias_polys, c_light_polys, c_faces, c_nodes, c_leafs, c_models, c_bmodels, c_sprites, c_particles, c_dlights; // -// refresh +// view origin // +extern vec3_t vup; +extern vec3_t vpn; +extern vec3_t vright; +extern vec3_t r_origin; - +// +// screen size info +// extern refdef_t r_refdef; -extern vec3_t r_origin, vpn, vright, vup; -extern qboolean hlbsp; +extern mleaf_t *r_viewleaf, *r_oldviewleaf; +extern unsigned short d_lightstylevalue[256]; // 8.8 fraction of base light value + +extern qboolean envmap; + +extern cvar_t r_drawentities; +extern cvar_t r_drawviewmodel; +extern cvar_t r_speeds; +extern cvar_t r_fullbright; +extern cvar_t r_wateralpha; +extern cvar_t r_dynamic; +extern cvar_t r_waterripple; + +//extern float r_world_matrix[16]; void R_Init (void); void R_RenderView (void); // must set r_refdef first -void R_ViewChanged (vrect_t *pvrect, int lineadj, float aspect); // called whenever r_refdef or vid change // LordHavoc: changed this for sake of GLQuake void R_InitSky (byte *src, int bytesperpixel); // called at level load @@ -194,14 +247,19 @@ extern qboolean lighthalf; void GL_LockArray(int first, int count); void GL_UnlockArray(void); -void R_DrawBrushModel (entity_t *e); -void R_DrawAliasModel (entity_t *ent, int cull, float alpha, model_t *clmodel, frameblend_t *blend, int skin, vec3_t org, vec3_t angles, vec_t scale, int effects, int flags, int colormap); -void R_DrawSpriteModel (entity_t *e, frameblend_t *blend); +void R_DrawBrushModel (void); +void R_DrawAliasModel (void); +void R_DrawSpriteModel (void); -void R_ClipSprite (entity_t *e, frameblend_t *blend); +void R_ClipSprite (void); void R_Entity_Callback(void *data, void *junk); extern cvar_t r_render; extern cvar_t r_upload; extern cvar_t r_ser; #include "image.h" + +// if contents is not zero, it will impact on content changes +// (leafs matching contents are considered empty, others are solid) +extern int traceline_endcontents; // set by TraceLine +float TraceLine (vec3_t start, vec3_t end, vec3_t impact, vec3_t normal, int contents); diff --git a/sbar.c b/sbar.c index 73e51ca7..018cbf9e 100644 --- a/sbar.c +++ b/sbar.c @@ -182,34 +182,34 @@ void Sbar_Init (void) sb_scorebar = Draw_PicFromWad ("scorebar"); //MED 01/04/97 added new hipnotic weapons - if (hipnotic) + if (gamemode == GAME_HIPNOTIC) { - hsb_weapons[0][0] = Draw_PicFromWad ("inv_laser"); - hsb_weapons[0][1] = Draw_PicFromWad ("inv_mjolnir"); - hsb_weapons[0][2] = Draw_PicFromWad ("inv_gren_prox"); - hsb_weapons[0][3] = Draw_PicFromWad ("inv_prox_gren"); - hsb_weapons[0][4] = Draw_PicFromWad ("inv_prox"); - - hsb_weapons[1][0] = Draw_PicFromWad ("inv2_laser"); - hsb_weapons[1][1] = Draw_PicFromWad ("inv2_mjolnir"); - hsb_weapons[1][2] = Draw_PicFromWad ("inv2_gren_prox"); - hsb_weapons[1][3] = Draw_PicFromWad ("inv2_prox_gren"); - hsb_weapons[1][4] = Draw_PicFromWad ("inv2_prox"); - - for (i=0 ; i<5 ; i++) - { - hsb_weapons[2+i][0] = Draw_PicFromWad (va("inva%i_laser",i+1)); - hsb_weapons[2+i][1] = Draw_PicFromWad (va("inva%i_mjolnir",i+1)); - hsb_weapons[2+i][2] = Draw_PicFromWad (va("inva%i_gren_prox",i+1)); - hsb_weapons[2+i][3] = Draw_PicFromWad (va("inva%i_prox_gren",i+1)); - hsb_weapons[2+i][4] = Draw_PicFromWad (va("inva%i_prox",i+1)); - } - - hsb_items[0] = Draw_PicFromWad ("sb_wsuit"); - hsb_items[1] = Draw_PicFromWad ("sb_eshld"); + hsb_weapons[0][0] = Draw_PicFromWad ("inv_laser"); + hsb_weapons[0][1] = Draw_PicFromWad ("inv_mjolnir"); + hsb_weapons[0][2] = Draw_PicFromWad ("inv_gren_prox"); + hsb_weapons[0][3] = Draw_PicFromWad ("inv_prox_gren"); + hsb_weapons[0][4] = Draw_PicFromWad ("inv_prox"); + + hsb_weapons[1][0] = Draw_PicFromWad ("inv2_laser"); + hsb_weapons[1][1] = Draw_PicFromWad ("inv2_mjolnir"); + hsb_weapons[1][2] = Draw_PicFromWad ("inv2_gren_prox"); + hsb_weapons[1][3] = Draw_PicFromWad ("inv2_prox_gren"); + hsb_weapons[1][4] = Draw_PicFromWad ("inv2_prox"); + + for (i=0 ; i<5 ; i++) + { + hsb_weapons[2+i][0] = Draw_PicFromWad (va("inva%i_laser",i+1)); + hsb_weapons[2+i][1] = Draw_PicFromWad (va("inva%i_mjolnir",i+1)); + hsb_weapons[2+i][2] = Draw_PicFromWad (va("inva%i_gren_prox",i+1)); + hsb_weapons[2+i][3] = Draw_PicFromWad (va("inva%i_prox_gren",i+1)); + hsb_weapons[2+i][4] = Draw_PicFromWad (va("inva%i_prox",i+1)); + } + + hsb_items[0] = Draw_PicFromWad ("sb_wsuit"); + hsb_items[1] = Draw_PicFromWad ("sb_eshld"); } - if (rogue) + else if (gamemode == GAME_ROGUE) { rsb_invbar[0] = Draw_PicFromWad ("r_invbar1"); rsb_invbar[1] = Draw_PicFromWad ("r_invbar2"); @@ -221,10 +221,10 @@ void Sbar_Init (void) rsb_weapons[4] = Draw_PicFromWad ("r_plasma"); rsb_items[0] = Draw_PicFromWad ("r_shield1"); - rsb_items[1] = Draw_PicFromWad ("r_agrav1"); + rsb_items[1] = Draw_PicFromWad ("r_agrav1"); // PGM 01/19/97 - team color border - rsb_teambord = Draw_PicFromWad ("r_teambord"); + rsb_teambord = Draw_PicFromWad ("r_teambord"); // PGM 01/19/97 - team color border rsb_ammo[0] = Draw_PicFromWad ("r_ammolava"); @@ -246,18 +246,18 @@ Sbar_DrawPic void Sbar_DrawPic (int x, int y, qpic_t *pic) { if (cl.gametype == GAME_DEATHMATCH) - Draw_Pic (x /* + ((vid.width - 320)>>1)*/, y + (vid.height-SBAR_HEIGHT), pic); + Draw_Pic (x, y + (vid.conheight-SBAR_HEIGHT), pic); else - Draw_Pic (x + ((vid.width - 320)>>1), y + (vid.height-SBAR_HEIGHT), pic); + Draw_Pic (x + ((vid.conwidth - 320)>>1), y + (vid.conheight-SBAR_HEIGHT), pic); } void Draw_AlphaPic (int x, int y, qpic_t *pic, float alpha); void Sbar_DrawAlphaPic (int x, int y, qpic_t *pic, float alpha) { if (cl.gametype == GAME_DEATHMATCH) - Draw_AlphaPic (x /* + ((vid.width - 320)>>1)*/, y + (vid.height-SBAR_HEIGHT), pic, alpha); + Draw_AlphaPic (x, y + (vid.conheight-SBAR_HEIGHT), pic, alpha); else - Draw_AlphaPic (x + ((vid.width - 320)>>1), y + (vid.height-SBAR_HEIGHT), pic, alpha); + Draw_AlphaPic (x + ((vid.conwidth - 320)>>1), y + (vid.conheight-SBAR_HEIGHT), pic, alpha); } /* @@ -270,9 +270,9 @@ Draws one solid graphics character void Sbar_DrawCharacter (int x, int y, int num) { if (cl.gametype == GAME_DEATHMATCH) - Draw_Character ( x /*+ ((vid.width - 320)>>1) */ + 4 , y + vid.height-SBAR_HEIGHT, num); + Draw_Character ( x + 4 , y + vid.conheight-SBAR_HEIGHT, num); else - Draw_Character ( x + ((vid.width - 320)>>1) + 4 , y + vid.height-SBAR_HEIGHT, num); + Draw_Character ( x + ((vid.conwidth - 320)>>1) + 4 , y + vid.conheight-SBAR_HEIGHT, num); } /* @@ -283,9 +283,9 @@ Sbar_DrawString void Sbar_DrawString (int x, int y, char *str) { if (cl.gametype == GAME_DEATHMATCH) - Draw_String (x /*+ ((vid.width - 320)>>1)*/, y+ vid.height-SBAR_HEIGHT, str, 0); + Draw_String (x, y+ vid.conheight-SBAR_HEIGHT, str, 0); else - Draw_String (x + ((vid.width - 320)>>1), y+ vid.height-SBAR_HEIGHT, str, 0); + Draw_String (x + ((vid.conwidth - 320)>>1), y+ vid.conheight-SBAR_HEIGHT, str, 0); } /* @@ -482,7 +482,7 @@ void Sbar_DrawInventory (void) float time; int flashon; - if (rogue) + if (gamemode == GAME_ROGUE) { if ( cl.stats[STAT_ACTIVEWEAPON] >= RIT_LAVA_NAILGUN ) Sbar_DrawAlphaPic (0, -24, rsb_invbar[0], 0.4); @@ -515,7 +515,7 @@ void Sbar_DrawInventory (void) // MED 01/04/97 // hipnotic weapons - if (hipnotic) + if (gamemode == GAME_HIPNOTIC) { int grenadeflashing=0; for (i=0 ; i<4 ; i++) @@ -562,7 +562,7 @@ void Sbar_DrawInventory (void) } } - if (rogue) + if (gamemode == GAME_ROGUE) { // check for powered up weapon. if ( cl.stats[STAT_ACTIVEWEAPON] >= RIT_LAVA_NAILGUN ) @@ -583,56 +583,37 @@ void Sbar_DrawInventory (void) Sbar_DrawCharacter ( (6*i+3)*8 - 2, -24, 18 + num[2] - '0'); } - flashon = 0; // items for (i=0 ; i<6 ; i++) if (cl.items & (1<<(17+i))) { - time = cl.item_gettime[17+i]; - if (time && time > cl.time - 2 && flashon ) - { // flash frame - } - else //MED 01/04/97 changed keys - if (!hipnotic || (i>1)) - Sbar_DrawPic (192 + i*16, -16, sb_items[i]); + if (gamemode != GAME_HIPNOTIC || (i>1)) + Sbar_DrawPic (192 + i*16, -16, sb_items[i]); } + //MED 01/04/97 added hipnotic items // hipnotic items - if (hipnotic) + if (gamemode == GAME_HIPNOTIC) { for (i=0 ; i<2 ; i++) if (cl.items & (1<<(24+i))) - { - time = cl.item_gettime[24+i]; - if (!time || time <= cl.time - 2 || !flashon) - Sbar_DrawPic (288 + i*16, -16, hsb_items[i]); - } + Sbar_DrawPic (288 + i*16, -16, hsb_items[i]); } - if (rogue) + if (gamemode == GAME_ROGUE) { // new rogue items for (i=0 ; i<2 ; i++) if (cl.items & (1<<(29+i))) - { - time = cl.item_gettime[29+i]; - if (!time || time <= cl.time - 2 || !flashon) - Sbar_DrawPic (288 + i*16, -16, rsb_items[i]); - } + Sbar_DrawPic (288 + i*16, -16, rsb_items[i]); } else { // sigils for (i=0 ; i<4 ; i++) - { if (cl.items & (1<<(28+i))) - { - time = cl.item_gettime[28+i]; - if (!time || time <= cl.time - 2 || !flashon) - Sbar_DrawPic (320-32 + i*8, -16, sb_sigil[i]); - } - } + Sbar_DrawPic (320-32 + i*8, -16, sb_sigil[i]); } } @@ -661,8 +642,8 @@ void Sbar_DrawFrags (void) if (cl.gametype == GAME_DEATHMATCH) xofs = 0; else - xofs = (vid.width - 320)>>1; - y = vid.height - SBAR_HEIGHT - 23; + xofs = (vid.conwidth - 320)>>1; + y = vid.conheight - SBAR_HEIGHT - 23; for (i=0 ; i3) && - (teamplay.value<7)) + if (gamemode == GAME_ROGUE && (cl.maxclients != 1) && (teamplay.value > 3) && (teamplay.value < 7)) { int top, bottom; int xofs; char num[12]; scoreboard_t *s; - + s = &cl.scores[cl.viewentity - 1]; // draw background top = (s->colors & 0xf0) + 8; @@ -727,11 +705,11 @@ void Sbar_DrawFace (void) if (cl.gametype == GAME_DEATHMATCH) xofs = 113; else - xofs = ((vid.width - 320)>>1) + 113; + xofs = ((vid.conwidth - 320)>>1) + 113; Sbar_DrawPic (112, 0, rsb_teambord); - Draw_Fill (xofs, vid.height-SBAR_HEIGHT+3, 22, 9, top); - Draw_Fill (xofs, vid.height-SBAR_HEIGHT+12, 22, 9, bottom); + Draw_Fill (xofs, vid.conheight-SBAR_HEIGHT+3, 22, 9, top); + Draw_Fill (xofs, vid.conheight-SBAR_HEIGHT+12, 22, 9, bottom); // draw number f = s->frags; @@ -752,49 +730,25 @@ void Sbar_DrawFace (void) Sbar_DrawCharacter ( 116, 3, num[1]); Sbar_DrawCharacter ( 123, 3, num[2]); } - + return; } // PGM 01/19/97 - team color drawing - if ( (cl.items & (IT_INVISIBILITY | IT_INVULNERABILITY) ) - == (IT_INVISIBILITY | IT_INVULNERABILITY) ) - { + if ( (cl.items & (IT_INVISIBILITY | IT_INVULNERABILITY) ) == (IT_INVISIBILITY | IT_INVULNERABILITY) ) Sbar_DrawPic (112, 0, sb_face_invis_invuln); - return; - } - if (cl.items & IT_QUAD) - { + else if (cl.items & IT_QUAD) Sbar_DrawPic (112, 0, sb_face_quad ); - return; - } - if (cl.items & IT_INVISIBILITY) - { + else if (cl.items & IT_INVISIBILITY) Sbar_DrawPic (112, 0, sb_face_invis ); - return; - } - if (cl.items & IT_INVULNERABILITY) - { + else if (cl.items & IT_INVULNERABILITY) Sbar_DrawPic (112, 0, sb_face_invuln); - return; - } - - if (cl.stats[STAT_HEALTH] >= 100) - f = 4; else - f = cl.stats[STAT_HEALTH] / 20; - // LordHavoc: I don't even know how the game didn't crash without this - if (f < 0) - f = 0; - - if (cl.time <= cl.faceanimtime) { - anim = 1; -// sb_updates = 0; // make sure the anim gets drawn over + f = cl.stats[STAT_HEALTH] / 20; + f = bound(0, f, 4); + Sbar_DrawPic (112, 0, sb_faces[f][cl.time <= cl.faceanimtime]); } - else - anim = 0; - Sbar_DrawPic (112, 0, sb_faces[f][anim]); } /* @@ -804,11 +758,9 @@ Sbar_Draw */ void Sbar_Draw (void) { - if (scr_con_current == vid.height) + if (scr_con_current == vid.conheight) return; // console is full screen -// sb_updates++; - if (sb_lines > 24) { Sbar_DrawInventory (); @@ -820,22 +772,21 @@ void Sbar_Draw (void) { Sbar_DrawAlphaPic (0, 0, sb_scorebar, 0.4); Sbar_DrawScoreboard (); -// sb_updates = 0; } else if (sb_lines) { Sbar_DrawAlphaPic (0, 0, sb_sbar, 0.4); - // keys (hipnotic only) - //MED 01/04/97 moved keys here so they would not be overwritten - if (hipnotic) - { - if (cl.items & IT_KEY1) - Sbar_DrawPic (209, 3, sb_items[0]); - if (cl.items & IT_KEY2) - Sbar_DrawPic (209, 12, sb_items[1]); - } - // armor +// keys (hipnotic only) + //MED 01/04/97 moved keys here so they would not be overwritten + if (gamemode == GAME_HIPNOTIC) + { + if (cl.items & IT_KEY1) + Sbar_DrawPic (209, 3, sb_items[0]); + if (cl.items & IT_KEY2) + Sbar_DrawPic (209, 12, sb_items[1]); + } +// armor if (cl.items & IT_INVULNERABILITY) { Sbar_DrawNum (24, 0, 666, 3, 1); @@ -843,10 +794,9 @@ void Sbar_Draw (void) } else { - if (rogue) + if (gamemode == GAME_ROGUE) { - Sbar_DrawNum (24, 0, cl.stats[STAT_ARMOR], 3, - cl.stats[STAT_ARMOR] <= 25); + Sbar_DrawNum (24, 0, cl.stats[STAT_ARMOR], 3, cl.stats[STAT_ARMOR] <= 25); if (cl.items & RIT_ARMOR3) Sbar_DrawPic (0, 0, sb_armor[2]); else if (cl.items & RIT_ARMOR2) @@ -856,8 +806,7 @@ void Sbar_Draw (void) } else { - Sbar_DrawNum (24, 0, cl.stats[STAT_ARMOR], 3 - , cl.stats[STAT_ARMOR] <= 25); + Sbar_DrawNum (24, 0, cl.stats[STAT_ARMOR], 3, cl.stats[STAT_ARMOR] <= 25); if (cl.items & IT_ARMOR3) Sbar_DrawPic (0, 0, sb_armor[2]); else if (cl.items & IT_ARMOR2) @@ -871,11 +820,10 @@ void Sbar_Draw (void) Sbar_DrawFace (); // health - Sbar_DrawNum (136, 0, cl.stats[STAT_HEALTH], 3 - , cl.stats[STAT_HEALTH] <= 25); + Sbar_DrawNum (136, 0, cl.stats[STAT_HEALTH], 3, cl.stats[STAT_HEALTH] <= 25); // ammo icon - if (rogue) + if (gamemode == GAME_ROGUE) { if (cl.items & RIT_SHELLS) Sbar_DrawPic (224, 0, sb_ammo[0]); @@ -904,14 +852,11 @@ void Sbar_Draw (void) Sbar_DrawPic (224, 0, sb_ammo[3]); } - Sbar_DrawNum (248, 0, cl.stats[STAT_AMMO], 3, - cl.stats[STAT_AMMO] <= 10); + Sbar_DrawNum (248, 0, cl.stats[STAT_AMMO], 3, cl.stats[STAT_AMMO] <= 10); } - if (vid.width > 320) { - if (cl.gametype == GAME_DEATHMATCH) - Sbar_MiniDeathmatchOverlay (); - } + if (vid.conwidth > 320 && cl.gametype == GAME_DEATHMATCH) + Sbar_MiniDeathmatchOverlay (); } //============================================================================= @@ -970,7 +915,7 @@ void Sbar_DeathmatchOverlay (void) // draw the text l = scoreboardlines; - x = ((vid.width - 320)>>1) - 140; + x = ((vid.conwidth - 320)>>1) - 140; y = 40; for (i = 0;i < l;i++) { @@ -1016,7 +961,7 @@ void Sbar_MiniDeathmatchOverlay (void) char num[128]; scoreboard_t *s; - if (vid.width < 512 || !sb_lines) + if (vid.conwidth < 512 || !sb_lines) return; // scores @@ -1024,7 +969,7 @@ void Sbar_MiniDeathmatchOverlay (void) // draw the text l = scoreboardlines; - y = vid.height - sb_lines; + y = vid.conheight - sb_lines; numlines = sb_lines/8; if (numlines < 3) return; @@ -1045,7 +990,7 @@ void Sbar_MiniDeathmatchOverlay (void) i = 0; x = 324; - for (;i < scoreboardlines && y < vid.height - 8;i++) + for (;i < scoreboardlines && y < vid.conheight - 8;i++) { k = fragsort[i]; s = &cl.scores[k]; @@ -1125,5 +1070,5 @@ void Sbar_FinaleOverlay (void) qpic_t *pic; pic = Draw_CachePic ("gfx/finale.lmp"); - Draw_Pic ( (vid.width-pic->width)/2, 16, pic); + Draw_Pic ( (vid.conwidth-pic->width)/2, 16, pic); } diff --git a/sv_main.c b/sv_main.c index d280f47d..9aa91f8d 100644 --- a/sv_main.c +++ b/sv_main.c @@ -22,7 +22,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "quakedef.h" cvar_t sv_pvscheckentities = {0, "sv_pvscheckentities", "1"}; -cvar_t sv_vischeckentities = {0, "sv_vischeckentities", "1"}; +cvar_t sv_vischeckentities = {0, "sv_vischeckentities", "0"}; // extremely accurate visibility checking, but too slow cvar_t sv_reportvischeckentities = {0, "sv_reportvischeckentities", "0"}; int sv_vischeckentitycullcount = 0; @@ -233,7 +233,7 @@ void SV_SendServerinfo (client_t *client) char message[2048]; MSG_WriteByte (&client->message, svc_print); - sprintf (message, "%c\nDARKPLACES VERSION %4.2f BUILD %i SERVER (%i CRC)", 2, VERSION, buildnumber, pr_crc); + sprintf (message, "\002\nServer: %s build %i (progs %i crc)", gamename, buildnumber, pr_crc); MSG_WriteString (&client->message,message); MSG_WriteByte (&client->message, svc_serverinfo); @@ -262,7 +262,7 @@ void SV_SendServerinfo (client_t *client) MSG_WriteByte (&client->message, sv.edicts->v.sounds); MSG_WriteByte (&client->message, sv.edicts->v.sounds); -// set view +// set view MSG_WriteByte (&client->message, svc_setview); MSG_WriteShort (&client->message, NUM_FOR_EDICT(client->edict)); @@ -419,7 +419,7 @@ void SV_AddToFatPVS (vec3_t org, mnode_t *node) } return; } - + plane = node->plane; d = DotProduct (org, plane->normal) - plane->dist; if (d > 8) @@ -500,9 +500,10 @@ void SV_WriteEntitiesToClient (client_t *client, edict_t *clent, sizebuf_t *msg) vec3_t org, origin, angles, entmins, entmaxs; float movelerp, moveilerp, nextfullupdate; edict_t *ent; - eval_t *val; - entity_state_t *baseline; // LordHavoc: delta or startup baseline + eval_t *val; + entity_state_t *baseline; // LordHavoc: delta or startup baseline trace_t trace; + model_t *model; // find the client's PVS VectorAdd (clent->v.origin, clent->v.view_ofs, org); @@ -516,7 +517,7 @@ void SV_WriteEntitiesToClient (client_t *client, edict_t *clent, sizebuf_t *msg) */ clentnum = EDICT_TO_PROG(clent); // LordHavoc: for comparison purposes -// send over all entities (except the client) that touch the pvs + // send all entities that touch the pvs ent = NEXT_EDICT(sv.edicts); for (e = 1;e < sv.num_edicts;e++, ent = NEXT_EDICT(ent)) { @@ -559,10 +560,15 @@ void SV_WriteEntitiesToClient (client_t *client, edict_t *clent, sizebuf_t *msg) if (val->_float != 0) bits |= U_GLOWTRAIL; - if (ent->v.modelindex == 0 || pr_strings[ent->v.model] == 0) // no model + if (ent->v.modelindex >= 0 && ent->v.modelindex < MAX_MODELS && pr_strings[ent->v.model]) + model = sv.models[(int)ent->v.modelindex]; + else + { + model = NULL; if (ent != clent) // LordHavoc: always send player if (glowsize == 0 && (bits & U_GLOWTRAIL) == 0) // no effects continue; + } if (ent->v.movetype == MOVETYPE_STEP && ((int) ent->v.flags & (FL_ONGROUND | FL_FLY | FL_SWIM))) // monsters have smoothed walking/flying/swimming movement { @@ -603,6 +609,16 @@ void SV_WriteEntitiesToClient (client_t *client, edict_t *clent, sizebuf_t *msg) } else // copy as they are { + if (ent->v.movetype == MOVETYPE_STEP) // monster, but airborn, update lerp info + { + // update lerp positions + ent->steplerptime = sv.time; + VectorCopy(ent->v.origin, ent->stepoldorigin); + VectorCopy(ent->v.angles, ent->stepoldangles); + VectorCopy(ent->v.origin, ent->steporigin); + VectorCopy(ent->v.angles, ent->stepangles); + } + VectorCopy(ent->v.angles, angles); if (DotProduct(ent->v.velocity, ent->v.velocity) >= 1.0f) { @@ -615,27 +631,37 @@ void SV_WriteEntitiesToClient (client_t *client, edict_t *clent, sizebuf_t *msg) { VectorCopy(ent->v.origin, origin); } - if (ent->v.movetype == MOVETYPE_STEP) // monster, but airborn, update lerp info - { - // update lerp positions - ent->steplerptime = sv.time; - VectorCopy(ent->v.origin, ent->stepoldorigin); - VectorCopy(ent->v.angles, ent->stepoldangles); - VectorCopy(ent->v.origin, ent->steporigin); - VectorCopy(ent->v.angles, ent->stepangles); - } } // ent has survived every check so far, check if it is visible if (ent != clent && ((bits & U_VIEWMODEL) == 0)) { // use the predicted origin - entmins[0] = ent->v.mins[0] + origin[0] - 1.0f; - entmins[1] = ent->v.mins[1] + origin[1] - 1.0f; - entmins[2] = ent->v.mins[2] + origin[2] - 1.0f; - entmaxs[0] = ent->v.maxs[0] + origin[0] + 1.0f; - entmaxs[1] = ent->v.maxs[1] + origin[1] + 1.0f; - entmaxs[2] = ent->v.maxs[2] + origin[2] + 1.0f; + entmins[0] = origin[0] - 1.0f; + entmins[1] = origin[1] - 1.0f; + entmins[2] = origin[2] - 1.0f; + entmaxs[0] = origin[0] + 1.0f; + entmaxs[1] = origin[1] + 1.0f; + entmaxs[2] = origin[2] + 1.0f; + // using the model's bounding box to ensure things are visible regardless of their physics box + if (model) + { + if (ent->v.angles[0] || ent->v.angles[2]) // pitch and roll + { + VectorAdd(entmins, model->rotatedmins, entmins); + VectorAdd(entmaxs, model->rotatedmaxs, entmaxs); + } + else if (ent->v.angles[1]) + { + VectorAdd(entmins, model->yawmins, entmins); + VectorAdd(entmaxs, model->yawmaxs, entmaxs); + } + else + { + VectorAdd(entmins, model->normalmins, entmins); + VectorAdd(entmaxs, model->normalmaxs, entmaxs); + } + } // if not touching a visible leaf if (sv_pvscheckentities.value && !SV_BoxTouchingPVS(pvs, entmins, entmaxs, sv.worldmodel->nodes)) @@ -689,10 +715,10 @@ void SV_WriteEntitiesToClient (client_t *client, edict_t *clent, sizebuf_t *msg) { if (glowsize == 0 && (bits & U_GLOWTRAIL) == 0) // no effects { - if (ent->v.modelindex && pr_strings[ent->v.model]) // model + if (model) // model { // don't send if flagged for NODRAW and there are no effects - if (sv.models[(int)ent->v.modelindex]->flags == 0 && ((effects & EF_NODRAW) || scale <= 0 || alpha <= 0)) + if (model->flags == 0 && ((effects & EF_NODRAW) || scale <= 0 || alpha <= 0)) continue; } else // no model and no effects @@ -992,11 +1018,7 @@ void SV_WriteClientdataToMessage (edict_t *ent, sizebuf_t *msg) MSG_WriteByte (msg, ent->v.ammo_rockets); MSG_WriteByte (msg, ent->v.ammo_cells); - if (standard_quake) - { - MSG_WriteByte (msg, ent->v.weapon); - } - else + if (gamemode == GAME_HIPNOTIC || gamemode == GAME_ROGUE) { for(i=0;i<32;i++) { @@ -1007,6 +1029,10 @@ void SV_WriteClientdataToMessage (edict_t *ent, sizebuf_t *msg) } } } + else + { + MSG_WriteByte (msg, ent->v.weapon); + } } /* diff --git a/sv_phys.c b/sv_phys.c index 9fc909d3..3cf4fd1a 100644 --- a/sv_phys.c +++ b/sv_phys.c @@ -356,6 +356,8 @@ int SV_FlyMove (edict_t *ent, float time, trace_t *steptrace) return 7; } CrossProduct (planes[0], planes[1], dir); + // LordHavoc: thanks to taniwha of QuakeForge for pointing out this fix for slowed falling in corners + VectorNormalize(dir); d = DotProduct (dir, ent->v.velocity); VectorScale (dir, d, ent->v.velocity); } diff --git a/sv_user.c b/sv_user.c index fd3d2b64..27a6e108 100644 --- a/sv_user.c +++ b/sv_user.c @@ -582,8 +582,8 @@ nextmsg: || Q_strncasecmp(s, "ping", 4) == 0 || Q_strncasecmp(s, "ban", 3) == 0 || Q_strncasecmp(s, "pmodel", 6) == 0 - || (nehahra && (Q_strncasecmp(s, "max", 3) == 0 || Q_strncasecmp(s, "monster", 7) == 0 || Q_strncasecmp(s, "scrag", 5) == 0 || Q_strncasecmp(s, "gimme", 5) == 0 || Q_strncasecmp(s, "wraith", 6) == 0)) - || (!nehahra && (Q_strncasecmp(s, "god", 3) == 0 || Q_strncasecmp(s, "notarget", 8) == 0 || Q_strncasecmp(s, "fly", 3) == 0 || Q_strncasecmp(s, "give", 4) == 0 || Q_strncasecmp(s, "noclip", 6) == 0))) + || (gamemode == GAME_NEHAHRA && (Q_strncasecmp(s, "max", 3) == 0 || Q_strncasecmp(s, "monster", 7) == 0 || Q_strncasecmp(s, "scrag", 5) == 0 || Q_strncasecmp(s, "gimme", 5) == 0 || Q_strncasecmp(s, "wraith", 6) == 0)) + || (gamemode != GAME_NEHAHRA && (Q_strncasecmp(s, "god", 3) == 0 || Q_strncasecmp(s, "notarget", 8) == 0 || Q_strncasecmp(s, "fly", 3) == 0 || Q_strncasecmp(s, "give", 4) == 0 || Q_strncasecmp(s, "noclip", 6) == 0))) { ret = 1; Cmd_ExecuteString (s, src_client); diff --git a/sys.h b/sys.h index dd31ce09..4b5372ea 100644 --- a/sys.h +++ b/sys.h @@ -60,3 +60,7 @@ void Sys_Sleep (void); void Sys_SendKeyEvents (void); // Perform Key_Event () callbacks until the input que is empty +// called after Com_InitArgv +void Sys_Shared_EarlyInit (void); +// called after Host_init +void Sys_Shared_LateInit (void); diff --git a/sys_linux.c b/sys_linux.c index d36b5588..405dc314 100644 --- a/sys_linux.c +++ b/sys_linux.c @@ -274,9 +274,11 @@ int main (int c, char **v) fcntl(0, F_SETFL, fcntl (0, F_GETFL, 0) | FNDELAY); + Sys_Shared_EarlyInit(); + Host_Init(); - Sys_Shared_Init(); + Sys_Shared_LateInit(); oldtime = Sys_DoubleTime () - 0.1; while (1) diff --git a/sys_shared.c b/sys_shared.c index 719bce79..01fd0fba 100644 --- a/sys_shared.c +++ b/sys_shared.c @@ -107,19 +107,24 @@ void Sys_Printf (char *fmt, ...) //#endif } -void Sys_Shared_Init(void) +char engineversion[40]; + +void Sys_Shared_EarlyInit(void) { - if (COM_CheckParm("-nostdout")) - sys_nostdout = 1; - else - { #if defined(__linux__) - fcntl(0, F_SETFL, fcntl (0, F_GETFL, 0) | FNDELAY); - printf ("DarkPlaces Linux GL %.2f build %3i", (float) VERSION, buildnumber); + sprintf (engineversion, "%s Linux GL build %3i", gamename, buildnumber); #elif defined(WIN32) - printf ("DarkPlaces Windows GL %.2f build %3i", (float) VERSION, buildnumber); + sprintf (engineversion, "%s Windows GL build %3i", gamename, buildnumber); #else - printf ("DarkPlaces Unknown GL %.2f build %3i", (float) VERSION, buildnumber); + sprintf (engineversion, "%s Unknown GL build %3i", gamename, buildnumber); #endif - } + + if (COM_CheckParm("-nostdout")) + sys_nostdout = 1; + else + printf("%s\n", engineversion); +} + +void Sys_Shared_LateInit(void) +{ } diff --git a/sys_win.c b/sys_win.c index 8ad72f03..82b5179b 100644 --- a/sys_win.c +++ b/sys_win.c @@ -579,7 +579,7 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLin *lpCmdLine = 0; lpCmdLine++; } - + } } @@ -590,7 +590,7 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLin host_parms.argc = com_argc; host_parms.argv = com_argv; - Sys_Shared_Init(); + Sys_Shared_EarlyInit(); // take the greater of all the available memory or half the total memory, // but at least 8 Mb and no more than 16 Mb, unless they explicitly @@ -631,13 +631,13 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLin if (t < com_argc) hFile = (HANDLE)atoi (com_argv[t+1]); } - + if ((t = COM_CheckParm ("-HPARENT")) > 0) { if (t < com_argc) heventParent = (HANDLE)atoi (com_argv[t+1]); } - + if ((t = COM_CheckParm ("-HCHILD")) > 0) { if (t < com_argc) @@ -659,9 +659,10 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLin timeBeginPeriod (1); #endif - Sys_Printf ("Host_Init\n"); Host_Init (); + Sys_Shared_LateInit(); + oldtime = Sys_DoubleTime (); /* main window message loop */ diff --git a/transform.c b/transform.c index 9396bbe3..363d04c9 100644 --- a/transform.c +++ b/transform.c @@ -148,17 +148,17 @@ void softwaretransformset (vec3_t origin, vec3_t angles, vec_t scale) softwaretransform_classify(); } -void softwaretransformforentity (entity_t *e) +void softwaretransformforentity (entity_render_t *r) { vec3_t angles; - angles[0] = -e->render.angles[0]; - angles[1] = e->render.angles[1]; - angles[2] = e->render.angles[2]; - softwaretransformset(e->render.origin, angles, e->render.scale); + angles[0] = -r->angles[0]; + angles[1] = r->angles[1]; + angles[2] = r->angles[2]; + softwaretransformset(r->origin, angles, r->scale); } // brush entities are not backwards like models and sprites are -void softwaretransformforbrushentity (entity_t *e) +void softwaretransformforbrushentity (entity_render_t *r) { - softwaretransformset(e->render.origin, e->render.angles, e->render.scale); + softwaretransformset(r->origin, r->angles, r->scale); } diff --git a/transform.h b/transform.h index 6b0494ec..e2d82e58 100644 --- a/transform.h +++ b/transform.h @@ -10,8 +10,8 @@ extern vec3_t softwaretransform_y; extern vec3_t softwaretransform_z; extern int softwaretransform_type; -extern void softwaretransformforentity (entity_t *e); -extern void softwaretransformforbrushentity (entity_t *e); +extern void softwaretransformforentity (entity_render_t *r); +extern void softwaretransformforbrushentity (entity_render_t *r); extern void softwaretransformidentity (void); extern void softwaretransformset (vec3_t origin, vec3_t angles, vec_t scale); extern void (*softwaretransform) (vec3_t in, vec3_t out); diff --git a/ui.c b/ui.c index 1e10d337..88e1c2e5 100644 --- a/ui.c +++ b/ui.c @@ -39,7 +39,7 @@ static byte pointerimage[256] = 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, @@ -49,8 +49,8 @@ void ui_start(void) { // ui_mousepointer = Draw_CachePic("ui/mousepointer.lmp"); ui_mousepointertexture = R_LoadTexture("mousepointer", 16, 16, pointerimage, TEXF_ALPHA | TEXF_PRECACHE); - ui_mouse_x = vid.width * 0.5; - ui_mouse_y = vid.height * 0.5; + ui_mouse_x = vid.conwidth * 0.5; + ui_mouse_y = vid.conheight * 0.5; ui_alive = true; } @@ -75,8 +75,8 @@ void ui_mouseupdate(float x, float y) { if (ui_alive) { - ui_mouse_x = bound(0, x, vid.width); - ui_mouse_y = bound(0, y, vid.height); + ui_mouse_x = bound(0, x, vid.conwidth); + ui_mouse_y = bound(0, y, vid.conheight); } } @@ -86,8 +86,8 @@ void ui_mouseupdaterelative(float x, float y) { ui_mouse_x += x; ui_mouse_y += y; - ui_mouse_x = bound(0, ui_mouse_x, vid.width); - ui_mouse_y = bound(0, ui_mouse_y, vid.height); + ui_mouse_x = bound(0, ui_mouse_x, vid.conwidth); + ui_mouse_y = bound(0, ui_mouse_y, vid.conheight); } } @@ -115,7 +115,7 @@ void ui_clear(ui_t *ui) void ui_item ( ui_t *ui, char *basename, int number, - float x, float y, qpic_t *pic, + float x, float y, qpic_t *pic, char *string, float left, float top, float width, float height, void(*leftkey)(void *nativedata1, void *nativedata2, float data1, float data2), void(*rightkey)(void *nativedata1, void *nativedata2, float data1, float data2), @@ -140,30 +140,37 @@ void ui_item } ui->item_count++; } + memset(it, 0, sizeof(ui_item_t)); strncpy(it->name, itemname, 32); it->flags = 0; + if (pic || string) + { + it->flags |= ITEM_DRAWABLE; + it->draw_pic = pic; + it->draw_string = string; + it->draw_x = x; + it->draw_y = y; + } if (leftkey || rightkey || enterkey || mouseclick) + { it->flags |= ITEM_CLICKABLE; - if (pic) - it->flags |= ITEM_DRAWABLE; - it->draw_x = x; - it->draw_y = y; - it->click_x = x + left; - it->click_y = y + top; - it->click_x2 = it->click_x + width; - it->click_y2 = it->click_y + height; - it->leftkey = leftkey; - it->rightkey = rightkey; - it->enterkey = enterkey; - it->mouseclick = mouseclick; - if (it->mouseclick == NULL) - it->mouseclick = (void *)it->enterkey; - if (it->leftkey == NULL) - it->leftkey = it->enterkey; - if (it->rightkey == NULL) - it->rightkey = it->enterkey; - it->nativedata1 = nativedata1; - it->nativedata2 = nativedata2; + it->click_x = x + left; + it->click_y = y + top; + it->click_x2 = it->click_x + width; + it->click_y2 = it->click_y + height; + it->leftkey = leftkey; + it->rightkey = rightkey; + it->enterkey = enterkey; + it->mouseclick = mouseclick; + if (it->mouseclick == NULL) + it->mouseclick = (void *)it->enterkey; + if (it->leftkey == NULL) + it->leftkey = it->enterkey; + if (it->rightkey == NULL) + it->rightkey = it->enterkey; + it->nativedata1 = nativedata1; + it->nativedata2 = nativedata2; + } } void ui_item_remove(ui_t *ui, char *basename, int number) @@ -298,8 +305,8 @@ void ui_update(void) ui_item_t *startitem, *it; if (ui_alive) { - ui_mouse_x = bound(0, ui_mouse_x, vid.width); - ui_mouse_y = bound(0, ui_mouse_y, vid.height); + ui_mouse_x = bound(0, ui_mouse_x, vid.conwidth); + ui_mouse_y = bound(0, ui_mouse_y, vid.conheight); if ((ui_active = ui_isactive())) { @@ -397,17 +404,28 @@ void ui_draw(void) if (ui->item_count) for (i = 0, it = ui->items;i < ui->item_count;i++, it++) if (it->flags & ITEM_DRAWABLE) - Draw_Pic(it->draw_x, it->draw_y, it->draw_pic); + { + if (it->draw_pic) + Draw_Pic(it->draw_x, it->draw_y, it->draw_pic); + if (it->draw_string) + Draw_String(it->draw_x, it->draw_y, it->draw_string, 9999); + } if ((it = ui_hititem(ui_mouse_x, ui_mouse_y))) { - Draw_AdditivePic(it->draw_x, it->draw_y, it->draw_pic); + if (it->draw_pic) + Draw_AdditivePic(it->draw_x, it->draw_y, it->draw_pic); + if (it->draw_string) + Draw_AdditiveString(it->draw_x, it->draw_y, it->draw_string, 9999); if (ui_showname.value) Draw_String(ui_mouse_x, ui_mouse_y + 16, it->name, 9999); } it = ui_keyrealitem; - Draw_AdditivePic(it->draw_x, it->draw_y, it->draw_pic); + if (it->draw_pic) + Draw_AdditivePic(it->draw_x, it->draw_y, it->draw_pic); + if (it->draw_string) + Draw_AdditiveString(it->draw_x, it->draw_y, it->draw_string, 9999); // Draw_Pic(ui_mouse_x, ui_mouse_y, ui_mousepointer); Draw_GenericPic(ui_mousepointertexture, 1, 1, 1, 1, ui_mouse_x, ui_mouse_y, 16, 16); diff --git a/ui.h b/ui.h index 4fc2c1c6..a9b94688 100644 --- a/ui.h +++ b/ui.h @@ -12,6 +12,7 @@ typedef struct char name[32]; int flags; qpic_t *draw_pic; + char *draw_string; int draw_x, draw_y; int click_x, click_y, click_x2, click_y2; void(*leftkey)(void *nativedata1, void *nativedata2, float data1, float data2); @@ -64,7 +65,7 @@ void ui_clear(ui_t *ui); void ui_item ( ui_t *ui, char *basename, int number, - float x, float y, qpic_t *pic, + float x, float y, qpic_t *pic, char *string, float left, float top, float width, float height, void(*leftkey)(void *nativedata1, void *nativedata2, float data1, float data2), void(*rightkey)(void *nativedata1, void *nativedata2, float data1, float data2), diff --git a/vid.h b/vid.h index d8a4cfdf..60a659f1 100644 --- a/vid.h +++ b/vid.h @@ -8,7 +8,7 @@ of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. @@ -19,17 +19,15 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // vid.h -- video driver defs -typedef struct vrect_s -{ - int x,y,width,height; - struct vrect_s *pnext; -} vrect_t; - typedef struct { - int width; - int height; - int recalc_refdef; // if true, recalc vid-based stuff + // these are set with GL_BeginRendering and can change from frame to frame + int realx; + int realy; + int realwidth; + int realheight; +// int recalc_refdef; // if true, recalc vid-based stuff + int conwidth; int conheight; } viddef_t; diff --git a/vid_3dfxsvga.c b/vid_3dfxsvga.c index 3f4e4266..cc1f9cca 100644 --- a/vid_3dfxsvga.c +++ b/vid_3dfxsvga.c @@ -291,8 +291,6 @@ void VID_Init(void) vid.conheight = height; if (vid.conwidth > width) vid.conwidth = width; - vid.width = vid.conwidth; - vid.height = vid.conheight; InitSig(); // trap evil signals @@ -302,7 +300,7 @@ void VID_Init(void) Con_SafePrintf ("Video mode %dx%d initialized.\n", width, height); - vid.recalc_refdef = 1; // force a surface cache flush +// vid.recalc_refdef = 1; // force a surface cache flush } void VID_ExtraOptionDraw(unsigned int options_draw_cursor) diff --git a/vid_glx.c b/vid_glx.c index 69c34705..994084da 100644 --- a/vid_glx.c +++ b/vid_glx.c @@ -38,7 +38,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include #include -static Display *dpy = NULL; +static Display *vidx11_display = NULL; static int scrnum; static Window win; static GLXContext ctx = NULL; @@ -73,6 +73,9 @@ static XF86VidModeModeInfo **vidmodes; static int num_vidmodes; static qboolean vidmode_active = false; +static Visual *vidx11_visual; +static Colormap vidx11_colormap; + /*-----------------------------------------------------------------------*/ float gldepthmin, gldepthmax; @@ -215,20 +218,20 @@ static void install_grabs(void) XWindowAttributes attribs_1; XSetWindowAttributes attribs_2; - XGetWindowAttributes(dpy, win, &attribs_1); + XGetWindowAttributes(vidx11_display, win, &attribs_1); attribs_2.event_mask = attribs_1.your_event_mask | KEY_MASK | MOUSE_MASK; - XChangeWindowAttributes(dpy, win, CWEventMask, &attribs_2); + XChangeWindowAttributes(vidx11_display, win, CWEventMask, &attribs_2); // inviso cursor - XDefineCursor(dpy, win, CreateNullCursor(dpy, win)); + XDefineCursor(vidx11_display, win, CreateNullCursor(vidx11_display, win)); - XGrabPointer(dpy, win, True, 0, GrabModeAsync, GrabModeAsync, win, None, CurrentTime); + XGrabPointer(vidx11_display, win, True, 0, GrabModeAsync, GrabModeAsync, win, None, CurrentTime); if (vid_dga.value) { int MajorVersion, MinorVersion; - if (!XF86DGAQueryVersion(dpy, &MajorVersion, &MinorVersion)) + if (!XF86DGAQueryVersion(vidx11_display, &MajorVersion, &MinorVersion)) { // unable to query, probalby not supported Con_Printf( "Failed to detect XF86DGA Mouse\n" ); @@ -237,34 +240,34 @@ static void install_grabs(void) else { vid_dga.value = 1; - XF86DGADirectVideo(dpy, DefaultScreen(dpy), XF86DGADirectMouse); - XWarpPointer(dpy, None, win, 0, 0, 0, 0, 0, 0); + XF86DGADirectVideo(vidx11_display, DefaultScreen(vidx11_display), XF86DGADirectMouse); + XWarpPointer(vidx11_display, None, win, 0, 0, 0, 0, 0, 0); } } else - XWarpPointer(dpy, None, win, 0, 0, 0, 0, vid.width / 2, vid.height / 2); + XWarpPointer(vidx11_display, None, win, 0, 0, 0, 0, scr_width / 2, scr_height / 2); - XGrabKeyboard(dpy, win, False, GrabModeAsync, GrabModeAsync, CurrentTime); + XGrabKeyboard(vidx11_display, win, False, GrabModeAsync, GrabModeAsync, CurrentTime); mouse_active = true; mouse_x = mouse_y = 0; -// XSync(dpy, True); +// XSync(vidx11_display, True); } static void uninstall_grabs(void) { - if (!dpy || !win) + if (!vidx11_display || !win) return; if (vid_dga.value == 1) - XF86DGADirectVideo(dpy, DefaultScreen(dpy), 0); + XF86DGADirectVideo(vidx11_display, DefaultScreen(vidx11_display), 0); - XUngrabPointer(dpy, CurrentTime); - XUngrabKeyboard(dpy, CurrentTime); + XUngrabPointer(vidx11_display, CurrentTime); + XUngrabKeyboard(vidx11_display, CurrentTime); // inviso cursor - XUndefineCursor(dpy, win); + XUndefineCursor(vidx11_display, win); mouse_active = false; } @@ -275,12 +278,12 @@ static void HandleEvents(void) // KeySym ks; qboolean dowarp = false; - if (!dpy) + if (!vidx11_display) return; - while (XPending(dpy)) + while (XPending(vidx11_display)) { - XNextEvent(dpy, &event); + XNextEvent(vidx11_display, &event); switch (event.type) { @@ -312,7 +315,7 @@ static void HandleEvents(void) { mouse_x += event.xmotion.x - p_mouse_x; mouse_y += event.xmotion.y - p_mouse_y; - if (abs(vid.width/2 - event.xmotion.x) > vid.width / 4 || abs(vid.height/2 - event.xmotion.y) > vid.height / 4) + if (abs(scr_width/2 - event.xmotion.x) > scr_width / 4 || abs(scr_height/2 - event.xmotion.y) > scr_height / 4) dowarp = true; } } @@ -394,16 +397,16 @@ static void HandleEvents(void) if (dowarp) { /* move the mouse to the window center again */ - p_mouse_x = vid.width / 2; - p_mouse_y = vid.height / 2; - XWarpPointer(dpy, None, win, 0, 0, 0, 0, p_mouse_x, p_mouse_y); + p_mouse_x = scr_width / 2; + p_mouse_y = scr_height / 2; + XWarpPointer(vidx11_display, None, win, 0, 0, 0, 0, p_mouse_x, p_mouse_y); } } static void IN_DeactivateMouse( void ) { - if (!mouse_avail || !dpy || !win) + if (!mouse_avail || !vidx11_display || !win) return; if (mouse_active) @@ -415,7 +418,7 @@ static void IN_DeactivateMouse( void ) static void IN_ActivateMouse( void ) { - if (!mouse_avail || !dpy || !win) + if (!mouse_avail || !vidx11_display || !win) return; if (!mouse_active) @@ -429,25 +432,25 @@ static void IN_ActivateMouse( void ) void VID_Shutdown(void) { - if (!ctx || !dpy) + if (!ctx || !vidx11_display) return; - if (dpy) + if (vidx11_display) { uninstall_grabs(); if (vidmode_active) - XF86VidModeSwitchToMode(dpy, scrnum, vidmodes[0]); + XF86VidModeSwitchToMode(vidx11_display, scrnum, vidmodes[0]); /* Disabled, causes a segfault during shutdown. if (ctx) - glXDestroyContext(dpy, ctx); + glXDestroyContext(vidx11_display, ctx); */ if (win) - XDestroyWindow(dpy, win); - XCloseDisplay(dpy); + XDestroyWindow(vidx11_display, win); + XCloseDisplay(vidx11_display); } vidmode_active = false; - dpy = NULL; + vidx11_display = NULL; win = 0; ctx = NULL; } @@ -495,7 +498,7 @@ void GL_EndRendering (void) if (!r_render.value) return; glFlush(); - glXSwapBuffers(dpy, win); + glXSwapBuffers(vidx11_display, win); // handle the mouse state when windowed if that's changed usemouse = false; @@ -521,15 +524,100 @@ void GL_EndRendering (void) } } +// LordHavoc: ported from SDL 1.2.2, this was far more difficult to port from +// SDL than to simply use the XFree gamma ramp extension, but that affects the +// whole screen even when the game window is inactive, this only affects the +// screen while the window is active, very desirable behavior :) int VID_SetGamma(float prescale, float gamma, float scale, float base) { +// LordHavoc: FIXME: finish this code, we need to allocate colors before we can store them +#if 1 return FALSE; +#else + int i, ncolors, c; + unsigned int Rmask, Gmask, Bmask, Rloss, Gloss, Bloss, Rshift, Gshift, Bshift, mask; + XColor xcmap[256]; + unsigned short ramp[256]; + + if (COM_CheckParm("-nogamma")) + return FALSE; + + if (vidx11_visual->class != DirectColor) + { + Con_Printf("X11 Visual class is %d, can only do gamma on %d\n", vidx11_visual->class, DirectColor); + return FALSE; + } + + Rmask = vidx11_visual->red_mask; + Gmask = vidx11_visual->green_mask; + Bmask = vidx11_visual->blue_mask; + + Rshift = 0; + Rloss = 8; + if ((mask = Rmask)) + { + for (;!(mask & 1);mask >>= 1) + ++Rshift; + for (;(mask & 1);mask >>= 1) + --Rloss; + } + Gshift = 0; + Gloss = 8; + if ((mask = Gmask)) + { + for (;!(mask & 1);mask >>= 1) + ++Gshift; + for (;(mask & 1);mask >>= 1) + --Gloss; + } + Bshift = 0; + Bloss = 8; + if ((mask = Bmask)) + { + for (;!(mask & 1);mask >>= 1) + ++Bshift; + for (;(mask & 1);mask >>= 1) + --Bloss; + } + + BuildGammaTable16(prescale, gamma, scale, base, ramp); + + // convert gamma ramp to palette (yes this seems odd) + ncolors = vidx11_visual->map_entries; + for (i = 0;i < ncolors;i++) + { + c = (256 * i / ncolors); + xcmap[i].pixel = ((c >> Rloss) << Rshift) | ((c >> Gloss) << Gshift) | ((c >> Bloss) << Bshift); + xcmap[i].red = ramp[c]; + xcmap[i].green = ramp[c]; + xcmap[i].blue = ramp[c]; + xcmap[i].flags = (DoRed|DoGreen|DoBlue); + } + XStoreColors(vidx11_display, vidx11_colormap, xcmap, ncolors); + XSync(vidx11_display, false); + // FIXME: should this check for BadAccess/BadColor/BadValue errors produced by XStoreColors before setting this true? + return TRUE; +#endif } void VID_Init(void) { int i; - int attrib[] = +// LordHavoc: FIXME: finish this code, we need to allocate colors before we can store them +#if 0 + int gammaattrib[] = + { + GLX_RGBA, + GLX_RED_SIZE, 1, + GLX_GREEN_SIZE, 1, + GLX_BLUE_SIZE, 1, + GLX_DOUBLEBUFFER, + GLX_DEPTH_SIZE, 1, + GLX_X_VISUAL_TYPE, GLX_DIRECT_COLOR, + None + }; +#endif + int nogammaattrib[] = { GLX_RGBA, GLX_RED_SIZE, 1, @@ -547,7 +635,6 @@ void VID_Init(void) XVisualInfo *visinfo; qboolean fullscreen = true; int MajorVersion, MinorVersion; - int actualWidth, actualHeight; Cvar_RegisterVariable (&vid_mouse); Cvar_RegisterVariable (&vid_dga); @@ -584,18 +671,18 @@ void VID_Init(void) if (vid.conheight < 200) vid.conheight = 200; - if (!(dpy = XOpenDisplay(NULL))) + if (!(vidx11_display = XOpenDisplay(NULL))) { fprintf(stderr, "Error couldn't open the X display\n"); exit(1); } - scrnum = DefaultScreen(dpy); - root = RootWindow(dpy, scrnum); + scrnum = DefaultScreen(vidx11_display); + root = RootWindow(vidx11_display, scrnum); // Get video mode list MajorVersion = MinorVersion = 0; - if (!XF86VidModeQueryVersion(dpy, &MajorVersion, &MinorVersion)) + if (!XF86VidModeQueryVersion(vidx11_display, &MajorVersion, &MinorVersion)) vidmode_ext = false; else { @@ -603,18 +690,27 @@ void VID_Init(void) vidmode_ext = true; } - visinfo = glXChooseVisual(dpy, scrnum, attrib); + visinfo = NULL; +// LordHavoc: FIXME: finish this code, we need to allocate colors before we can store them +#if 0 + if (!COM_CheckParm("-nogamma")) + visinfo = glXChooseVisual(vidx11_display, scrnum, gammaattrib); +#endif if (!visinfo) { - fprintf(stderr, "qkHack: Error couldn't get an RGB, Double-buffered, Depth visual\n"); - exit(1); + visinfo = glXChooseVisual(vidx11_display, scrnum, nogammaattrib); + if (!visinfo) + { + fprintf(stderr, "qkHack: Error couldn't get an RGB, Double-buffered, Depth visual\n"); + exit(1); + } } if (vidmode_ext) { int best_fit, best_dist, dist, x, y; - XF86VidModeGetAllModeLines(dpy, scrnum, &num_vidmodes, &vidmodes); + XF86VidModeGetAllModeLines(vidx11_display, scrnum, &num_vidmodes, &vidmodes); // Are we going fullscreen? If so, let's change video mode if (fullscreen) @@ -639,25 +735,32 @@ void VID_Init(void) if (best_fit != -1) { - actualWidth = vidmodes[best_fit]->hdisplay; - actualHeight = vidmodes[best_fit]->vdisplay; + // LordHavoc: changed from ActualWidth/ActualHeight =, + // to width/height =, so the window will take the full area of + // the mode chosen + width = vidmodes[best_fit]->hdisplay; + height = vidmodes[best_fit]->vdisplay; // change to the mode - XF86VidModeSwitchToMode(dpy, scrnum, vidmodes[best_fit]); + XF86VidModeSwitchToMode(vidx11_display, scrnum, vidmodes[best_fit]); vidmode_active = true; // Move the viewport to top left - XF86VidModeSetViewPort(dpy, scrnum, 0, 0); + XF86VidModeSetViewPort(vidx11_display, scrnum, 0, 0); } else fullscreen = 0; } } + // LordHavoc: save the visual for use in gamma ramp settings later + vidx11_visual = visinfo->visual; + /* window attributes */ attr.background_pixel = 0; attr.border_pixel = 0; - attr.colormap = XCreateColormap(dpy, root, visinfo->visual, AllocNone); + // LordHavoc: save the colormap for later, too + vidx11_colormap = attr.colormap = XCreateColormap(vidx11_display, root, visinfo->visual, AllocNone); attr.event_mask = X_MASK; if (vidmode_active) { @@ -669,25 +772,25 @@ void VID_Init(void) else mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask; - win = XCreateWindow(dpy, root, 0, 0, width, height, 0, visinfo->depth, InputOutput, visinfo->visual, mask, &attr); - XStoreName(dpy, win, "DarkPlaces-GLX"); - XMapWindow(dpy, win); + win = XCreateWindow(vidx11_display, root, 0, 0, width, height, 0, visinfo->depth, InputOutput, visinfo->visual, mask, &attr); + XStoreName(vidx11_display, win, gamename); + XMapWindow(vidx11_display, win); if (vidmode_active) { - XMoveWindow(dpy, win, 0, 0); - XRaiseWindow(dpy, win); - XWarpPointer(dpy, None, win, 0, 0, 0, 0, 0, 0); - XFlush(dpy); + XMoveWindow(vidx11_display, win, 0, 0); + XRaiseWindow(vidx11_display, win); + XWarpPointer(vidx11_display, None, win, 0, 0, 0, 0, 0, 0); + XFlush(vidx11_display); // Move the viewport to top left - XF86VidModeSetViewPort(dpy, scrnum, 0, 0); + XF86VidModeSetViewPort(vidx11_display, scrnum, 0, 0); } - XFlush(dpy); + XFlush(vidx11_display); - ctx = glXCreateContext(dpy, visinfo, NULL, True); + ctx = glXCreateContext(vidx11_display, visinfo, NULL, True); - glXMakeCurrent(dpy, win, ctx); + glXMakeCurrent(vidx11_display, win, ctx); scr_width = width; scr_height = height; @@ -696,8 +799,6 @@ void VID_Init(void) vid.conheight = height; if (vid.conwidth > width) vid.conwidth = width; - vid.width = vid.conwidth; - vid.height = vid.conheight; InitSig(); // trap evil signals @@ -706,7 +807,7 @@ void VID_Init(void) Con_SafePrintf ("Video mode %dx%d initialized.\n", width, height); // force a surface cache flush - vid.recalc_refdef = 1; +// vid.recalc_refdef = 1; } void Sys_SendKeyEvents(void) @@ -764,7 +865,7 @@ void IN_MouseMove (usercmd_t *cmd) if (/*freelook && */!(in_strafe.state & 1)) { cl.viewangles[PITCH] += m_pitch.value * mouse_y; - cl.viewangles[PITCH] = bound (-70, cl.viewangles[PITCH], 80); + cl.viewangles[PITCH] = bound (-90, cl.viewangles[PITCH], 90); } else { diff --git a/vid_wgl.c b/vid_wgl.c index cb4621c2..7f4cc5f6 100644 --- a/vid_wgl.c +++ b/vid_wgl.c @@ -163,7 +163,7 @@ qboolean VID_SetWindowedMode (int modenum) height = rect.bottom - rect.top; // Create the DIB window - mainwindow = CreateWindowEx (ExWindowStyle, "DarkPlaces", "DarkPlacesGL", WindowStyle, rect.left, rect.top, width, height, NULL, NULL, global_hInstance, NULL); + mainwindow = CreateWindowEx (ExWindowStyle, gamename, gamename, WindowStyle, rect.left, rect.top, width, height, NULL, NULL, global_hInstance, NULL); if (!mainwindow) Sys_Error ("Couldn't create DIB window"); @@ -180,8 +180,6 @@ qboolean VID_SetWindowedMode (int modenum) vid.conheight = modelist[modenum].height; if (vid.conwidth > modelist[modenum].width) vid.conwidth = modelist[modenum].width; - vid.width = vid.conwidth; - vid.height = vid.conheight; SendMessage (mainwindow, WM_SETICON, (WPARAM)true, (LPARAM)hIcon); SendMessage (mainwindow, WM_SETICON, (WPARAM)false, (LPARAM)hIcon); @@ -229,7 +227,7 @@ qboolean VID_SetFullDIBMode (int modenum) height = rect.bottom - rect.top; // Create the DIB window - mainwindow = CreateWindowEx (ExWindowStyle, "DarkPlaces", "DarkPlacesGL", WindowStyle, rect.left, rect.top, width, height, NULL, NULL, global_hInstance, NULL); + mainwindow = CreateWindowEx (ExWindowStyle, gamename, gamename, WindowStyle, rect.left, rect.top, width, height, NULL, NULL, global_hInstance, NULL); if (!mainwindow) Sys_Error ("Couldn't create DIB window"); @@ -241,8 +239,6 @@ qboolean VID_SetFullDIBMode (int modenum) vid.conheight = modelist[modenum].height; if (vid.conwidth > modelist[modenum].width) vid.conwidth = modelist[modenum].width; - vid.width = vid.conwidth; - vid.height = vid.conheight; // needed because we're not getting WM_MOVE messages fullscreen on NT window_x = 0; @@ -342,7 +338,7 @@ int VID_SetMode (int modenum) if (!msg_suppress_1) Con_SafePrintf ("Video mode %s initialized.\n", VID_GetModeDescription (vid_modenum)); - vid.recalc_refdef = 1; +// vid.recalc_refdef = 1; return true; } @@ -587,6 +583,7 @@ void ClearAllStates (void) } void VID_RestoreGameGamma(void); +extern qboolean hostloopactive; void AppActivate(BOOL fActive, BOOL minimize) /**************************************************************************** @@ -640,7 +637,8 @@ void AppActivate(BOOL fActive, BOOL minimize) // IN_ActivateMouse (); // IN_HideMouse (); // } - VID_RestoreGameGamma(); + if (hostloopactive) + VID_RestoreGameGamma(); } if (!fActive) @@ -988,7 +986,7 @@ void VID_InitDIB (HINSTANCE hInstance) wc.hCursor = LoadCursor (NULL,IDC_ARROW); wc.hbrBackground = NULL; wc.lpszMenuName = 0; - wc.lpszClassName = "DarkPlaces"; + wc.lpszClassName = gamename; if (!RegisterClass (&wc) ) Sys_Error ("Couldn't register window class"); diff --git a/view.c b/view.c index ae3c45f2..65ba402a 100644 --- a/view.c +++ b/view.c @@ -562,7 +562,7 @@ CalcGunAngle ================== */ void CalcGunAngle (void) -{ +{ /* float yaw, pitch, move; static float oldyaw = 0; @@ -718,6 +718,8 @@ void V_CalcIntermissionRefdef (void) v_idlescale.value = old; } +extern void CL_LerpUpdate(entity_t *e, int frame, int modelindex); + /* ================== V_CalcRefdef @@ -786,13 +788,12 @@ void V_CalcRefdef (void) V_BoundOffsets (); // set up gun position + VectorCopy (ent->render.origin, view->render.origin); + view->render.origin[2] += cl.viewheight; VectorCopy (cl.viewangles, view->render.angles); CalcGunAngle (); - VectorCopy (ent->render.origin, view->render.origin); - view->render.origin[2] += cl.viewheight; - for (i=0 ; i<3 ; i++) { view->render.origin[i] += forward[i]*bob*0.4; @@ -801,9 +802,16 @@ void V_CalcRefdef (void) } view->render.origin[2] += bob; + // FIXME: this setup code is somewhat evil (CL_LerpUpdate should be private) + CL_LerpUpdate(view, cl.stats[STAT_WEAPONFRAME], cl.stats[STAT_WEAPON]); + view->render.model = cl.model_precache[cl.stats[STAT_WEAPON]]; view->render.frame = cl.stats[STAT_WEAPONFRAME]; view->render.colormap = -1; // no special coloring + view->render.alpha = ent->render.alpha; // LordHavoc: if the player is transparent, so is the gun + view->render.effects = ent->render.effects; + view->render.scale = 1; + VectorCopy(ent->render.colormod, view->render.colormod); // set up the refresh position diff --git a/view.h b/view.h index f44353eb..ab069251 100644 --- a/view.h +++ b/view.h @@ -28,4 +28,5 @@ void V_Init (void); void V_RenderView (void); float V_CalcRoll (vec3_t angles, vec3_t velocity); void V_UpdateBlends (void); +void V_CalcBlend (void); diff --git a/world.c b/world.c index fc2f38a4..c0edd62e 100644 --- a/world.c +++ b/world.c @@ -320,7 +320,7 @@ void SV_ClearWorld (void) memset (sv_areanodes, 0, sizeof(sv_areanodes)); sv_numareanodes = 0; - SV_CreateAreaNode (0, sv.worldmodel->mins, sv.worldmodel->maxs); + SV_CreateAreaNode (0, sv.worldmodel->normalmins, sv.worldmodel->normalmaxs); } @@ -566,157 +566,173 @@ LINE TESTING IN HULLS */ // 1/32 epsilon to keep floating point happy -#define DIST_EPSILON (0.03125) +//#define DIST_EPSILON (0.03125) +#define DIST_EPSILON (0.125) -/* -================== -SV_RecursiveHullCheck +#define HULLCHECKSTATE_EMPTY 0 +#define HULLCHECKSTATE_SOLID 1 +#define HULLCHECKSTATE_DONE 2 -================== -*/ -/* -qboolean SV_RecursiveHullCheck (hull_t *hull, int num, float p1f, float p2f, vec3_t p1, vec3_t p2, trace_t *trace) +// LordHavoc: FIXME: this is not thread safe, if threading matters here, pass +// this as a struct to RecursiveHullCheck, RecursiveHullCheck_Impact, etc... +RecursiveHullCheckTraceInfo_t RecursiveHullCheckInfo; +#define RHC RecursiveHullCheckInfo + +void SV_RecursiveHullCheck_Impact (mplane_t *plane, int side) +{ + // LordHavoc: using doubles for extra accuracy + double t1, t2, frac; + + // LordHavoc: now that we have found the impact, recalculate the impact + // point from scratch for maximum accuracy, with an epsilon bias on the + // surface distance + frac = plane->dist; + if (side) + { + frac -= DIST_EPSILON; + VectorNegate (plane->normal, RHC.trace->plane.normal); + RHC.trace->plane.dist = -plane->dist; + } + else + { + frac += DIST_EPSILON; + VectorCopy (plane->normal, RHC.trace->plane.normal); + RHC.trace->plane.dist = plane->dist; + } + + if (plane->type < 3) + { + t1 = RHC.start[plane->type] - frac; + t2 = RHC.start[plane->type] + RHC.dist[plane->type] - frac; + } + else + { + t1 = plane->normal[0] * RHC.start[0] + plane->normal[1] * RHC.start[1] + plane->normal[2] * RHC.start[2] - frac; + t2 = plane->normal[0] * (RHC.start[0] + RHC.dist[0]) + plane->normal[1] * (RHC.start[1] + RHC.dist[1]) + plane->normal[2] * (RHC.start[2] + RHC.dist[2]) - frac; + } + + frac = t1 / (t1 - t2); + frac = bound(0.0f, frac, 1.0f); + + RHC.trace->fraction = frac; + RHC.trace->endpos[0] = RHC.start[0] + frac * RHC.dist[0]; + RHC.trace->endpos[1] = RHC.start[1] + frac * RHC.dist[1]; + RHC.trace->endpos[2] = RHC.start[2] + frac * RHC.dist[2]; +} + +int SV_RecursiveHullCheck (int num, float p1f, float p2f, vec3_t p1, vec3_t p2) { dclipnode_t *node; - mplane_t *plane; - float t1, t2; - float frac; - int i; vec3_t mid; int side; float midf; + // LordHavoc: FIXME: this is not thread safe... if threading matters here, + // remove the static prefixes + static int ret; + static mplane_t *plane; + static float t1, t2, frac; + // LordHavoc: a goto! everyone flee in terror... :) loc0: -// check for empty + // check for empty if (num < 0) { - if (num != CONTENTS_SOLID) + RHC.trace->endcontents = num; + if (RHC.trace->startcontents) { - trace->allsolid = false; - if (num == CONTENTS_EMPTY) - trace->inopen = true; + if (num == RHC.trace->startcontents) + RHC.trace->allsolid = false; else - trace->inwater = true; + { + // if the first leaf is solid, set startsolid + if (RHC.trace->allsolid) + RHC.trace->startsolid = true; + return HULLCHECKSTATE_SOLID; + } + return HULLCHECKSTATE_EMPTY; } else - trace->startsolid = true; - return true; // empty + { + if (num != CONTENTS_SOLID) + { + RHC.trace->allsolid = false; + if (num == CONTENTS_EMPTY) + RHC.trace->inopen = true; + else + RHC.trace->inwater = true; + } + else + { + // if the first leaf is solid, set startsolid + if (RHC.trace->allsolid) + RHC.trace->startsolid = true; + return HULLCHECKSTATE_SOLID; + } + return HULLCHECKSTATE_EMPTY; + } } - if (num < hull->firstclipnode || num > hull->lastclipnode) - Sys_Error ("SV_RecursiveHullCheck: bad node number"); - -// -// find the point distances -// - node = hull->clipnodes + num; - plane = hull->planes + node->planenum; + // find the point distances + node = RHC.hull->clipnodes + num; - t1 = PlaneDiff(p1, plane); - t2 = PlaneDiff(p2, plane); - -#if 1 - if (t1 >= 0 && t2 >= 0) - // LordHavoc: optimized recursion -// return SV_RecursiveHullCheck (hull, node->children[0], p1f, p2f, p1, p2, trace); - { - num = node->children[0]; - goto loc0; - } - if (t1 < 0 && t2 < 0) -// return SV_RecursiveHullCheck (hull, node->children[1], p1f, p2f, p1, p2, trace); + plane = RHC.hull->planes + node->planenum; + if (plane->type < 3) { - num = node->children[1]; - goto loc0; + t1 = p1[plane->type] - plane->dist; + t2 = p2[plane->type] - plane->dist; } -#else - if ( (t1 >= DIST_EPSILON && t2 >= DIST_EPSILON) || (t2 > t1 && t1 >= 0) ) - return SV_RecursiveHullCheck (hull, node->children[0], p1f, p2f, p1, p2, trace); - if ( (t1 <= -DIST_EPSILON && t2 <= -DIST_EPSILON) || (t2 < t1 && t1 <= 0) ) - return SV_RecursiveHullCheck (hull, node->children[1], p1f, p2f, p1, p2, trace); -#endif - -// put the crosspoint DIST_EPSILON pixels on the near side - if (t1 < 0) - frac = bound(0, (t1 + DIST_EPSILON)/(t1-t2), 1); else - frac = bound(0, (t1 - DIST_EPSILON)/(t1-t2), 1); - - midf = p1f + (p2f - p1f)*frac; - mid[0] = p1[0] + frac*(p2[0] - p1[0]); - mid[1] = p1[1] + frac*(p2[1] - p1[1]); - mid[2] = p1[2] + frac*(p2[2] - p1[2]); - - side = (t1 < 0); - -// move up to the node - if (!SV_RecursiveHullCheck (hull, node->children[side], p1f, midf, p1, mid, trace) ) - return false; - -#ifdef PARANOID - if (SV_HullPointContents (hull, node->children[side], mid) == CONTENTS_SOLID) - { - Con_Printf ("mid PointInHullSolid\n"); - return false; - } -#endif - - if (SV_HullPointContents (hull, node->children[side^1], mid) != CONTENTS_SOLID) -// go past the node - return SV_RecursiveHullCheck (hull, node->children[side^1], midf, p2f, mid, p2, trace); - // mid would need to be duplicated during recursion... -*/ - /* { - p1f = midf; - p1 = mid; - num = node->children[side^1]; - goto loc0; + t1 = DotProduct (plane->normal, p1) - plane->dist; + t2 = DotProduct (plane->normal, p2) - plane->dist; } - */ -/* - if (trace->allsolid) - return false; // never got out of the solid area - -//================== -// the other side of the node is solid, this is the impact point -//================== - if (!side) + // LordHavoc: rearranged the side/frac code + if (t1 >= 0) { - VectorCopy (plane->normal, trace->plane.normal); - trace->plane.dist = plane->dist; + if (t2 >= 0) + { + num = node->children[0]; + goto loc0; + } + // put the crosspoint DIST_EPSILON pixels on the near side + side = 0; } else { - VectorNegate (plane->normal, trace->plane.normal); - trace->plane.dist = -plane->dist; - } - - while (SV_HullPointContents (hull, hull->firstclipnode, mid) == CONTENTS_SOLID) - { // shouldn't really happen, but does occasionally - frac -= 0.1; - if (frac < 0) + if (t2 < 0) { - trace->fraction = midf; - VectorCopy (mid, trace->endpos); - Con_DPrintf ("backup past 0\n"); - return false; + num = node->children[1]; + goto loc0; } - midf = p1f + (p2f - p1f)*frac; - for (i=0 ; i<3 ; i++) - mid[i] = p1[i] + frac*(p2[i] - p1[i]); + // put the crosspoint DIST_EPSILON pixels on the near side + side = 1; } - trace->fraction = midf; - VectorCopy (mid, trace->endpos); + frac = t1 / (t1 - t2); + frac = bound(0.0f, frac, 1.0f); - return false; + midf = p1f + ((p2f - p1f) * frac); + mid[0] = RHC.start[0] + midf * RHC.dist[0]; + mid[1] = RHC.start[1] + midf * RHC.dist[1]; + mid[2] = RHC.start[2] + midf * RHC.dist[2]; + + // front side first + ret = SV_RecursiveHullCheck (node->children[side], p1f, midf, p1, mid); + if (ret != HULLCHECKSTATE_EMPTY) + return ret; // solid or done + ret = SV_RecursiveHullCheck (node->children[!side], midf, p2f, mid, p2); + if (ret != HULLCHECKSTATE_SOLID) + return ret; // empty or done + + // front is air and back is solid, this is the impact point... + SV_RecursiveHullCheck_Impact(RHC.hull->planes + node->planenum, side); + + return HULLCHECKSTATE_DONE; } -*/ -// LordHavoc: backported from my optimizations to PM_RecursiveHullCheck in QuakeForge newtree (QW) -qboolean SV_RecursiveHullCheck (hull_t *hull, int num, float p1f, float p2f, vec3_t p1, vec3_t p2, trace_t *trace) +/* +qboolean SV_RecursiveHullCheckContentBoundary (hull_t *hull, int num, float p1f, float p2f, vec3_t p1, vec3_t p2, trace_t *trace) { dclipnode_t *node; mplane_t *plane; @@ -732,16 +748,10 @@ loc0: // check for empty if (num < 0) { - if (num != CONTENTS_SOLID) - { - trace->allsolid = false; - if (num == CONTENTS_EMPTY) - trace->inopen = true; - else - trace->inwater = true; - } - else + if (num != trace->startcontents) trace->startsolid = true; + else + trace->allsolid = false; return true; // empty } @@ -760,49 +770,61 @@ loc0: t2 = DotProduct (plane->normal, p2) - plane->dist; } + // LordHavoc: rearranged the side/frac code // LordHavoc: recursion optimization - if (t1 >= 0 && t2 >= 0) + if (t1 >= 0) { - num = node->children[0]; - goto loc0; + if (t2 >= 0) + { + num = node->children[0]; + goto loc0; + } + // put the crosspoint DIST_EPSILON pixels on the near side + side = 0; } - if (t1 < 0 && t2 < 0) + else { - num = node->children[1]; - goto loc0; + if (t2 < 0) + { + num = node->children[1]; + goto loc0; + } + // put the crosspoint DIST_EPSILON pixels on the near side + side = 1; } -// put the crosspoint DIST_EPSILON pixels on the near side - side = (t1 < 0); - if (side) - frac = bound(0, (t1 + DIST_EPSILON) / (t1 - t2), 1); - else - frac = bound(0, (t1 - DIST_EPSILON) / (t1 - t2), 1); - - midf = p1f + (p2f - p1f)*frac; - for (i=0 ; i<3 ; i++) - mid[i] = p1[i] + frac*(p2[i] - p1[i]); + frac = t1 / (t1 - t2); + frac = bound(0.0f, frac, 1.0f); + + midf = p1f + ((p2f - p1f) * frac); + mid[0] = p1[0] + ((p2[0] - p1[0]) * frac); + mid[1] = p1[1] + ((p2[1] - p1[1]) * frac); + mid[2] = p1[2] + ((p2[2] - p1[2]) * frac); // move up to the node if (!SV_RecursiveHullCheck (hull, node->children[side], p1f, midf, p1, mid, trace) ) return false; +*/ + /* #ifdef PARANOID - if (SV_HullPointContents (pm_hullmodel, mid, node->children[side]) == CONTENTS_SOLID) + if (SV_HullPointContents (pm_hullmodel, mid, node->children[side]) != trace->startcontents) { Con_Printf ("mid PointInHullSolid\n"); return false; } #endif + */ +/* // LordHavoc: warning to the clumsy, this recursion can not be optimized because mid would need to be duplicated on a stack - if (SV_HullPointContents (hull, node->children[side^1], mid) != CONTENTS_SOLID) + if (SV_HullPointContents (hull, node->children[side^1], mid) == trace->startcontents) // go past the node return SV_RecursiveHullCheck (hull, node->children[side^1], midf, p2f, mid, p2, trace); - + if (trace->allsolid) return false; // never got out of the solid area - + //================== // the other side of the node is solid, this is the impact point //================== @@ -817,8 +839,11 @@ loc0: trace->plane.dist = -plane->dist; } - while (SV_HullPointContents (hull, hull->firstclipnode, mid) == CONTENTS_SOLID) - { // shouldn't really happen, but does occasionally +*/ + /* + while (SV_HullPointContents (hull, hull->firstclipnode, mid) != trace->startcontents) + { + // shouldn't really happen, but does occasionally frac -= 0.1; if (frac < 0) { @@ -828,15 +853,30 @@ loc0: return false; } midf = p1f + (p2f - p1f)*frac; - for (i=0 ; i<3 ; i++) - mid[i] = p1[i] + frac*(p2[i] - p1[i]); + mid[0] = p1[0] + frac*(p2[0] - p1[0]); + mid[1] = p1[1] + frac*(p2[1] - p1[1]); + mid[2] = p1[2] + frac*(p2[2] - p1[2]); } + */ +/* + + frac = t1; + if (side) + frac += DIST_EPSILON; + else + frac -= DIST_EPSILON; - trace->fraction = midf; - VectorCopy (mid, trace->endpos); + frac /= (t1 - t2); + frac = bound(0.0f, frac, 1.0f); + + trace->fraction = p1f + (p2f - p1f)*frac; + trace->endpos[0] = p1[0] + frac*(p2[0] - p1[0]); + trace->endpos[1] = p1[1] + frac*(p2[1] - p1[1]); + trace->endpos[2] = p1[2] + frac*(p2[2] - p1[2]); return false; } +*/ qboolean SV_TestLine (hull_t *hull, int num, vec3_t p1, vec3_t p2) { @@ -858,44 +898,98 @@ loc0: // find the point distances // node = hull->clipnodes + num; + if (node->children[0] < 0) + { + if (node->children[0] == CONTENTS_SOLID) + return false; + if (node->children[1] < 0) + return node->children[1] != CONTENTS_SOLID; + } + else if (node->children[1] == CONTENTS_SOLID) + return false; + plane = hull->planes + node->planenum; - t1 = PlaneDiff(p1, plane); - t2 = PlaneDiff(p2, plane); - - if (t1 >= 0 && t2 >= 0) + if (plane->type < 3) { - num = node->children[0]; - goto loc0; + t1 = p1[plane->type] - plane->dist; + t2 = p2[plane->type] - plane->dist; } - if (t1 < 0 && t2 < 0) + else { - num = node->children[1]; - goto loc0; + t1 = DotProduct (plane->normal, p1) - plane->dist; + t2 = DotProduct (plane->normal, p2) - plane->dist; } -// put the crosspoint DIST_EPSILON pixels on the near side - side = (t1 < 0); - - if (side) - frac = bound(0, (t1 + DIST_EPSILON)/(t1-t2), 1); + if (t1 >= 0) + { + if (t2 >= 0) + { + num = node->children[0]; + goto loc0; + } + side = 0; + } else - frac = bound(0, (t1 - DIST_EPSILON)/(t1-t2), 1); - - mid[0] = p1[0] + frac*(p2[0] - p1[0]); - mid[1] = p1[1] + frac*(p2[1] - p1[1]); - mid[2] = p1[2] + frac*(p2[2] - p1[2]); + { + if (t2 < 0) + { + num = node->children[1]; + goto loc0; + } + side = 1; + } if (node->children[side] < 0) { if (node->children[side] == CONTENTS_SOLID) return false; - return SV_TestLine(hull, node->children[!side], mid, p2); + + if (node->children[!side] < 0) + return node->children[!side] != CONTENTS_SOLID; + else + { + frac = t1 / (t1 - t2); + frac = bound(0, frac, 1); + + mid[0] = p1[0] + frac*(p2[0] - p1[0]); + mid[1] = p1[1] + frac*(p2[1] - p1[1]); + mid[2] = p1[2] + frac*(p2[2] - p1[2]); + + return SV_TestLine(hull, node->children[!side], mid, p2); + } } - else if (SV_TestLine(hull, node->children[side], p1, mid)) - return SV_TestLine(hull, node->children[!side], mid, p2); else - return false; + { + if (node->children[!side] < 0) + { + if (node->children[!side] == CONTENTS_SOLID) + return false; + + frac = t1 / (t1 - t2); + frac = bound(0, frac, 1); + + mid[0] = p1[0] + frac*(p2[0] - p1[0]); + mid[1] = p1[1] + frac*(p2[1] - p1[1]); + mid[2] = p1[2] + frac*(p2[2] - p1[2]); + + return SV_TestLine(hull, node->children[side], p1, mid); + } + else + { + frac = t1 / (t1 - t2); + frac = bound(0, frac, 1); + + mid[0] = p1[0] + frac*(p2[0] - p1[0]); + mid[1] = p1[1] + frac*(p2[1] - p1[1]); + mid[2] = p1[2] + frac*(p2[2] - p1[2]); + + if (SV_TestLine(hull, node->children[side], p1, mid)) + return SV_TestLine(hull, node->children[!side], mid, p2); + else + return false; + } + } } @@ -947,7 +1041,11 @@ trace_t SV_ClipMoveToEntity (edict_t *ent, vec3_t start, vec3_t mins, vec3_t max } // trace a line through the apropriate clipping hull - SV_RecursiveHullCheck (hull, hull->firstclipnode, 0, 1, start_l, end_l, &trace); + VectorCopy(start_l, RecursiveHullCheckInfo.start); + VectorSubtract(end_l, start_l, RecursiveHullCheckInfo.dist); + RecursiveHullCheckInfo.hull = hull; + RecursiveHullCheckInfo.trace = &trace; + SV_RecursiveHullCheck (hull->firstclipnode, 0, 1, start_l, end_l); // LordHavoc: enabling rotating bmodels // rotate endpos back to world frame of reference @@ -1149,7 +1247,7 @@ trace_t SV_Move (vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, int type, e VectorCopy (mins, clip.mins2); VectorCopy (maxs, clip.maxs2); } - + // create the bounding box of the entire move SV_MoveBounds ( start, clip.mins2, clip.maxs2, end, clip.boxmins, clip.boxmaxs ); diff --git a/world.h b/world.h index c6cc8a83..7de90a32 100644 --- a/world.h +++ b/world.h @@ -8,7 +8,7 @@ of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. @@ -34,9 +34,9 @@ typedef struct vec3_t endpos; // final position plane_t plane; // surface normal at impact edict_t *ent; // entity the surface is on - // LordHavoc: added texture and lighting to traceline - char *texturename; - vec3_t light; + int startcontents; // if not zero, treats this value as empty, and + // all others as solid (impact on content change) + int endcontents; // set to the contents that was hit at the end point } trace_t; @@ -82,4 +82,17 @@ trace_t SV_Move (vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, int type, e // passedict is explicitly excluded from clipping checks (normally NULL) -extern qboolean SV_RecursiveHullCheck (hull_t *hull, int num, float p1f, float p2f, vec3_t p1, vec3_t p2, trace_t *trace); +int SV_RecursiveHullCheck (int num, float p1f, float p2f, vec3_t p1, vec3_t p2); + +typedef struct +{ + hull_t *hull; + trace_t *trace; + vec3_t start; + vec3_t dist; +} +RecursiveHullCheckTraceInfo_t; + +// LordHavoc: FIXME: this is not thread safe, if threading matters here, pass +// this as a struct to RecursiveHullCheck, RecursiveHullCheck_Impact, etc... +extern RecursiveHullCheckTraceInfo_t RecursiveHullCheckInfo; -- 2.39.2