From e4b3858e7aca0ead91be1d8f675db084d025abad Mon Sep 17 00:00:00 2001 From: lordhavoc Date: Fri, 6 Apr 2001 03:10:06 +0000 Subject: [PATCH] optimized AngleVectors calls (pass NULL for vectors that should not be generated) added VectorVectors (takes a forward unit vector, makes right and up vectors) corrected silly id spelling mistakes 'allready' and 'allways' most host_frametime references changed to cl.frametime or sv.frametime fixed movement interpolation in listen games (host client wasn't lerping the framerate capped server's frames) added EF_FLAME effect, untested changed svc_showlmp to use shorts, not bytes (except in nehahra compatibility mode) broke svc_fog for now removed svc_farclip removed svc_playerposition removed svc_skybox increased maximum number of models and sounds to 1024 each (and added extra svc_ messages and update bits to handle the new limits) made punchangle use preciseangles (on DP servers), added punchvector (view origin kick, useful for earthquakes?) redesigned entire animation interpolation system (can lerp between independently playing framegroups) redesigned animation scene lookup in model and sprite rendering to use a single system added a simple clientside effect system (meant for playing sprite explosion animations entirely on the client, with very nice interpolation and framerate control) added te_smallflash added te_customflash added te_flamejet (untested) darkened lightning glow and made it adjustable (r_glowinglightning cvar is now a scaler, not just an option) increased maximum number of clientside entities COM_WriteFile will now create a path leading up to the file removed cpu_*.* files reorganized fractalnoise code, now behaves more correctly stripped out qsg_version stuff, replaced by pr_checkextension and extensions have changed completely (extensions are documented in dpextensions.qc in DP mod and release zips) made skin and sprite mipmapping optional (r_mipskins cvar, r_mipsprites cvar), saves about 32% of texture memory if disabled rewrote texture management system (again), now uses flags to specify texture attributes (all textures without the PRECACHE flag are uploaded only when first used, conserves huge amounts of memory), and is cleaner code r_precachetextures cvar controls how PRECACHE texture flag is used (0 = never precache, 1 = use PRECACHE flag, 2 = always precache) changed way text filtering mode is decided now requires vertex array support (standard in OpenGL 1.1 so this is not a problem) takes advantage of GL_EXT_compiled_vertex_array extension (no speed gain for my Geforce2, may help other people) reverted to GL transforms for models (no speed gain for my Geforce2, may help other people) gl_transform cvar controls whether to use GL transforms (1) or software transforms (0), could not measure any speed difference in my testing r_shadows removed due to GL transforms on models model and sprite interpolation now handle 4 frame interpolation to accomodate new interpolation system RSurf_Draw* functions greatly optimized Host_Error will now Sys_Error rather than crash if Host_Frame has not yet been executed cleaned up viewthing frame reporting code, now uses the new animation system can now look directly up and down ByteToNormal and NormalToByte added in mathlib.c, also moved anorms.h table to mathlib.c added axial cases for BoxOnPlaneSide (BIG improvement) trivert2 vertex format removed, now uses alias trivertx_t format as-is (33% less model memory usage and possibly quicker loading) redesigned map texture loading again (particularly HL maps) water is now lit on both sides sprites are now cached like models sprite loading redesigned to use new animation system increased maximum packet size to accomodate the largest possible PF_vectoyaw optimized a little PF_vectoangles optimized a little PF_findchain added PF_findchainfloat added PF_effect added PF_te_blood added PF_te_bloodshower added PF_te_explosionrgb added PF_te_particlecube added PF_te_particlerain added PF_te_particlesnow added PF_te_spark added PF_te_gunshotquad added PF_te_spikequad added PF_te_superspikequad added PF_te_explosionquad added PF_te_smallflash added PF_te_customflash added PF_te_gunshot added PF_te_spike added PF_te_superspike added PF_te_explosion added PF_te_tarexplosion added PF_te_wizspike added PF_te_knightspike added PF_te_lavasplash added PF_te_teleport added PF_te_explosion2 added PF_te_lightning1 added PF_te_lightning2 added PF_te_lightning3 added PF_te_beam added PF_vectorvectors added increased maximum file path length explosions are no longer round removed LIGHTSCALE settings removed r_donttransformmodels cvar a lot of particle effect changes (bouncing sparks, blood sprays from gibs that stick on the walls) fixed sound combining so it no longer plays past the end of the buffer fixed sound resampling git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@183 d7cf8633-e32d-0410-b094-e92efae38249 --- anorms.h | 181 -------- chase.c | 4 +- cl_demo.c | 4 +- cl_input.c | 7 +- cl_main.c | 72 ++-- cl_parse.c | 215 ++++++---- cl_tent.c | 48 ++- client.h | 16 +- cmd.c | 2 +- cmd.h | 2 +- common.c | 52 +-- common.h | 2 + cpu_noasm.c | 67 --- cpu_x86.bat | 1 - cpu_x86.nasm | 198 --------- cpu_x86.obj | Bin 847 -> 0 bytes cvar.c | 2 +- cvar.h | 2 +- draw.h | 2 +- fractalnoise.c | 68 +-- gl_draw.c | 91 ++-- gl_models.c | 1089 +++++++++++++++++++----------------------------- gl_poly.c | 129 +++--- gl_poly.h | 69 ++- gl_rmain.c | 92 +++- gl_rsurf.c | 452 ++++++++++++-------- gl_screen.c | 9 +- gl_textures.c | 560 ++++++++++++------------- gl_warp.c | 61 +-- glquake.h | 70 +--- host.c | 37 +- host_cmd.c | 67 +-- image.c | 31 +- image.h | 8 +- in_svgalib.c | 9 +- in_win.c | 13 +- makefile | 10 +- mathlib.c | 467 ++++++++++++++++++--- mathlib.h | 15 + menu.c | 2 +- model_alias.c | 278 ++++++------ model_alias.h | 30 +- model_brush.c | 279 +++++++------ model_brush.h | 6 +- model_shared.c | 13 +- model_shared.h | 24 +- model_sprite.c | 171 ++++---- model_sprite.h | 31 +- net.h | 2 +- pr_cmds.c | 723 ++++++++++++++++++++++++++++---- pr_edict.c | 4 + progs.h | 1 + protocol.h | 40 +- quakedef.h | 13 +- r_crosshairs.c | 4 +- r_explosion.c | 101 ++--- r_lerpanim.c | 183 ++++++++ r_lerpanim.h | 9 + r_light.c | 259 ++++++------ r_light.h | 10 +- r_part.c | 774 +++++++++++++++++++--------------- r_sprites.c | 130 ++---- r_textures.h | 19 + render.h | 102 ++--- server.h | 6 +- snd_dma.c | 22 +- snd_mem.c | 118 ++++-- snd_mix.c | 90 ++-- snd_win.c | 2 +- sv_main.c | 93 ++++- sv_phys.c | 44 +- sv_user.c | 30 +- sys_win.c | 12 +- vid.h | 7 +- vid_3dfxsvga.c | 50 ++- vid_glx.c | 91 ++-- vid_shared.c | 14 + vid_wgl.c | 64 +-- view.c | 41 +- world.c | 14 +- zone.c | 2 +- 81 files changed, 4500 insertions(+), 3632 deletions(-) delete mode 100644 anorms.h delete mode 100644 cpu_noasm.c delete mode 100644 cpu_x86.bat delete mode 100644 cpu_x86.nasm delete mode 100644 cpu_x86.obj create mode 100644 r_lerpanim.c create mode 100644 r_lerpanim.h create mode 100644 r_textures.h diff --git a/anorms.h b/anorms.h deleted file mode 100644 index 11a9007e..00000000 --- a/anorms.h +++ /dev/null @@ -1,181 +0,0 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -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. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -{-0.525731, 0.000000, 0.850651}, -{-0.442863, 0.238856, 0.864188}, -{-0.295242, 0.000000, 0.955423}, -{-0.309017, 0.500000, 0.809017}, -{-0.162460, 0.262866, 0.951056}, -{0.000000, 0.000000, 1.000000}, -{0.000000, 0.850651, 0.525731}, -{-0.147621, 0.716567, 0.681718}, -{0.147621, 0.716567, 0.681718}, -{0.000000, 0.525731, 0.850651}, -{0.309017, 0.500000, 0.809017}, -{0.525731, 0.000000, 0.850651}, -{0.295242, 0.000000, 0.955423}, -{0.442863, 0.238856, 0.864188}, -{0.162460, 0.262866, 0.951056}, -{-0.681718, 0.147621, 0.716567}, -{-0.809017, 0.309017, 0.500000}, -{-0.587785, 0.425325, 0.688191}, -{-0.850651, 0.525731, 0.000000}, -{-0.864188, 0.442863, 0.238856}, -{-0.716567, 0.681718, 0.147621}, -{-0.688191, 0.587785, 0.425325}, -{-0.500000, 0.809017, 0.309017}, -{-0.238856, 0.864188, 0.442863}, -{-0.425325, 0.688191, 0.587785}, -{-0.716567, 0.681718, -0.147621}, -{-0.500000, 0.809017, -0.309017}, -{-0.525731, 0.850651, 0.000000}, -{0.000000, 0.850651, -0.525731}, -{-0.238856, 0.864188, -0.442863}, -{0.000000, 0.955423, -0.295242}, -{-0.262866, 0.951056, -0.162460}, -{0.000000, 1.000000, 0.000000}, -{0.000000, 0.955423, 0.295242}, -{-0.262866, 0.951056, 0.162460}, -{0.238856, 0.864188, 0.442863}, -{0.262866, 0.951056, 0.162460}, -{0.500000, 0.809017, 0.309017}, -{0.238856, 0.864188, -0.442863}, -{0.262866, 0.951056, -0.162460}, -{0.500000, 0.809017, -0.309017}, -{0.850651, 0.525731, 0.000000}, -{0.716567, 0.681718, 0.147621}, -{0.716567, 0.681718, -0.147621}, -{0.525731, 0.850651, 0.000000}, -{0.425325, 0.688191, 0.587785}, -{0.864188, 0.442863, 0.238856}, -{0.688191, 0.587785, 0.425325}, -{0.809017, 0.309017, 0.500000}, -{0.681718, 0.147621, 0.716567}, -{0.587785, 0.425325, 0.688191}, -{0.955423, 0.295242, 0.000000}, -{1.000000, 0.000000, 0.000000}, -{0.951056, 0.162460, 0.262866}, -{0.850651, -0.525731, 0.000000}, -{0.955423, -0.295242, 0.000000}, -{0.864188, -0.442863, 0.238856}, -{0.951056, -0.162460, 0.262866}, -{0.809017, -0.309017, 0.500000}, -{0.681718, -0.147621, 0.716567}, -{0.850651, 0.000000, 0.525731}, -{0.864188, 0.442863, -0.238856}, -{0.809017, 0.309017, -0.500000}, -{0.951056, 0.162460, -0.262866}, -{0.525731, 0.000000, -0.850651}, -{0.681718, 0.147621, -0.716567}, -{0.681718, -0.147621, -0.716567}, -{0.850651, 0.000000, -0.525731}, -{0.809017, -0.309017, -0.500000}, -{0.864188, -0.442863, -0.238856}, -{0.951056, -0.162460, -0.262866}, -{0.147621, 0.716567, -0.681718}, -{0.309017, 0.500000, -0.809017}, -{0.425325, 0.688191, -0.587785}, -{0.442863, 0.238856, -0.864188}, -{0.587785, 0.425325, -0.688191}, -{0.688191, 0.587785, -0.425325}, -{-0.147621, 0.716567, -0.681718}, -{-0.309017, 0.500000, -0.809017}, -{0.000000, 0.525731, -0.850651}, -{-0.525731, 0.000000, -0.850651}, -{-0.442863, 0.238856, -0.864188}, -{-0.295242, 0.000000, -0.955423}, -{-0.162460, 0.262866, -0.951056}, -{0.000000, 0.000000, -1.000000}, -{0.295242, 0.000000, -0.955423}, -{0.162460, 0.262866, -0.951056}, -{-0.442863, -0.238856, -0.864188}, -{-0.309017, -0.500000, -0.809017}, -{-0.162460, -0.262866, -0.951056}, -{0.000000, -0.850651, -0.525731}, -{-0.147621, -0.716567, -0.681718}, -{0.147621, -0.716567, -0.681718}, -{0.000000, -0.525731, -0.850651}, -{0.309017, -0.500000, -0.809017}, -{0.442863, -0.238856, -0.864188}, -{0.162460, -0.262866, -0.951056}, -{0.238856, -0.864188, -0.442863}, -{0.500000, -0.809017, -0.309017}, -{0.425325, -0.688191, -0.587785}, -{0.716567, -0.681718, -0.147621}, -{0.688191, -0.587785, -0.425325}, -{0.587785, -0.425325, -0.688191}, -{0.000000, -0.955423, -0.295242}, -{0.000000, -1.000000, 0.000000}, -{0.262866, -0.951056, -0.162460}, -{0.000000, -0.850651, 0.525731}, -{0.000000, -0.955423, 0.295242}, -{0.238856, -0.864188, 0.442863}, -{0.262866, -0.951056, 0.162460}, -{0.500000, -0.809017, 0.309017}, -{0.716567, -0.681718, 0.147621}, -{0.525731, -0.850651, 0.000000}, -{-0.238856, -0.864188, -0.442863}, -{-0.500000, -0.809017, -0.309017}, -{-0.262866, -0.951056, -0.162460}, -{-0.850651, -0.525731, 0.000000}, -{-0.716567, -0.681718, -0.147621}, -{-0.716567, -0.681718, 0.147621}, -{-0.525731, -0.850651, 0.000000}, -{-0.500000, -0.809017, 0.309017}, -{-0.238856, -0.864188, 0.442863}, -{-0.262866, -0.951056, 0.162460}, -{-0.864188, -0.442863, 0.238856}, -{-0.809017, -0.309017, 0.500000}, -{-0.688191, -0.587785, 0.425325}, -{-0.681718, -0.147621, 0.716567}, -{-0.442863, -0.238856, 0.864188}, -{-0.587785, -0.425325, 0.688191}, -{-0.309017, -0.500000, 0.809017}, -{-0.147621, -0.716567, 0.681718}, -{-0.425325, -0.688191, 0.587785}, -{-0.162460, -0.262866, 0.951056}, -{0.442863, -0.238856, 0.864188}, -{0.162460, -0.262866, 0.951056}, -{0.309017, -0.500000, 0.809017}, -{0.147621, -0.716567, 0.681718}, -{0.000000, -0.525731, 0.850651}, -{0.425325, -0.688191, 0.587785}, -{0.587785, -0.425325, 0.688191}, -{0.688191, -0.587785, 0.425325}, -{-0.955423, 0.295242, 0.000000}, -{-0.951056, 0.162460, 0.262866}, -{-1.000000, 0.000000, 0.000000}, -{-0.850651, 0.000000, 0.525731}, -{-0.955423, -0.295242, 0.000000}, -{-0.951056, -0.162460, 0.262866}, -{-0.864188, 0.442863, -0.238856}, -{-0.951056, 0.162460, -0.262866}, -{-0.809017, 0.309017, -0.500000}, -{-0.864188, -0.442863, -0.238856}, -{-0.951056, -0.162460, -0.262866}, -{-0.809017, -0.309017, -0.500000}, -{-0.681718, 0.147621, -0.716567}, -{-0.681718, -0.147621, -0.716567}, -{-0.850651, 0.000000, -0.525731}, -{-0.688191, 0.587785, -0.425325}, -{-0.587785, 0.425325, -0.688191}, -{-0.425325, 0.688191, -0.587785}, -{-0.425325, -0.688191, -0.587785}, -{-0.587785, -0.425325, -0.688191}, -{-0.688191, -0.587785, -0.425325}, diff --git a/chase.c b/chase.c index 21893960..9bab5473 100644 --- a/chase.c +++ b/chase.c @@ -53,13 +53,13 @@ float TraceLine (vec3_t start, vec3_t end, vec3_t impact, vec3_t normal) void Chase_Update (void) { - vec3_t forward, up, right, stop, chase_dest, normal; + vec3_t forward, stop, chase_dest, normal; float dist; chase_back.value = bound(0, chase_back.value, 128); chase_up.value = bound(-64, chase_up.value, 64); - AngleVectors (cl.viewangles, forward, right, up); + AngleVectors (cl.viewangles, forward, NULL, NULL); dist = -chase_back.value - 8; chase_dest[0] = r_refdef.vieworg[0] + forward[0] * dist; diff --git a/cl_demo.c b/cl_demo.c index 13fbed5b..85873db3 100644 --- a/cl_demo.c +++ b/cl_demo.c @@ -101,12 +101,12 @@ int CL_GetMessage (void) return 0; // decide if it is time to grab the next message - if (cls.signon == SIGNONS) // allways grab until fully connected + if (cls.signon == SIGNONS) // always grab until fully connected { if (cls.timedemo) { if (host_framecount == cls.td_lastframe) - return 0; // allready read this frame's message + return 0; // already read this frame's message cls.td_lastframe = host_framecount; // if this is the second frame, grab the real td_starttime // so the bogus time on the first frame doesn't count diff --git a/cl_input.c b/cl_input.c index f3432d22..21f084ff 100644 --- a/cl_input.c +++ b/cl_input.c @@ -253,9 +253,9 @@ void CL_AdjustAngles (void) float up, down; if (in_speed.state & 1) - speed = host_frametime * cl_anglespeedkey.value; + speed = cl.frametime * cl_anglespeedkey.value; else - speed = host_frametime; + speed = cl.frametime; if (!(in_strafe.state & 1)) { @@ -430,8 +430,7 @@ void CL_SendMove (usercmd_t *cmd) return; // -// allways dump the first two message, because it may contain leftover inputs -// from the last level +// always dump the first two messages, because they may contain leftover inputs from the last level // if (++cl.movemessages <= 2) return; diff --git a/cl_main.c b/cl_main.c index 1abbfd2f..7a6623a1 100644 --- a/cl_main.c +++ b/cl_main.c @@ -175,9 +175,6 @@ void CL_EstablishConnection (char *host) cls.signon = 0; // need all the signon messages before playing } -extern int numgltextures; -extern int texels; - /* ===================== CL_SignonReply @@ -224,8 +221,6 @@ Con_DPrintf ("CL_SignonReply: %i\n", cls.signon); case 4: SCR_EndLoadingPlaque (); // allow normal screen updates - // LordHavoc: debugging purposes - Con_DPrintf("Texture slots in use: %i : %i : %i texels\n", texture_extension_number, numgltextures, texels); break; } } @@ -280,8 +275,7 @@ void CL_PrintEntities_f (void) Con_Printf ("EMPTY\n"); continue; } - Con_Printf ("%s:%2i (%5.1f,%5.1f,%5.1f) [%5.1f %5.1f %5.1f]\n" - ,ent->model->name,ent->frame, ent->origin[0], ent->origin[1], ent->origin[2], ent->angles[0], ent->angles[1], ent->angles[2]); + Con_Printf ("%s:%2i (%5.1f,%5.1f,%5.1f) [%5.1f %5.1f %5.1f]\n", ent->model->name, ent->frame, ent->origin[0], ent->origin[1], ent->origin[2], ent->angles[0], ent->angles[1], ent->angles[2]); } } @@ -374,8 +368,9 @@ float CL_LerpPoint (void) float f, frac; f = cl.mtime[0] - cl.mtime[1]; - - if (!f || cl_nolerp.value || cls.timedemo || sv.active) + + // LordHavoc: lerp in listen games as the server is being capped below the client (usually) + if (!f || cl_nolerp.value || cls.timedemo || (sv.active && svs.maxclients == 1)) { cl.time = cl.mtime[0]; return 1; @@ -460,8 +455,8 @@ void CL_RelinkEntities (void) { if (!ent->model) { // empty slot - if (ent->forcelink) - R_RemoveEfrags (ent); // just became empty +// if (ent->forcelink) +// R_RemoveEfrags (ent); // just became empty continue; } @@ -470,30 +465,11 @@ void CL_RelinkEntities (void) { ent->model = NULL; // LordHavoc: free on the same frame, not the next - if (ent->forcelink) - R_RemoveEfrags (ent); // just became empty +// if (ent->forcelink) +// R_RemoveEfrags (ent); // just became empty continue; } - // LordHavoc: animation interpolation, note: framegroups partially override this in the renderer - /* - if (ent->model != ent->lerp_model || ent->lerp_time > cl.time) - { - ent->lerp_frame1 = ent->lerp_frame2 = ent->frame; - ent->lerp_time = cl.time; - ent->lerp = 0; - } - else if (ent->frame != ent->lerp_frame2) - { - ent->lerp_frame1 = ent->lerpframe2; - ent->lerp_frame2 = ent->frame; - ent->lerp_time = cl.time; - ent->lerp = 0; - } - else - ent->lerp = bound(0, (cl.time - ent->lerp_time) * 10.0f, 1); - */ - VectorCopy (ent->origin, oldorg); if (ent->forcelink) @@ -532,12 +508,12 @@ void CL_RelinkEntities (void) R_EntityParticles (ent); if (ent->effects & EF_MUZZLEFLASH) { - vec3_t fv, rv, uv; + vec3_t fv; dl = CL_AllocDlight (i); VectorCopy (ent->origin, dl->origin); dl->origin[2] += 16; - AngleVectors (ent->angles, fv, rv, uv); + AngleVectors (ent->angles, fv, NULL, NULL); VectorMA (dl->origin, 18, fv, dl->origin); dl->radius = 100 + (rand()&31); @@ -589,6 +565,25 @@ void CL_RelinkEntities (void) dl->die = cl.time + 0.001; dl->color[0] = 0.05;dl->color[1] = 0.05;dl->color[2] = 0.8; } + else if (ent->effects & EF_FLAME) + { + if (ent->model) + { + vec3_t mins, maxs; + int temp; + VectorAdd(ent->origin, ent->model->mins, mins); + VectorAdd(ent->origin, ent->model->maxs, maxs); + // how many flames to make + temp = (int) (cl.time * 30) - (int) (cl.oldtime * 30); + R_FlameCube(mins, maxs, temp); + } + dl = CL_AllocDlight (i); + VectorCopy (ent->origin, dl->origin); + dl->radius = 200 + (rand()&31); + dl->die = cl.time + 0.25; + dl->decay = dl->radius * 4; + dl->color[0] = 1.0;dl->color[1] = 0.7;dl->color[2] = 0.3; + } if (ent->model->flags) // LordHavoc: if the model has no flags, don't check each { @@ -643,10 +638,7 @@ void CL_RelinkEntities (void) if (!ent->model || ent->effects & EF_NODRAW) continue; if (cl_numvisedicts < MAX_VISEDICTS) - { - cl_visedicts[cl_numvisedicts] = ent; - cl_numvisedicts++; - } + cl_visedicts[cl_numvisedicts++] = ent; } } @@ -664,7 +656,7 @@ int CL_ReadFromServer (void) int ret; cl.oldtime = cl.time; - cl.time += host_frametime; + cl.time += cl.frametime; do { @@ -683,6 +675,7 @@ int CL_ReadFromServer (void) CL_RelinkEntities (); CL_UpdateTEnts (); + CL_DoEffects (); // // bring the links up to date @@ -712,7 +705,6 @@ void CL_SendCmd (void) // send the unreliable message CL_SendMove (&cmd); - } if (cls.demoplayback) diff --git a/cl_parse.c b/cl_parse.c index 0d776abf..368bf3da 100644 --- a/cl_parse.c +++ b/cl_parse.c @@ -65,24 +65,25 @@ char *svc_strings[128] = "svc_cdtrack", // [byte] track [byte] looptrack "svc_sellscreen", "svc_cutscene", - "svc_showlmp", // [string] iconlabel [string] lmpfile [byte] x [byte] y + "svc_showlmp", // [string] iconlabel [string] lmpfile [short] x [short] y "svc_hidelmp", // [string] iconlabel - "svc_skybox", // [string] skyname - "?", // 38 - "?", // 39 - "?", // 40 - "?", // 41 - "?", // 42 - "?", // 43 - "?", // 44 - "?", // 45 - "?", // 46 - "?", // 47 - "?", // 48 - "?", // 49 - "svc_farclip", // [coord] size - "svc_fog", // [byte] enable [short] density*4096 [byte] red [byte] green [byte] blue - "svc_playerposition" // [float] x [float] y [float] z + "", // 37 + "", // 38 + "", // 39 + "", // 40 + "", // 41 + "", // 42 + "", // 43 + "", // 44 + "", // 45 + "", // 46 + "", // 47 + "", // 48 + "", // 49 + "", // 50 + "svc_fog", // 51 + "svc_effect", // [vector] org [byte] modelindex [byte] startframe [byte] framecount [byte] framerate + "svc_effect2", // [vector] org [short] modelindex [byte] startframe [byte] framecount [byte] framerate }; //============================================================================= @@ -119,14 +120,14 @@ entity_t *CL_EntityNum (int num) CL_ParseStartSoundPacket ================== */ -void CL_ParseStartSoundPacket(void) +void CL_ParseStartSoundPacket(int largesoundindex) { vec3_t pos; int channel, ent; int sound_num; int volume; int field_mask; - float attenuation; + float attenuation; int i; field_mask = MSG_ReadByte(); @@ -142,7 +143,13 @@ void CL_ParseStartSoundPacket(void) attenuation = DEFAULT_SOUND_PACKET_ATTENUATION; channel = MSG_ReadShort (); - sound_num = MSG_ReadByte (); + if (largesoundindex) + sound_num = (unsigned short) MSG_ReadShort (); + else + sound_num = MSG_ReadByte (); + + if (sound_num >= MAX_SOUNDS) + Host_Error("CL_ParseStartSoundPacket: sound_num (%i) >= MAX_SOUNDS (%i)\n", sound_num, MAX_SOUNDS); ent = channel >> 3; channel &= 7; @@ -455,7 +462,7 @@ relinked. Other attributes can change without relinking. */ void CL_ParseUpdate (int bits) { - int i, modnum, num, alpha, scale, glowsize, glowcolor, colormod; + int i, modnum, num, alpha, scale, glowsize, glowcolor, colormod, frame; model_t *model; qboolean forcelink; entity_t *ent; @@ -511,21 +518,8 @@ void CL_ParseUpdate (int bits) modnum = bits & U_MODEL ? MSG_ReadByte() : baseline->modelindex; if (modnum >= MAX_MODELS) Host_Error ("CL_ParseModel: bad modnum"); - ent->deltabaseline.modelindex = modnum; - - model = cl.model_precache[modnum]; - if (model != ent->model) - { - ent->model = model; - // automatic animation (torches, etc) can be either all together - // or randomized - if (model) - ent->syncbase = model->synctype == ST_RAND ? (float)(rand()&0x7fff) / 0x7fff : 0.0; - else - forcelink = true; // hack to make null model players work - } - ent->frame = ((bits & U_FRAME) ? MSG_ReadByte() : (baseline->frame & 0xFF)); + frame = ((bits & U_FRAME) ? MSG_ReadByte() : (baseline->frame & 0xFF)); i = bits & U_COLORMAP ? MSG_ReadByte() : baseline->colormap; ent->deltabaseline.colormap = i; @@ -564,14 +558,36 @@ void CL_ParseUpdate (int bits) glowsize = bits & U_GLOWSIZE ? MSG_ReadByte() : baseline->glowsize; glowcolor = bits & U_GLOWCOLOR ? MSG_ReadByte() : baseline->glowcolor; colormod = bits & U_COLORMOD ? MSG_ReadByte() : baseline->colormod; - ent->frame |= ((bits & U_FRAME2) ? (MSG_ReadByte() << 8) : (baseline->frame & 0xFF00)); + modnum |= ((bits & U_MODEL2) ? (MSG_ReadByte() << 8) : (baseline->modelindex & 0xFF00)); + frame |= ((bits & U_FRAME2) ? (MSG_ReadByte() << 8) : (baseline->frame & 0xFF00)); + + if (modnum >= MAX_MODELS) + Host_Error("modnum (%i) >= MAX_MODELS (%i)\n", modnum, MAX_MODELS); + + model = cl.model_precache[modnum]; + if (model != ent->model) + { + ent->model = model; + // automatic animation (torches, etc) can be either all together + // or randomized + if (model) + ent->syncbase = model->synctype == ST_RAND ? (float)(rand()&0x7fff) / 0x7fff : 0.0; + else + forcelink = true; // hack to make null model players work + } + + ent->frame = frame; + if (model && (unsigned) frame >= model->numframes) + Con_DPrintf("CL_ParseUpdate: no such frame %i in \"%s\"\n", frame, model->name); + ent->deltabaseline.alpha = alpha; ent->deltabaseline.scale = scale; ent->deltabaseline.effects = ent->effects; ent->deltabaseline.glowsize = glowsize; ent->deltabaseline.glowcolor = glowcolor; ent->deltabaseline.colormod = colormod; - ent->deltabaseline.frame = ent->frame; + ent->deltabaseline.modelindex = modnum; + ent->deltabaseline.frame = frame; ent->alpha = (float) alpha * (1.0 / 255.0); ent->scale = (float) scale * (1.0 / 16.0); ent->glowsize = glowsize * 4.0; @@ -579,7 +595,7 @@ void CL_ParseUpdate (int bits) ent->colormod[0] = (float) ((colormod >> 5) & 7) * (1.0 / 7.0); ent->colormod[1] = (float) ((colormod >> 2) & 7) * (1.0 / 7.0); ent->colormod[2] = (float) (colormod & 3) * (1.0 / 3.0); - if (bits & U_EXTEND1 && Nehahrademcompatibility) // LordHavoc: to allow playback of the early Nehahra movie segments + if (bits & U_EXTEND1 && Nehahrademcompatibility) // LordHavoc: to allow playback of the Nehahra movie { i = MSG_ReadFloat(); ent->alpha = MSG_ReadFloat(); @@ -608,11 +624,14 @@ void CL_ParseUpdate (int bits) CL_ParseBaseline ================== */ -void CL_ParseBaseline (entity_t *ent) +void CL_ParseBaseline (entity_t *ent, int largemodelindex) { int i; - - ent->baseline.modelindex = MSG_ReadByte (); + + if (largemodelindex) + ent->baseline.modelindex = (unsigned short) MSG_ReadShort (); + else + ent->baseline.modelindex = MSG_ReadByte (); ent->baseline.frame = MSG_ReadByte (); ent->baseline.colormap = MSG_ReadByte(); ent->baseline.skin = MSG_ReadByte(); @@ -626,6 +645,9 @@ void CL_ParseBaseline (entity_t *ent) ent->baseline.glowsize = 0; ent->baseline.glowcolor = 254; ent->baseline.colormod = 255; + + if (ent->baseline.modelindex >= MAX_MODELS) + Host_Error("CL_ParseBaseline: modelindex (%i) >= MAX_MODELS (%i)\n", ent->baseline.modelindex, MAX_MODELS); } @@ -639,7 +661,13 @@ Server information pertaining to this client only void CL_ParseClientdata (int bits) { int i, j; - + + bits &= 0xFFFF; + if (bits & SU_EXTEND1) + bits |= (MSG_ReadByte() << 16); + if (bits & SU_EXTEND2) + bits |= (MSG_ReadByte() << 24); + if (bits & SU_VIEWHEIGHT) cl.viewheight = MSG_ReadChar (); else @@ -654,9 +682,18 @@ void CL_ParseClientdata (int bits) for (i=0 ; i<3 ; i++) { if (bits & (SU_PUNCH1<model = cl.model_precache[ent->baseline.modelindex]; - ent->frame = ent->baseline.frame; + ent->frame = ent->frame1 = ent->frame2 = ent->baseline.frame; + ent->framelerp = 0; + ent->lerp_starttime = -1; + // make torchs play out of sync + ent->frame1start = ent->frame2start = -(rand() & 32767); ent->colormap = -1; // no special coloring ent->skinnum = ent->baseline.skin; ent->effects = ent->baseline.effects; @@ -738,10 +779,8 @@ void CL_ParseStaticSound (void) { vec3_t org; int sound_num, vol, atten; - int i; - - for (i=0 ; i<3 ; i++) - org[i] = MSG_ReadCoord (); + + MSG_ReadVector(org); sound_num = MSG_ReadByte (); vol = MSG_ReadByte (); atten = MSG_ReadByte (); @@ -749,6 +788,34 @@ void CL_ParseStaticSound (void) S_StaticSound (cl.sound_precache[sound_num], org, vol, atten); } +void CL_ParseEffect (void) +{ + vec3_t org; + int modelindex, startframe, framecount, framerate; + + MSG_ReadVector(org); + modelindex = MSG_ReadByte (); + startframe = MSG_ReadByte (); + framecount = MSG_ReadByte (); + framerate = MSG_ReadByte (); + + CL_Effect(org, modelindex, startframe, framecount, framerate); +} + +void CL_ParseEffect2 (void) +{ + vec3_t org; + int modelindex, startframe, framecount, framerate; + + MSG_ReadVector(org); + modelindex = MSG_ReadShort (); + startframe = MSG_ReadByte (); + framecount = MSG_ReadByte (); + framerate = MSG_ReadByte (); + + CL_Effect(org, modelindex, startframe, framecount, framerate); +} + #define SHOWNET(x) if(cl_shownet.value==2)Con_Printf ("%3i:%s\n", msg_readcount-1, x); @@ -919,9 +986,13 @@ void CL_ParseServerMessage (void) break; case svc_sound: - CL_ParseStartSoundPacket(); + CL_ParseStartSoundPacket(false); break; - + + case svc_sound2: + CL_ParseStartSoundPacket(true); + break; + case svc_stopsound: i = MSG_ReadShort(); S_StopSound(i>>3, i&7); @@ -952,14 +1023,30 @@ void CL_ParseServerMessage (void) R_ParseParticleEffect (); break; + case svc_effect: + CL_ParseEffect (); + break; + + case svc_effect2: + CL_ParseEffect2 (); + break; + case svc_spawnbaseline: i = MSG_ReadShort (); // must use CL_EntityNum() to force cl.num_entities up - CL_ParseBaseline (CL_EntityNum(i)); + CL_ParseBaseline (CL_EntityNum(i), false); + break; + case svc_spawnbaseline2: + i = MSG_ReadShort (); + // must use CL_EntityNum() to force cl.num_entities up + CL_ParseBaseline (CL_EntityNum(i), false); break; case svc_spawnstatic: - CL_ParseStatic (); - break; + CL_ParseStatic (false); + break; + case svc_spawnstatic2: + CL_ParseStatic (true); + break; case svc_temp_entity: CL_ParseTEnt (); break; @@ -1037,24 +1124,6 @@ void CL_ParseServerMessage (void) case svc_showlmp: SHOWLMP_decodeshow(); break; - // LordHavoc: extra worldspawn fields (fog, sky, farclip) - case svc_skybox: - R_SetSkyBox(MSG_ReadString()); - break; - case svc_farclip: - r_farclip.value = MSG_ReadCoord(); - break; - case svc_fog: - if (MSG_ReadByte()) - { - fog_density = MSG_ReadShort() * (1.0f / 4096.0f); - fog_red = MSG_ReadByte() * (1.0 / 255.0); - fog_green = MSG_ReadByte() * (1.0 / 255.0); - fog_blue = MSG_ReadByte() * (1.0 / 255.0); - } - else - fog_density = 0.0f; - break; } } } diff --git a/cl_tent.c b/cl_tent.c index 518b1ef4..1046cbc6 100644 --- a/cl_tent.c +++ b/cl_tent.c @@ -21,8 +21,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "quakedef.h" -#define MSG_ReadVector(v) {(v)[0] = MSG_ReadCoord();(v)[1] = MSG_ReadCoord();(v)[2] = MSG_ReadCoord();} - cvar_t r_glowinglightning = {"r_glowinglightning", "1", true}; int num_temp_entities; @@ -242,11 +240,11 @@ void CL_ParseTEnt (void) dir[1] = MSG_ReadChar (); dir[2] = MSG_ReadChar (); count = MSG_ReadByte (); // amount of particles - R_BloodPuff(pos); + R_BloodPuff(pos, dir, count); break; case TE_BLOOD2: // blood puff MSG_ReadVector(pos); - R_BloodPuff(pos); + R_BloodPuff(pos, vec3_origin, 10); break; case TE_SPARK: // spark shower MSG_ReadVector(pos); @@ -398,6 +396,36 @@ void CL_ParseTEnt (void) S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1); break; + case TE_SMALLFLASH: + MSG_ReadVector(pos); + FindNonSolidLocation(pos); + dl = CL_AllocDlight (0); + VectorCopy (pos, dl->origin); + dl->radius = 200; + dl->die = cl.time + 0.2; + dl->decay = 1000; + dl->color[0] = dl->color[1] = dl->color[2] = 1; + break; + + case TE_CUSTOMFLASH: + MSG_ReadVector(pos); + FindNonSolidLocation(pos); + dl = CL_AllocDlight (0); + VectorCopy (pos, dl->origin); + dl->radius = MSG_ReadByte() * 8; + velspeed = (MSG_ReadByte() + 1) * (1.0 / 256.0); + dl->die = cl.time + velspeed; + dl->decay = dl->radius / velspeed; + dl->color[0] = MSG_ReadByte() * (1.0 / 255.0);dl->color[1] = MSG_ReadByte() * (1.0 / 255.0);dl->color[2] = MSG_ReadByte() * (1.0 / 255.0); + break; + + case TE_FLAMEJET: + MSG_ReadVector(pos); + MSG_ReadVector(dir); + count = MSG_ReadByte(); + R_Flames(pos, dir, count); + break; + case TE_LIGHTNING1: // lightning bolts CL_ParseBeam (Mod_ForName("progs/bolt.mdl", true)); break; @@ -467,15 +495,13 @@ entity_t *CL_NewTempEntity (void) { entity_t *ent; - if (cl_numvisedicts == MAX_VISEDICTS) + if (cl_numvisedicts >= MAX_VISEDICTS) return NULL; - if (num_temp_entities == MAX_TEMP_ENTITIES) + if (num_temp_entities >= MAX_TEMP_ENTITIES) return NULL; - ent = &cl_temp_entities[num_temp_entities]; + ent = &cl_temp_entities[num_temp_entities++]; memset (ent, 0, sizeof(*ent)); - num_temp_entities++; - cl_visedicts[cl_numvisedicts] = ent; - cl_numvisedicts++; + cl_visedicts[cl_numvisedicts++] = ent; ent->colormap = -1; // no special coloring ent->scale = 1; @@ -559,7 +585,7 @@ void CL_UpdateTEnts (void) VectorCopy (ent->origin, dl->origin); dl->radius = 100 + (rand()&31); dl->die = cl.time + 0.001; - dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 1; + dl->color[0] = dl->color[1] = dl->color[2] = r_glowinglightning.value * 0.25f; } VectorMA(org, 30, dist, org); diff --git a/client.h b/client.h index 44fbedf9..9abe25e2 100644 --- a/client.h +++ b/client.h @@ -161,6 +161,7 @@ typedef struct vec3_t velocity; // lerped between mvelocity[0] and [1] vec3_t punchangle; // temporary offset + vec3_t punchvector; // LordHavoc: origin view kick // pitch drifting vars float idealpitch; @@ -185,6 +186,8 @@ typedef struct // a lerp point for other data double oldtime; // previous cl.time, time-oldtime is used // to decay light values and smooth step ups + + double frametime; float last_received_message; // (realtime) for net trouble icon @@ -249,8 +252,9 @@ extern cvar_t m_forward; extern cvar_t m_side; -#define MAX_TEMP_ENTITIES 64 // lightning bolts, etc -#define MAX_STATIC_ENTITIES 128 // torches, etc +// LordHavoc: raised these from 64 and 128 to 512 and 256 +#define MAX_TEMP_ENTITIES 512 // lightning bolts, effects, etc +#define MAX_STATIC_ENTITIES 256 // torches, etc extern client_state_t cl; @@ -283,7 +287,8 @@ void CL_Disconnect (void); void CL_Disconnect_f (void); void CL_NextDemo (void); -#define MAX_VISEDICTS 256 +// LordHavoc: raised this from 256 to the maximum possible number of entities visible +#define MAX_VISEDICTS (MAX_EDICTS + MAX_STATIC_ENTITIES + MAX_TEMP_ENTITIES) extern int cl_numvisedicts; extern entity_t *cl_visedicts[MAX_VISEDICTS]; @@ -306,6 +311,11 @@ void CL_SendMove (usercmd_t *cmd); void CL_ParseTEnt (void); void CL_UpdateTEnts (void); +void CL_DoEffects (void); + +entity_t *CL_NewTempEntity (void); + +void CL_Effect(vec3_t org, int modelindex, int startframe, int framecount, float framerate); void CL_ClearState (void); diff --git a/cmd.c b/cmd.c index 6bb726f4..85cd55c1 100644 --- a/cmd.c +++ b/cmd.c @@ -360,7 +360,7 @@ void Cmd_Alias_f (void) return; } - // if the alias allready exists, reuse it + // if the alias already exists, reuse it for (a = cmd_alias ; a ; a=a->next) { if (!strcmp(s, a->name)) diff --git a/cmd.h b/cmd.h index f9eab24e..da1daa65 100644 --- a/cmd.h +++ b/cmd.h @@ -96,7 +96,7 @@ char *Cmd_Argv (int arg); char *Cmd_Args (void); // The functions that execute commands get their parameters with these // functions. Cmd_Argv () will return an empty string, not a NULL -// if arg > argc, so string operations are allways safe. +// if arg > argc, so string operations are always safe. int Cmd_CheckParm (char *parm); // Returns the position (1 to argc-1) in the command's argument list diff --git a/common.c b/common.c index 1430e057..cc4bfd8b 100644 --- a/common.c +++ b/common.c @@ -1383,6 +1383,30 @@ void COM_Path_f (void) } } +/* +============ +COM_CreatePath + +LordHavoc: Previously only used for CopyFile, now also used for COM_WriteFile. +============ +*/ +void COM_CreatePath (char *path) +{ + char *ofs, save; + + for (ofs = path+1 ; *ofs ; ofs++) + { + if (*ofs == '/' || *ofs == '\\' || *ofs == ':') + { // create the directory + save = *ofs; + *ofs = 0; + Sys_mkdir (path); + *ofs = save; + } + } +} + + /* ============ COM_WriteFile @@ -1397,6 +1421,9 @@ void COM_WriteFile (char *filename, void *data, int len) sprintf (name, "%s/%s", com_gamedir, filename); + // LordHavoc: added this + COM_CreatePath (name); // create directories up to the file + handle = Sys_FileOpenWrite (name); if (handle == -1) { @@ -1410,29 +1437,6 @@ void COM_WriteFile (char *filename, void *data, int len) } -/* -============ -COM_CreatePath - -Only used for CopyFile -============ -*/ -void COM_CreatePath (char *path) -{ - char *ofs; - - for (ofs = path+1 ; *ofs ; ofs++) - { - if (*ofs == '/') - { // create the directory - *ofs = 0; - Sys_mkdir (path); - *ofs = '/'; - } - } -} - - /* =========== COM_CopyFile @@ -1639,7 +1643,7 @@ void COM_CloseFile (int h) COM_LoadFile Filename are reletive to the quake directory. -Allways appends a 0 byte. +Always appends a 0 byte. ============ */ cache_user_t *loadcache; diff --git a/common.h b/common.h index a9dad19e..502f4cdb 100644 --- a/common.h +++ b/common.h @@ -146,6 +146,8 @@ float MSG_ReadCoord (void); #define MSG_ReadAngle() (MSG_ReadByte() * (360.0f / 256.0f)) #define MSG_ReadPreciseAngle() (MSG_ReadShort() * (360.0f / 65536.0f)) +#define MSG_ReadVector(v) {(v)[0] = MSG_ReadCoord();(v)[1] = MSG_ReadCoord();(v)[2] = MSG_ReadCoord();} + extern qboolean dpprotocol; //============================================================================ diff --git a/cpu_noasm.c b/cpu_noasm.c deleted file mode 100644 index 7c5f8efd..00000000 --- a/cpu_noasm.c +++ /dev/null @@ -1,67 +0,0 @@ - -#include "quakedef.h" - -/* -=============== -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"); - - node = model->nodes; - if (node->contents < 0) - return (mleaf_t *)node; - while (1) - { - node = node->children[(node->plane->type < 3 ? p[node->plane->type] : DotProduct (p,node->plane->normal)) < node->plane->dist]; - if (node->contents < 0) - return (mleaf_t *)node; - } - - return NULL; // never reached -} -/* -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"); - - node = model->nodes; - while (1) - { - if (node->contents < 0) - return (mleaf_t *)node; - plane = node->plane; - d = DotProduct (p,plane->normal) - plane->dist; - if (d > 0) - node = node->children[0]; - else - node = node->children[1]; - } - - return NULL; // never reached -} -*/ - -/* -================== -SV_HullPointContents - -================== -*/ -int SV_HullPointContents (hull_t *hull, int num, vec3_t p) -{ - while (num >= 0) - num = hull->clipnodes[num].children[(hull->planes[hull->clipnodes[num].planenum].type < 3 ? p[hull->planes[hull->clipnodes[num].planenum].type] : DotProduct (hull->planes[hull->clipnodes[num].planenum].normal, p)) < hull->planes[hull->clipnodes[num].planenum].dist]; - - return num; -} diff --git a/cpu_x86.bat b/cpu_x86.bat deleted file mode 100644 index 26e5a5a1..00000000 --- a/cpu_x86.bat +++ /dev/null @@ -1 +0,0 @@ -nasmw -fwin32 cpu_x86.nasm diff --git a/cpu_x86.nasm b/cpu_x86.nasm deleted file mode 100644 index 4ab98755..00000000 --- a/cpu_x86.nasm +++ /dev/null @@ -1,198 +0,0 @@ - BITS 32 - GLOBAL _Mod_PointInLeaf - GLOBAL _SV_HullPointContents - SECTION .text -_Mod_PointInLeaf - -;{ - - mov eax, dword [esp+12-4] ; model - sub esp, 4 - push ebx - push esi - -; mnode_t *node; -; node = model->nodes; - - mov esi, dword [eax+200] ; model->nodes - -; if (node->contents < 0) - - cmp dword [esi], 0 ; node->contents - jge .firstvalid - -; return (mleaf_t *)node; - - mov eax, esi - pop esi - pop ebx - add esp, 4 - ret 0 -.firstvalid - mov edx, dword [esp+8+8] ; p -.loop - -; while (1) - - xor ecx, ecx - mov eax, dword [esi+76] ; node->plane - mov cl, byte [eax+16] ; node->plane->type - -; { -; node = node->children[(node->plane->type < 3 ? p[node->plane->type] : DotProduct (p,node->plane->normal)) < node->plane->dist]; - - cmp cl, 3 - jb .axisplane - fld dword [eax+4] ; node->plane->normal[1] - fmul dword [edx+4] ; p[1] - fld dword [eax+8] ; node->plane->normal[2] - fmul dword [edx+8] ; p[2] - fld dword [eax] ; node->plane->normal[0] - fmul dword [edx] ; p[0] - faddp st1, st0 - faddp st1, st0 - fld dword [eax+12] ; node->plane->dist - fcompp - fnstsw ax - test ah, 65 ; 00000041H - sete cl - mov esi, dword [esi+ecx*4+80] ; node = node->children[condition] - -; if (node->contents < 0) - - cmp dword [esi], 0 - jge .loop - -; return (mleaf_t *)node; - - mov eax, esi - -; } -; return NULL; // never reached -;} - - pop esi - pop ebx - add esp, 4 - ret 0 -.axisplane: - fld dword [edx+ecx*4] - fld dword [eax+12] - fcompp - fnstsw ax - test ah, 65 ; 00000041H - sete cl - mov esi, dword [esi+ecx*4+80] ; node = node->children[condition] - -; if (node->contents < 0) - - cmp dword [esi], 0 - jge .loop - -; return (mleaf_t *)node; - - mov eax, esi - -; } -; return NULL; // never reached -;} - - pop esi - pop ebx - add esp, 4 - ret 0 - - -_SV_HullPointContents - -;{ - mov ecx, [esp+12-4] ; num - sub esp, 4 - test ecx, ecx - nop ; padding - push ebx - push esi - push edi - push ebp - -; while (num >= 0) - - jge .firstvalid -; return num; - mov eax, ecx - pop ebp -;} - pop edi - pop esi - pop ebx - add esp, 4 - ret 0 -.firstvalid - mov eax, [esp+8+16] ; hull - mov edx, [esp+16+16] ; p - mov esi, [eax] - mov edi, [eax+4] -.loop - mov eax, [esi+ecx*8] - lea ebx, [eax+eax*2] - xor eax, eax - mov al, [edi+ebx*8+16] - lea ebp, [edi+ebx*8] - -; num = hull->clipnodes[num].children[(hull->planes[hull->clipnodes[num].planenum].type < 3 ? p[hull->planes[hull->clipnodes[num].planenum].type] : DotProduct (hull->planes[hull->clipnodes[num].planenum].normal, p)) < hull->planes[hull->clipnodes[num].planenum].dist]; - - cmp al, 3 - jb .axisplane - fld dword [edx+8] - fmul dword [ebp+8] - fld dword [edx+4] - fmul dword [ebp+4] - fld dword [edx] - fmul dword [ebp] - faddp st1, st0 - faddp st1, st0 - fstp dword [esp-4+20] - - fld dword [ebp+12] - fcomp dword [esp-4+20] - xor ebx, ebx - fnstsw ax - test ah, 65 ; 00000041H - sete bl - lea eax, [ebx+ecx*4] - movsx ecx, word [esi+eax*2+4] - test ecx, ecx - jge .loop -; return num; - mov eax, ecx - pop ebp -;} - pop edi - pop esi - pop ebx - add esp, 4 - ret 0 - -.axisplane - mov eax, [edx+eax*4] - mov [esp-4+20], eax - - fld dword [ebp+12] - fcomp dword [esp-4+20] - xor ebx, ebx - fnstsw ax - test ah, 65 ; 00000041H - sete bl - lea eax, [ebx+ecx*4] - movsx ecx, word [esi+eax*2+4] - test ecx, ecx - jge .loop -; return num; - mov eax, ecx - pop ebp -;} - pop edi - pop esi - pop ebx - add esp, 4 - ret 0 diff --git a/cpu_x86.obj b/cpu_x86.obj deleted file mode 100644 index 3c138636d61e81c160b642abe0b879010fec5bc4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 847 zcmeZaWMq)_zGpd+k%57i0Rr?&QY%WJY!DR+l(PZSAT=f;8V0g0I&8N#lpy4NTk=0EHmK$CyHyt=`cyZih zxWRSr;Jt%49eD2Dy#L_a5l8+h2fIu90-#16Low4q-@*p)FV0ykZGZU8C6+fdgY?q%ub-|yqb(t5IXJGvz-O`R_IwX~pV(M!wBNd<)> z5d8bkz>vTcVPU41msp$&5l4<7P@FI`f}#i&=p`l<=jW7yaIC`v#8 zq?`%N5(Sd#P!Wh4Lm*EZMZ_J*D?$-T0`g`0C{^+)XW6(PN9fw0rHf9R)gKl za0SSV_svg<56I8VEAhbegURvVnt?gK~7>`Dnop5 iSiDDRP7c@t=lr~q)Vz{n?4l_4VAG}tu?(ve!bSk8!SBKV diff --git a/cvar.c b/cvar.c index db48c0c2..bb680158 100644 --- a/cvar.c +++ b/cvar.c @@ -153,7 +153,7 @@ void Cvar_RegisterVariable (cvar_t *variable) { char *oldstr; -// first check to see if it has allready been defined +// first check to see if it has already been defined if (Cvar_FindVar (variable->name)) { Con_Printf ("Can't register variable %s, already defined\n", variable->name); diff --git a/cvar.h b/cvar.h index 009b7478..4a961b20 100644 --- a/cvar.h +++ b/cvar.h @@ -64,7 +64,7 @@ typedef struct cvar_s } cvar_t; void Cvar_RegisterVariable (cvar_t *variable); -// registers a cvar that allready has the name, string, and optionally the +// registers a cvar that already has the name, string, and optionally the // archive elements set. void Cvar_Set (char *var_name, char *value); diff --git a/draw.h b/draw.h index 322c9b8f..267b9e92 100644 --- a/draw.h +++ b/draw.h @@ -25,7 +25,7 @@ extern qpic_t *draw_disc; // also used on sbar void Draw_Init (void); void Draw_Character (int x, int y, int num); -void Draw_GenericPic (int texnum, float red, float green, float blue, float alpha, int x, int y, int width, int height); +void Draw_GenericPic (rtexture_t *tex, float red, float green, float blue, float alpha, int x, int y, int width, int height); void Draw_Pic (int x, int y, qpic_t *pic); void Draw_PicTranslate (int x, int y, qpic_t *pic, byte *translation); void Draw_ConsoleBackground (int lines); diff --git a/fractalnoise.c b/fractalnoise.c index e9899a47..93622b14 100644 --- a/fractalnoise.c +++ b/fractalnoise.c @@ -1,48 +1,50 @@ #include "quakedef.h" -void fractalnoise(unsigned char *noise, int size, int startgrid) +void fractalnoise(byte *noise, int size, int startgrid) { - int x, y, g, g2, amplitude, min, max, size1 = size - 1; + int x, y, g, g2, amplitude, min, max, size1 = size - 1, sizepower, gridpower; int *noisebuf; #define n(x,y) noisebuf[((y)&size1)*size+((x)&size1)] - if (startgrid > size) - startgrid = size; + + for (sizepower = 0;(1 << sizepower) < size;sizepower++); + if (size != (1 << sizepower)) + Sys_Error("fractalnoise: size must be power of 2\n"); + + for (gridpower = 0;(1 << gridpower) < startgrid;gridpower++); + if (startgrid != (1 << gridpower)) + Sys_Error("fractalnoise: grid must be power of 2\n"); + + startgrid = bound(0, startgrid, size); + + amplitude = 32767; noisebuf = qmalloc(size*size*sizeof(int)); memset(noisebuf, 0, size*size*sizeof(int)); - amplitude = 32767; - // quick 1x1 case which the rest of the code can't handle - if (startgrid < 2) - { - for (x = 0;x < size*size;x++) - *noise++ = (rand()&255); - return; - } - g2 = startgrid; - // clear the starting grid (the rest does not need to be cleared, it will simply be overwritten) - for (y = 0;y < size;y += g2) - for (x = 0;x < size;x += g2) - n(x,y) = 0; - for (;(g = g2 >> 1) >= 1;g2 >>= 1) + for (g2 = startgrid;g2;g2 >>= 1) { - // subdivide, diamond-square algorythm (really this has little to do with squares) - // diamond - for (y = 0;y < size;y += g2) - for (x = 0;x < size;x += g2) - n(x+g,y+g) = (n(x,y) + n(x+g2,y) + n(x,y+g2) + n(x+g2,y+g2)) >> 2; - // square + // brownian motion (at every smaller level there is random behavior) + amplitude >>= 1; for (y = 0;y < size;y += g2) for (x = 0;x < size;x += g2) - { - n(x+g,y) = (n(x,y) + n(x+g2,y) + n(x+g,y-g) + n(x+g,y+g)) >> 2; - n(x,y+g) = (n(x,y) + n(x,y+g2) + n(x-g,y+g) + n(x+g,y+g)) >> 2; - } - // brownian motion theory - amplitude >>= 1; - for (y = 0;y < size;y += g) - for (x = 0;x < size;x += g) n(x,y) += (rand()&litude); + + g = g2 >> 1; + if (g) + { + // subdivide, diamond-square algorythm (really this has little to do with squares) + // diamond + for (y = 0;y < size;y += g2) + for (x = 0;x < size;x += g2) + n(x+g,y+g) = (n(x,y) + n(x+g2,y) + n(x,y+g2) + n(x+g2,y+g2)) >> 2; + // square + for (y = 0;y < size;y += g2) + for (x = 0;x < size;x += g2) + { + n(x+g,y) = (n(x,y) + n(x+g2,y) + n(x+g,y-g) + n(x+g,y+g)) >> 2; + n(x,y+g) = (n(x,y) + n(x,y+g2) + n(x-g,y+g) + n(x+g,y+g)) >> 2; + } + } } // find range of noise values min = max = 0; @@ -59,4 +61,4 @@ void fractalnoise(unsigned char *noise, int size, int startgrid) *noise++ = (n(x,y) - min) * 255 / max; qfree(noisebuf); #undef n -} \ No newline at end of file +} diff --git a/gl_draw.c b/gl_draw.c index 5a1e715a..f2c94651 100644 --- a/gl_draw.c +++ b/gl_draw.c @@ -25,20 +25,19 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. //#define GL_COLOR_INDEX8_EXT 0x80E5 -cvar_t qsg_version = {"qsg_version", "1"}; cvar_t scr_conalpha = {"scr_conalpha", "1"}; byte *draw_chars; // 8*8 graphic characters qpic_t *draw_disc; -int char_texture; +rtexture_t *char_texture; typedef struct { - int texnum; + rtexture_t *tex; } glpic_t; -int conbacktexnum; +rtexture_t *conbacktex; //============================================================================= /* Support Routines */ @@ -67,7 +66,7 @@ qpic_t *Draw_PicFromWad (char *name) p = W_GetLumpName (name); gl = (glpic_t *)p->data; - gl->texnum = GL_LoadTexture (name, p->width, p->height, p->data, false, true, 1); + gl->tex = R_LoadTexture (name, p->width, p->height, p->data, TEXF_ALPHA | TEXF_PRECACHE); return p; } @@ -111,9 +110,9 @@ qpic_t *Draw_CachePic (char *path) pic->pic.height = dat->height; gl = (glpic_t *)pic->pic.data; - gl->texnum = loadtextureimage(path, 0, 0, false, false); - if (!gl->texnum) - gl->texnum = GL_LoadTexture (path, dat->width, dat->height, dat->data, false, true, 1); + gl->tex = loadtextureimage(path, 0, 0, false, false, true); + if (!gl->tex) + gl->tex = R_LoadTexture (path, dat->width, dat->height, dat->data, TEXF_ALPHA | TEXF_PRECACHE); qfree(dat); @@ -133,7 +132,7 @@ void gl_draw_start() { int i; - char_texture = loadtextureimage ("conchars", 0, 0, false, false); + char_texture = loadtextureimage ("conchars", 0, 0, false, false, true); if (!char_texture) { draw_chars = W_GetLumpName ("conchars"); @@ -142,10 +141,10 @@ void gl_draw_start() draw_chars[i] = 255; // proper transparent color // now turn them into textures - char_texture = GL_LoadTexture ("charset", 128, 128, draw_chars, false, true, 1); + char_texture = R_LoadTexture ("charset", 128, 128, draw_chars, TEXF_ALPHA | TEXF_PRECACHE); } - conbacktexnum = loadtextureimage("gfx/conback", 0, 0, false, false); + conbacktex = loadtextureimage("gfx/conback", 0, 0, false, false, true); // get the other pics we need draw_disc = Draw_PicFromWad ("disc"); @@ -158,11 +157,10 @@ void gl_draw_shutdown() char engineversion[40]; int engineversionx, engineversiony; -extern void GL_Textures_Init(); +extern void R_Textures_Init(); void GL_Draw_Init (void) { int i; - Cvar_RegisterVariable (&qsg_version); Cvar_RegisterVariable (&scr_conalpha); Cmd_AddCommand ("loadsky", &LoadSky_f); @@ -179,7 +177,7 @@ void GL_Draw_Init (void) engineversionx = vid.width - strlen(engineversion) * 8 - 8; engineversiony = vid.height - 8; - GL_Textures_Init(); + R_Textures_Init(); R_RegisterModule("GL_Draw", gl_draw_start, gl_draw_shutdown); } @@ -214,13 +212,18 @@ void Draw_Character (int x, int y, int num) if (!r_render.value) return; - glBindTexture(GL_TEXTURE_2D, char_texture); + glBindTexture(GL_TEXTURE_2D, R_GetTexture(char_texture)); // LordHavoc: NEAREST mode on text if not scaling up - if (glwidth < (int) vid.width) + if (glwidth <= (int) vid.width) { glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); } + else + { + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + } glColor3f(1,1,1); glBegin (GL_QUADS); @@ -235,11 +238,11 @@ void Draw_Character (int x, int y, int num) glEnd (); // LordHavoc: revert to LINEAR mode - if (glwidth < (int) vid.width) - { - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - } +// if (glwidth < (int) vid.width) +// { +// glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); +// glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); +// } } /* @@ -260,14 +263,19 @@ void Draw_String (int x, int y, char *str, int maxlen) maxlen = strlen(str); else if (maxlen > (int) strlen(str)) maxlen = strlen(str); - glBindTexture(GL_TEXTURE_2D, char_texture); + glBindTexture(GL_TEXTURE_2D, R_GetTexture(char_texture)); // LordHavoc: NEAREST mode on text if not scaling up - if (glwidth < (int) vid.width) + if (glwidth <= (int) vid.width) { glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); } + else + { + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + } glColor3f(1,1,1); glBegin (GL_QUADS); @@ -287,19 +295,19 @@ void Draw_String (int x, int y, char *str, int maxlen) glEnd (); // LordHavoc: revert to LINEAR mode - if (glwidth < (int) vid.width) - { - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - } +// if (glwidth < (int) vid.width) +// { +// glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); +// glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); +// } } -void Draw_GenericPic (int texnum, float red, float green, float blue, float alpha, int x, int y, int width, int height) +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) return; glColor4f(red,green,blue,alpha); - glBindTexture(GL_TEXTURE_2D, texnum); + glBindTexture(GL_TEXTURE_2D, R_GetTexture(tex)); glBegin (GL_QUADS); glTexCoord2f (0, 0);glVertex2f (x, y); glTexCoord2f (1, 0);glVertex2f (x+width, y); @@ -315,7 +323,7 @@ Draw_AlphaPic */ void Draw_AlphaPic (int x, int y, qpic_t *pic, float alpha) { - Draw_GenericPic(((glpic_t *)pic->data)->texnum, 1,1,1,alpha, x,y,pic->width, pic->height); + Draw_GenericPic(((glpic_t *)pic->data)->tex, 1,1,1,alpha, x,y,pic->width, pic->height); } @@ -326,7 +334,7 @@ Draw_Pic */ void Draw_Pic (int x, int y, qpic_t *pic) { - Draw_GenericPic(((glpic_t *)pic->data)->texnum, 1,1,1,1, x,y,pic->width, pic->height); + Draw_GenericPic(((glpic_t *)pic->data)->tex, 1,1,1,1, x,y,pic->width, pic->height); } @@ -341,6 +349,7 @@ void Draw_PicTranslate (int x, int y, qpic_t *pic, byte *translation) { int i, c; byte *trans, *src, *dest; + rtexture_t *rt; c = pic->width * pic->height; src = menuplyr_pixels; @@ -348,12 +357,12 @@ void Draw_PicTranslate (int x, int y, qpic_t *pic, byte *translation) for (i = 0;i < c;i++) *dest++ = translation[*src++]; - c = GL_LoadTexture ("translatedplayerpic", pic->width, pic->height, trans, false, true, 1); + rt = R_LoadTexture ("translatedplayerpic", pic->width, pic->height, trans, TEXF_ALPHA | TEXF_PRECACHE); qfree(trans); if (!r_render.value) return; - Draw_GenericPic (c, 1,1,1,1, x, y, pic->width, pic->height); + Draw_GenericPic (rt, 1,1,1,1, x, y, pic->width, pic->height); } @@ -365,7 +374,7 @@ Draw_ConsoleBackground */ void Draw_ConsoleBackground (int lines) { - Draw_GenericPic (conbacktexnum, 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.height, 0, lines - vid.height, vid.width, vid.height); // LordHavoc: draw version Draw_String(engineversionx, lines - vid.height + engineversiony, engineversion, 9999); } @@ -465,8 +474,16 @@ void SHOWLMP_decodeshow() float x, y; strcpy(lmplabel,MSG_ReadString()); strcpy(picname, MSG_ReadString()); - x = MSG_ReadByte(); - y = MSG_ReadByte(); + if (nehahra) // LordHavoc: nasty old legacy junk + { + x = MSG_ReadByte(); + y = MSG_ReadByte(); + } + else + { + x = MSG_ReadShort(); + y = MSG_ReadShort(); + } k = -1; for (i = 0;i < SHOWLMP_MAXLABELS;i++) if (showlmp[i].isactive) diff --git a/gl_models.c b/gl_models.c index 42b68fcd..99e71140 100644 --- a/gl_models.c +++ b/gl_models.c @@ -1,6 +1,9 @@ #include "quakedef.h" +cvar_t gl_transform = {"gl_transform", "1"}; +cvar_t gl_lockarrays = {"gl_lockarrays", "1"}; + typedef struct { float m[3][4]; @@ -8,14 +11,46 @@ typedef struct // LordHavoc: vertex array float *aliasvert; -float *modelaliasvert; float *aliasvertnorm; byte *aliasvertcolor; byte *aliasvertcolor2; zymbonematrix *zymbonepose; int *aliasvertusage; -int chrometexture; +rtexture_t *chrometexture; + +int arraylocked = false; +void GL_LockArray(int first, int count) +{ + if (gl_supportslockarrays && gl_lockarrays.value) + { + qglLockArraysEXT(first, count); + arraylocked = true; + } +} + +void GL_UnlockArray() +{ + if (arraylocked) + { + qglUnlockArraysEXT(); + arraylocked = false; + } +} + +void GL_SetupModelTransform (vec3_t origin, vec3_t angles, vec_t scale) +{ + glTranslatef (origin[0], origin[1], origin[2]); + + if (scale != 1) + glScalef (scale, scale, scale); + if (angles[1]) + glRotatef (angles[1], 0, 0, 1); + if (angles[0]) + glRotatef (-angles[0], 0, 1, 0); + if (angles[2]) + glRotatef (angles[2], 1, 0, 0); +} void makechrometexture() { @@ -23,7 +58,7 @@ void makechrometexture() byte noise[64*64]; byte data[64*64][4]; - fractalnoise(noise, 64, 16); + fractalnoise(noise, 64, 8); // convert to RGBA data for (i = 0;i < 64*64;i++) @@ -32,14 +67,13 @@ void makechrometexture() data[i][3] = 255; } - chrometexture = GL_LoadTexture ("chrometexture", 64, 64, &data[0][0], true, false, 4); + chrometexture = R_LoadTexture ("chrometexture", 64, 64, &data[0][0], TEXF_MIPMAP | TEXF_RGBA | TEXF_PRECACHE); } void gl_models_start() { // allocate vertex processing arrays aliasvert = qmalloc(sizeof(float[MD2MAX_VERTS][3])); - modelaliasvert = qmalloc(sizeof(float[MD2MAX_VERTS][3])); aliasvertnorm = qmalloc(sizeof(float[MD2MAX_VERTS][3])); aliasvertcolor = qmalloc(sizeof(byte[MD2MAX_VERTS][4])); aliasvertcolor2 = qmalloc(sizeof(byte[MD2MAX_VERTS][4])); // used temporarily for tinted coloring @@ -60,6 +94,9 @@ void gl_models_shutdown() void GL_Models_Init() { + Cvar_RegisterVariable(&gl_transform); + Cvar_RegisterVariable(&gl_lockarrays); + R_RegisterModule("GL_Models", gl_models_start, gl_models_shutdown); } @@ -68,74 +105,121 @@ extern vec3_t softwaretransform_y; extern vec3_t softwaretransform_z; extern vec_t softwaretransform_scale; extern vec3_t softwaretransform_offset; -extern cvar_t r_modelsdonttransformnormals; -void R_AliasLerpVerts(int vertcount, float lerp, trivert2 *verts1, vec3_t scale1, vec3_t translate1, trivert2 *verts2, vec3_t scale2, vec3_t translate2) +void R_AliasTransformVerts(int vertcount) { int i; vec3_t point, matrix_x, matrix_y, matrix_z; float *av, *avn; av = aliasvert; avn = aliasvertnorm; - VectorScale(softwaretransform_x, softwaretransform_scale, matrix_x); - VectorScale(softwaretransform_y, softwaretransform_scale, matrix_y); - VectorScale(softwaretransform_z, softwaretransform_scale, matrix_z); - if (lerp < 0) lerp = 0; - if (lerp > 1) lerp = 1; - if (lerp != 0) + matrix_x[0] = softwaretransform_x[0] * softwaretransform_scale; + matrix_x[1] = softwaretransform_y[0] * softwaretransform_scale; + matrix_x[2] = softwaretransform_z[0] * softwaretransform_scale; + matrix_y[0] = softwaretransform_x[1] * softwaretransform_scale; + matrix_y[1] = softwaretransform_y[1] * softwaretransform_scale; + matrix_y[2] = softwaretransform_z[1] * softwaretransform_scale; + matrix_z[0] = softwaretransform_x[2] * softwaretransform_scale; + matrix_z[1] = softwaretransform_y[2] * softwaretransform_scale; + matrix_z[2] = softwaretransform_z[2] * softwaretransform_scale; + for (i = 0;i < vertcount;i++) + { + // rotate, scale, and translate the vertex locations + VectorCopy(av, point); + av[0] = DotProduct(point, matrix_x) + softwaretransform_offset[0]; + av[1] = DotProduct(point, matrix_y) + softwaretransform_offset[1]; + av[2] = DotProduct(point, matrix_z) + softwaretransform_offset[2]; + // rotate the normals + VectorCopy(avn, point); + avn[0] = point[0] * softwaretransform_x[0] + point[1] * softwaretransform_y[0] + point[2] * softwaretransform_z[0]; + avn[1] = point[0] * softwaretransform_x[1] + point[1] * softwaretransform_y[1] + point[2] * softwaretransform_z[1]; + avn[2] = point[0] * softwaretransform_x[2] + point[1] * softwaretransform_y[2] + point[2] * softwaretransform_z[2]; + av += 3; + avn += 3; + } +} + +void R_AliasLerpVerts(int vertcount, + float lerp1, trivertx_t *verts1, vec3_t fscale1, vec3_t translate1, + float lerp2, trivertx_t *verts2, vec3_t fscale2, vec3_t translate2, + float lerp3, trivertx_t *verts3, vec3_t fscale3, vec3_t translate3, + float lerp4, trivertx_t *verts4, vec3_t fscale4, vec3_t translate4) +{ + int i; + vec3_t scale1, scale2, scale3, scale4, translate; + float *n1, *n2, *n3, *n4; + float *av, *avn; + av = aliasvert; + avn = aliasvertnorm; + VectorScaleQuick(fscale1, lerp1, scale1); + if (lerp2) { - float ilerp, ilerp127, lerp127, scalex1, scalex2, translatex, scaley1, scaley2, translatey, scalez1, scalez2, translatez; - ilerp = 1 - lerp; - ilerp127 = ilerp * (1.0 / 127.0); - lerp127 = lerp * (1.0 / 127.0); - // calculate combined interpolation variables - scalex1 = scale1[0] * ilerp;scalex2 = scale2[0] * lerp;translatex = translate1[0] * ilerp + translate2[0] * lerp; - scaley1 = scale1[1] * ilerp;scaley2 = scale2[1] * lerp;translatey = translate1[1] * ilerp + translate2[1] * lerp; - scalez1 = scale1[2] * ilerp;scalez2 = scale2[2] * lerp;translatez = translate1[2] * ilerp + translate2[2] * lerp; - // generate vertices - if (r_modelsdonttransformnormals.value) + VectorScaleQuick(fscale2, lerp2, scale2); + if (lerp3) { - float *modelav = modelaliasvert; - for (i = 0;i < vertcount;i++) + VectorScaleQuick(fscale3, lerp3, scale3); + if (lerp4) { - // rotate, scale, and translate the vertex locations - point[0] = verts1->v[0] * scalex1 + verts2->v[0] * scalex2 + translatex; - point[1] = verts1->v[1] * scaley1 + verts2->v[1] * scaley2 + translatey; - point[2] = verts1->v[2] * scalez1 + verts2->v[2] * scalez2 + translatez; - // save mostly un-transformed copy for lighting - modelav[0] = point[0] * softwaretransform_scale; - modelav[1] = point[1] * softwaretransform_scale; - modelav[2] = point[2] * softwaretransform_scale; - av[0] = point[0] * matrix_x[0] + point[1] * matrix_y[0] + point[2] * matrix_z[0] + softwaretransform_offset[0]; - av[1] = point[0] * matrix_x[1] + point[1] * matrix_y[1] + point[2] * matrix_z[1] + softwaretransform_offset[1]; - av[2] = point[0] * matrix_x[2] + point[1] * matrix_y[2] + point[2] * matrix_z[2] + softwaretransform_offset[2]; - // decompress but do not transform the normals - avn[0] = verts1->n[0] * ilerp127 + verts2->n[0] * lerp127; - avn[1] = verts1->n[1] * ilerp127 + verts2->n[1] * lerp127; - avn[2] = verts1->n[2] * ilerp127 + verts2->n[2] * lerp127; - modelav += 3; - av += 3; - avn += 3; - verts1++;verts2++; + VectorScaleQuick(fscale4, lerp4, scale4); + translate[0] = translate1[0] * lerp1 + translate2[0] * lerp2 + translate3[0] * lerp3 + translate4[0] * lerp4; + translate[1] = translate1[1] * lerp1 + translate2[1] * lerp2 + translate3[1] * lerp3 + translate4[1] * lerp4; + translate[2] = translate1[2] * lerp1 + translate2[2] * lerp2 + translate3[2] * lerp3 + translate4[2] * lerp4; + // generate vertices + for (i = 0;i < vertcount;i++) + { + av[0] = verts1->v[0] * scale1[0] + verts2->v[0] * scale2[0] + verts3->v[0] * scale3[0] + verts4->v[0] * scale4[0] + translate[0]; + av[1] = verts1->v[1] * scale1[1] + verts2->v[1] * scale2[1] + verts3->v[1] * scale3[1] + verts4->v[1] * scale4[1] + translate[1]; + av[2] = verts1->v[2] * scale1[2] + verts2->v[2] * scale2[2] + verts3->v[2] * scale3[2] + verts4->v[2] * scale4[2] + translate[2]; + n1 = m_bytenormals[verts1->lightnormalindex]; + n2 = m_bytenormals[verts2->lightnormalindex]; + n3 = m_bytenormals[verts3->lightnormalindex]; + n4 = m_bytenormals[verts4->lightnormalindex]; + avn[0] = n1[0] * lerp1 + n2[0] * lerp2 + n3[0] * lerp3 + n4[0] * lerp4; + avn[1] = n1[1] * lerp1 + n2[1] * lerp2 + n3[1] * lerp3 + n4[1] * lerp4; + avn[2] = n1[2] * lerp1 + n2[2] * lerp2 + n3[2] * lerp3 + n4[2] * lerp4; + av += 3; + avn += 3; + verts1++;verts2++;verts3++;verts4++; + } + } + else + { + translate[0] = translate1[0] * lerp1 + translate2[0] * lerp2 + translate3[0] * lerp3; + translate[1] = translate1[1] * lerp1 + translate2[1] * lerp2 + translate3[1] * lerp3; + translate[2] = translate1[2] * lerp1 + translate2[2] * lerp2 + translate3[2] * lerp3; + // generate vertices + for (i = 0;i < vertcount;i++) + { + av[0] = verts1->v[0] * scale1[0] + verts2->v[0] * scale2[0] + verts3->v[0] * scale3[0] + translate[0]; + av[1] = verts1->v[1] * scale1[1] + verts2->v[1] * scale2[1] + verts3->v[1] * scale3[1] + translate[1]; + av[2] = verts1->v[2] * scale1[2] + verts2->v[2] * scale2[2] + verts3->v[2] * scale3[2] + translate[2]; + n1 = m_bytenormals[verts1->lightnormalindex]; + n2 = m_bytenormals[verts2->lightnormalindex]; + n3 = m_bytenormals[verts3->lightnormalindex]; + avn[0] = n1[0] * lerp1 + n2[0] * lerp2 + n3[0] * lerp3; + avn[1] = n1[1] * lerp1 + n2[1] * lerp2 + n3[1] * lerp3; + avn[2] = n1[2] * lerp1 + n2[2] * lerp2 + n3[2] * lerp3; + av += 3; + avn += 3; + verts1++;verts2++;verts3++; + } } } else { + translate[0] = translate1[0] * lerp1 + translate2[0] * lerp2; + translate[1] = translate1[1] * lerp1 + translate2[1] * lerp2; + translate[2] = translate1[2] * lerp1 + translate2[2] * lerp2; + // generate vertices for (i = 0;i < vertcount;i++) { - // rotate, scale, and translate the vertex locations - point[0] = verts1->v[0] * scalex1 + verts2->v[0] * scalex2 + translatex; - point[1] = verts1->v[1] * scaley1 + verts2->v[1] * scaley2 + translatey; - point[2] = verts1->v[2] * scalez1 + verts2->v[2] * scalez2 + translatez; - av[0] = point[0] * matrix_x[0] + point[1] * matrix_y[0] + point[2] * matrix_z[0] + softwaretransform_offset[0]; - av[1] = point[0] * matrix_x[1] + point[1] * matrix_y[1] + point[2] * matrix_z[1] + softwaretransform_offset[1]; - av[2] = point[0] * matrix_x[2] + point[1] * matrix_y[2] + point[2] * matrix_z[2] + softwaretransform_offset[2]; - // rotate the normals - point[0] = verts1->n[0] * ilerp127 + verts2->n[0] * lerp127; - point[1] = verts1->n[1] * ilerp127 + verts2->n[1] * lerp127; - point[2] = verts1->n[2] * ilerp127 + verts2->n[2] * lerp127; - avn[0] = point[0] * softwaretransform_x[0] + point[1] * softwaretransform_y[0] + point[2] * softwaretransform_z[0]; - avn[1] = point[0] * softwaretransform_x[1] + point[1] * softwaretransform_y[1] + point[2] * softwaretransform_z[1]; - avn[2] = point[0] * softwaretransform_x[2] + point[1] * softwaretransform_y[2] + point[2] * softwaretransform_z[2]; + av[0] = verts1->v[0] * scale1[0] + verts2->v[0] * scale2[0] + translate[0]; + av[1] = verts1->v[1] * scale1[1] + verts2->v[1] * scale2[1] + translate[1]; + av[2] = verts1->v[2] * scale1[2] + verts2->v[2] * scale2[2] + translate[2]; + n1 = m_bytenormals[verts1->lightnormalindex]; + n2 = m_bytenormals[verts2->lightnormalindex]; + avn[0] = n1[0] * lerp1 + n2[0] * lerp2; + avn[1] = n1[1] * lerp1 + n2[1] * lerp2; + avn[2] = n1[2] * lerp1 + n2[2] * lerp2; av += 3; avn += 3; verts1++;verts2++; @@ -144,28 +228,22 @@ void R_AliasLerpVerts(int vertcount, float lerp, trivert2 *verts1, vec3_t scale1 } else { + translate[0] = translate1[0] * lerp1; + translate[1] = translate1[1] * lerp1; + translate[2] = translate1[2] * lerp1; // generate vertices - if (r_modelsdonttransformnormals.value) + if (lerp1 != 1) { - float *modelav = modelaliasvert; + // general but almost never used case for (i = 0;i < vertcount;i++) { - // rotate, scale, and translate the vertex locations - point[0] = verts1->v[0] * scale1[0] + translate1[0]; - point[1] = verts1->v[1] * scale1[1] + translate1[1]; - point[2] = verts1->v[2] * scale1[2] + translate1[2]; - // save mostly un-transformed copy for lighting - modelav[0] = point[0] * softwaretransform_scale; - modelav[1] = point[1] * softwaretransform_scale; - modelav[2] = point[2] * softwaretransform_scale; - av[0] = point[0] * matrix_x[0] + point[1] * matrix_y[0] + point[2] * matrix_z[0] + softwaretransform_offset[0]; - av[1] = point[0] * matrix_x[1] + point[1] * matrix_y[1] + point[2] * matrix_z[1] + softwaretransform_offset[1]; - av[2] = point[0] * matrix_x[2] + point[1] * matrix_y[2] + point[2] * matrix_z[2] + softwaretransform_offset[2]; - // decompress normal but do not rotate it - avn[0] = verts1->n[0] * (1.0f / 127.0f); - avn[1] = verts1->n[1] * (1.0f / 127.0f); - avn[2] = verts1->n[2] * (1.0f / 127.0f); - modelav += 3; + av[0] = verts1->v[0] * scale1[0] + translate[0]; + av[1] = verts1->v[1] * scale1[1] + translate[1]; + av[2] = verts1->v[2] * scale1[2] + translate[2]; + n1 = m_bytenormals[verts1->lightnormalindex]; + avn[0] = n1[0] * lerp1; + avn[1] = n1[1] * lerp1; + avn[2] = n1[2] * lerp1; av += 3; avn += 3; verts1++; @@ -173,22 +251,13 @@ void R_AliasLerpVerts(int vertcount, float lerp, trivert2 *verts1, vec3_t scale1 } else { + // fast normal case for (i = 0;i < vertcount;i++) { - // rotate, scale, and translate the vertex locations - point[0] = verts1->v[0] * scale1[0] + translate1[0]; - point[1] = verts1->v[1] * scale1[1] + translate1[1]; - point[2] = verts1->v[2] * scale1[2] + translate1[2]; - av[0] = point[0] * matrix_x[0] + point[1] * matrix_y[0] + point[2] * matrix_z[0] + softwaretransform_offset[0]; - av[1] = point[0] * matrix_x[1] + point[1] * matrix_y[1] + point[2] * matrix_z[1] + softwaretransform_offset[1]; - av[2] = point[0] * matrix_x[2] + point[1] * matrix_y[2] + point[2] * matrix_z[2] + softwaretransform_offset[2]; - // rotate the normals - point[0] = verts1->n[0] * (1.0f / 127.0f); - point[1] = verts1->n[1] * (1.0f / 127.0f); - point[2] = verts1->n[2] * (1.0f / 127.0f); - avn[0] = point[0] * softwaretransform_x[0] + point[1] * softwaretransform_y[0] + point[2] * softwaretransform_z[0]; - avn[1] = point[0] * softwaretransform_x[1] + point[1] * softwaretransform_y[1] + point[2] * softwaretransform_z[1]; - avn[2] = point[0] * softwaretransform_x[2] + point[1] * softwaretransform_y[2] + point[2] * softwaretransform_z[2]; + av[0] = verts1->v[0] * scale1[0] + translate[0]; + av[1] = verts1->v[1] * scale1[1] + translate[1]; + av[2] = verts1->v[2] * scale1[2] + translate[2]; + VectorCopy(m_bytenormals[verts1->lightnormalindex], avn); av += 3; avn += 3; verts1++; @@ -197,35 +266,11 @@ void R_AliasLerpVerts(int vertcount, float lerp, trivert2 *verts1, vec3_t scale1 } } -float R_CalcAnimLerp(entity_t *ent, int pose, float lerpscale) -{ - if (ent->draw_lastmodel == ent->model && ent->draw_lerpstart <= cl.time) - { - if (pose != ent->draw_pose) - { - ent->draw_lastpose = ent->draw_pose; - ent->draw_pose = pose; - ent->draw_lerpstart = cl.time; - return 0; - } - else - return ((cl.time - ent->draw_lerpstart) * lerpscale); - } - else // uninitialized - { - ent->draw_lastmodel = ent->model; - ent->draw_lastpose = ent->draw_pose = pose; - ent->draw_lerpstart = cl.time; - return 0; - } -} - -void GL_DrawModelMesh(int skin, byte *colors, maliashdr_t *maliashdr) +void GL_DrawModelMesh(rtexture_t *skin, byte *colors, maliashdr_t *maliashdr) { - int i; if (!r_render.value) return; - glBindTexture(GL_TEXTURE_2D, skin); + glBindTexture(GL_TEXTURE_2D, R_GetTexture(skin)); if (!colors) { if (lighthalf) @@ -233,41 +278,16 @@ void GL_DrawModelMesh(int skin, byte *colors, maliashdr_t *maliashdr) else glColor3f(1.0f, 1.0f, 1.0f); } - if (gl_vertexarrays.value) + if (colors) { - if (colors) - { - qglColorPointer(4, GL_UNSIGNED_BYTE, 0, colors); - glEnableClientState(GL_COLOR_ARRAY); - } - - qglTexCoordPointer(2, GL_FLOAT, 0, (void *)((int) maliashdr->texdata + (int) maliashdr)); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - - qglDrawElements(GL_TRIANGLES, maliashdr->numtris * 3, GL_UNSIGNED_SHORT, (void *)((int) maliashdr + maliashdr->tridata)); + glColorPointer(4, GL_UNSIGNED_BYTE, 0, colors); + glEnableClientState(GL_COLOR_ARRAY); + } - glDisableClientState(GL_TEXTURE_COORD_ARRAY); + glDrawElements(GL_TRIANGLES, maliashdr->numtris * 3, GL_UNSIGNED_SHORT, (void *)((int) maliashdr + maliashdr->tridata)); - if (colors) - glDisableClientState(GL_COLOR_ARRAY); - } - else - { - unsigned short *in, index; - float *tex; - in = (void *)((int) maliashdr + maliashdr->tridata); - glBegin(GL_TRIANGLES); - tex = (void *)((int) maliashdr + maliashdr->texdata); - for (i = 0;i < maliashdr->numtris * 3;i++) - { - index = *in++; - glTexCoord2f(tex[index*2], tex[index*2+1]); - if (colors) - glColor4f(colors[index*4] * (1.0f / 255.0f), colors[index*4+1] * (1.0f / 255.0f), colors[index*4+2] * (1.0f / 255.0f), colors[index*4+3] * (1.0f / 255.0f)); - glVertex3fv(&aliasvert[index*3]); - } - glEnd(); - } + if (colors) + glDisableClientState(GL_COLOR_ARRAY); // leave it in a state for additional passes glDepthMask(0); glEnable(GL_BLEND); @@ -299,43 +319,35 @@ R_DrawAliasFrame */ extern vec3_t lightspot; void R_LightModel(int numverts, vec3_t center, vec3_t basecolor); -void R_DrawAliasFrame (maliashdr_t *maliashdr, float alpha, vec3_t color, entity_t *ent, int shadow, vec3_t org, vec3_t angles, int frame, int *skin, int colormap, int effects, int flags) +void R_DrawAliasFrame (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) { - int i, pose; - float lerpscale, lerp; - maliasframe_t *frameinfo; - - softwaretransformforentity(ent); - - if ((frame >= maliashdr->numframes) || (frame < 0)) - { - Con_DPrintf ("R_AliasSetupFrame: no such frame %d\n", frame); - frame = 0; - } - - frameinfo = ((maliasframe_t *)((int) maliashdr + maliashdr->framedata)) + frame; - pose = frameinfo->start; - - if (frameinfo->length > 1) + if (gl_transform.value) { - lerpscale = frameinfo->rate; - pose += (int)(cl.time * frameinfo->rate) % frameinfo->length; + if (r_render.value) + { + glPushMatrix(); + GL_SetupModelTransform(org, angles, scale); + } } - else - lerpscale = 10.0f; - - lerp = R_CalcAnimLerp(ent, pose, lerpscale); + // always needed, for model lighting + softwaretransformforentity(ent); - R_AliasLerpVerts(maliashdr->numverts, lerp, (trivert2 *)((int) maliashdr + maliashdr->posedata) + ent->draw_lastpose * maliashdr->numverts, maliashdr->scale, maliashdr->scale_origin, (trivert2 *)((int) maliashdr + maliashdr->posedata) + ent->draw_pose * maliashdr->numverts, maliashdr->scale, maliashdr->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); // prep the vertex array as early as possible if (r_render.value) { - if (gl_vertexarrays.value) - { - qglVertexPointer(3, GL_FLOAT, 0, aliasvert); - glEnableClientState(GL_VERTEX_ARRAY); - } + glVertexPointer(3, GL_FLOAT, 0, aliasvert); + glEnableClientState(GL_VERTEX_ARRAY); + glTexCoordPointer(2, GL_FLOAT, 0, (void *)((int) maliashdr->texdata + (int) maliashdr)); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + GL_LockArray(0, maliashdr->numverts); } R_LightModel(maliashdr->numverts, org, color); @@ -408,64 +420,20 @@ void R_DrawAliasFrame (maliashdr_t *maliashdr, float alpha, vec3_t color, entity VectorSubtract(org, r_refdef.vieworg, diff); glColor4f(fogcolor[0], fogcolor[1], fogcolor[2], exp(fogdensity/DotProduct(diff,diff))); - if (gl_vertexarrays.value) - { - qglDrawElements(GL_TRIANGLES, maliashdr->numtris * 3, GL_UNSIGNED_SHORT, (void *)((int) maliashdr + maliashdr->tridata)); - } - else - { - unsigned short *in; - in = (void *)((int) maliashdr + maliashdr->tridata); - glBegin(GL_TRIANGLES); - for (i = 0;i < maliashdr->numtris * 3;i++) - glVertex3fv(&aliasvert[*in++ * 3]); - glEnd(); - } - - glEnable (GL_TEXTURE_2D); - glColor3f (1,1,1); - } - if (gl_vertexarrays.value) - glDisableClientState(GL_VERTEX_ARRAY); - - if (!fogenabled && r_shadows.value && !(effects & EF_ADDITIVE) && shadow) - { - // flatten it to make a shadow - float *av = aliasvert + 2, l = lightspot[2] + 0.125; - av = aliasvert + 2; - for (i = 0;i < maliashdr->numverts;i++, av+=3) - if (*av > l) - *av = l; - glDisable (GL_TEXTURE_2D); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glEnable (GL_BLEND); - glDepthMask(0); // disable zbuffer updates - glColor4f (0,0,0,0.5 * alpha); - - if (gl_vertexarrays.value) - { - qglVertexPointer(3, GL_FLOAT, 0, aliasvert); - glEnableClientState(GL_VERTEX_ARRAY); - qglDrawElements(GL_TRIANGLES, maliashdr->numtris * 3, GL_UNSIGNED_SHORT, (void *)((int) maliashdr + maliashdr->tridata)); - glDisableClientState(GL_VERTEX_ARRAY); - } - else - { - unsigned short *in; - in = (void *)((int) maliashdr + maliashdr->tridata); - glBegin(GL_TRIANGLES); - for (i = 0;i < maliashdr->numtris * 3;i++) - glVertex3fv(&aliasvert[*in++ * 3]); - glEnd(); - } + glDrawElements(GL_TRIANGLES, maliashdr->numtris * 3, GL_UNSIGNED_SHORT, (void *)((int) maliashdr + maliashdr->tridata)); glEnable (GL_TEXTURE_2D); glColor3f (1,1,1); } + GL_UnlockArray(); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + glDisableClientState(GL_VERTEX_ARRAY); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable (GL_BLEND); glDepthMask(1); + + glPopMatrix(); } /* @@ -474,42 +442,90 @@ R_DrawQ2AliasFrame ================= */ -void R_DrawQ2AliasFrame (md2mem_t *pheader, float alpha, vec3_t color, entity_t *ent, int shadow, vec3_t org, vec3_t angles, int frame, int skin, int effects, int flags) +void R_DrawQ2AliasFrame (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) { int *order, count; - float lerp; - md2memframe_t *frame1, *frame2; + md2frame_t *frame1, *frame2, *frame3, *frame4; if (r_render.value) - glBindTexture(GL_TEXTURE_2D, skin); - - softwaretransformforentity(ent); + glBindTexture(GL_TEXTURE_2D, R_GetTexture(skin)); - if ((frame >= pheader->num_frames) || (frame < 0)) + if (gl_transform.value) { - Con_DPrintf ("R_SetupQ2AliasFrame: no such frame %d\n", frame); - frame = 0; + if (r_render.value) + { + glPushMatrix(); + GL_SetupModelTransform(org, angles, scale); + } } + // always needed, for model lighting + softwaretransformforentity(ent); - lerp = R_CalcAnimLerp(ent, frame, 10); - - frame1 = (void *)((int) pheader + pheader->ofs_frames + (pheader->framesize * ent->draw_lastpose)); - frame2 = (void *)((int) pheader + pheader->ofs_frames + (pheader->framesize * ent->draw_pose)); - R_AliasLerpVerts(pheader->num_xyz, lerp, frame1->verts, frame1->scale, frame1->translate, frame2->verts, frame2->scale, frame2->translate); + 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); + if (!gl_transform.value) + R_AliasTransformVerts(pheader->num_xyz); R_LightModel(pheader->num_xyz, org, color); if (!r_render.value) return; - if (gl_vertexarrays.value) + // LordHavoc: big mess... + // using vertex arrays only slightly, although it is enough to prevent duplicates + // (saving half the transforms) + glVertexPointer(3, GL_FLOAT, 0, aliasvert); + glColorPointer(4, GL_UNSIGNED_BYTE, 0, aliasvertcolor); + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_COLOR_ARRAY); + + order = (int *)((int)pheader + pheader->ofs_glcmds); + while(1) + { + if (!(count = *order++)) + break; + if (count > 0) + glBegin(GL_TRIANGLE_STRIP); + else + { + glBegin(GL_TRIANGLE_FAN); + count = -count; + } + do + { + glTexCoord2f(((float *)order)[0], ((float *)order)[1]); + glArrayElement(order[2]); + order += 3; + } + while (count--); + } + + glDisableClientState(GL_COLOR_ARRAY); + glDisableClientState(GL_VERTEX_ARRAY); + + if (fogenabled) { + glDisable (GL_TEXTURE_2D); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable (GL_BLEND); + glDepthMask(0); // disable zbuffer updates + { + vec3_t diff; + VectorSubtract(org, r_refdef.vieworg, diff); + glColor4f(fogcolor[0], fogcolor[1], fogcolor[2], exp(fogdensity/DotProduct(diff,diff))); + } + // LordHavoc: big mess... - // using arrays only slightly, although it is enough to prevent duplicates + // using vertex arrays only slightly, although it is enough to prevent duplicates // (saving half the transforms) - qglVertexPointer(3, GL_FLOAT, 0, aliasvert); - qglColorPointer(4, GL_UNSIGNED_BYTE, 0, aliasvertcolor); + glVertexPointer(3, GL_FLOAT, 0, aliasvert); glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_COLOR_ARRAY); order = (int *)((int)pheader + pheader->ofs_glcmds); while(1) @@ -525,230 +541,184 @@ void R_DrawQ2AliasFrame (md2mem_t *pheader, float alpha, vec3_t color, entity_t } do { - glTexCoord2f(((float *)order)[0], ((float *)order)[1]); - qglArrayElement(order[2]); + glArrayElement(order[2]); order += 3; } while (count--); } - glDisableClientState(GL_COLOR_ARRAY); glDisableClientState(GL_VERTEX_ARRAY); - } - else - { - order = (int *)((int)pheader + pheader->ofs_glcmds); - while(1) - { - if (!(count = *order++)) - break; - if (count > 0) - glBegin(GL_TRIANGLE_STRIP); - else - { - glBegin(GL_TRIANGLE_FAN); - count = -count; - } - do - { - glTexCoord2f(((float *)order)[0], ((float *)order)[1]); - glColor4f(aliasvertcolor[order[2] * 4] * (1.0f / 255.0f), aliasvertcolor[order[2] * 4 + 1] * (1.0f / 255.0f), aliasvertcolor[order[2] * 4 + 2] * (1.0f / 255.0f), aliasvertcolor[order[2] * 4 + 3] * (1.0f / 255.0f)); - glVertex3fv(&aliasvert[order[2] * 3]); - order += 3; - } - while (count--); - } + + glEnable (GL_TEXTURE_2D); + glColor3f (1,1,1); } - if (fogenabled) - { - glDisable (GL_TEXTURE_2D); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glEnable (GL_BLEND); - glDepthMask(0); // disable zbuffer updates - { - vec3_t diff; - VectorSubtract(org, r_refdef.vieworg, diff); - glColor4f(fogcolor[0], fogcolor[1], fogcolor[2], exp(fogdensity/DotProduct(diff,diff))); - } + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable (GL_BLEND); + glDepthMask(1); + + if (gl_transform.value) + glPopMatrix(); +} - if (gl_vertexarrays.value) +void ZymoticLerpBones(int count, zymbonematrix *bonebase, frameblend_t *blend, zymbone_t *bone, float rootorigin[3], float rootangles[3], float rootscale) +{ + float lerp1, lerp2, lerp3, lerp4; + zymbonematrix *out, rootmatrix, m, *bone1, *bone2, *bone3, *bone4; + lerp1 = 1 - lerp2; + out = zymbonepose; + AngleVectors(rootangles, rootmatrix.m[0], rootmatrix.m[1], rootmatrix.m[2]); + VectorScale(rootmatrix.m[0], rootscale, rootmatrix.m[0]); + VectorScale(rootmatrix.m[1], rootscale, rootmatrix.m[1]); + VectorScale(rootmatrix.m[2], rootscale, rootmatrix.m[2]); + rootmatrix.m[0][3] = rootorigin[0]; + rootmatrix.m[1][3] = rootorigin[1]; + rootmatrix.m[2][3] = rootorigin[2]; + bone1 = bonebase + blend[0].frame * count; + lerp1 = blend[0].lerp; + if (blend[1].lerp) + { + bone2 = bonebase + blend[1].frame * count; + lerp2 = blend[1].lerp; + if (blend[2].lerp) { - // LordHavoc: big mess... - // using arrays only slightly, although it is enough to prevent duplicates - // (saving half the transforms) - qglVertexPointer(3, GL_FLOAT, 0, aliasvert); - glEnableClientState(GL_VERTEX_ARRAY); - - order = (int *)((int)pheader + pheader->ofs_glcmds); - while(1) + bone3 = bonebase + blend[2].frame * count; + lerp3 = blend[2].lerp; + if (blend[3].lerp) { - if (!(count = *order++)) - break; - if (count > 0) - glBegin(GL_TRIANGLE_STRIP); - else + // 4 poses + bone4 = bonebase + blend[3].frame * count; + lerp4 = blend[3].lerp; + while(count--) { - glBegin(GL_TRIANGLE_FAN); - count = -count; + // interpolate matrices + m.m[0][0] = bone1->m[0][0] * lerp1 + bone2->m[0][0] * lerp2 + bone3->m[0][0] * lerp3 + bone4->m[0][0] * lerp4; + m.m[0][1] = bone1->m[0][1] * lerp1 + bone2->m[0][1] * lerp2 + bone3->m[0][1] * lerp3 + bone4->m[0][1] * lerp4; + m.m[0][2] = bone1->m[0][2] * lerp1 + bone2->m[0][2] * lerp2 + bone3->m[0][2] * lerp3 + bone4->m[0][2] * lerp4; + m.m[0][3] = bone1->m[0][3] * lerp1 + bone2->m[0][3] * lerp2 + bone3->m[0][3] * lerp3 + bone4->m[0][3] * lerp4; + m.m[1][0] = bone1->m[1][0] * lerp1 + bone2->m[1][0] * lerp2 + bone3->m[1][0] * lerp3 + bone4->m[1][0] * lerp4; + m.m[1][1] = bone1->m[1][1] * lerp1 + bone2->m[1][1] * lerp2 + bone3->m[1][1] * lerp3 + bone4->m[1][1] * lerp4; + m.m[1][2] = bone1->m[1][2] * lerp1 + bone2->m[1][2] * lerp2 + bone3->m[1][2] * lerp3 + bone4->m[1][2] * lerp4; + m.m[1][3] = bone1->m[1][3] * lerp1 + bone2->m[1][3] * lerp2 + bone3->m[1][3] * lerp3 + bone4->m[1][3] * lerp4; + m.m[2][0] = bone1->m[2][0] * lerp1 + bone2->m[2][0] * lerp2 + bone3->m[2][0] * lerp3 + bone4->m[2][0] * lerp4; + m.m[2][1] = bone1->m[2][1] * lerp1 + bone2->m[2][1] * lerp2 + bone3->m[2][1] * lerp3 + bone4->m[2][1] * lerp4; + m.m[2][2] = bone1->m[2][2] * lerp1 + bone2->m[2][2] * lerp2 + bone3->m[2][2] * lerp3 + bone4->m[2][2] * lerp4; + m.m[2][3] = bone1->m[2][3] * lerp1 + bone2->m[2][3] * lerp2 + bone3->m[2][3] * lerp3 + bone4->m[2][3] * lerp4; + if (bone->parent >= 0) + R_ConcatTransforms(&zymbonepose[bone->parent].m[0], &m.m[0], &out->m[0]); + else + R_ConcatTransforms(&rootmatrix.m[0], &m.m[0], &out->m[0]); + bone1++; + bone2++; + bone3++; + bone4++; + bone++; + out++; } - do + } + else + { + // 3 poses + while(count--) { - qglArrayElement(order[2]); - order += 3; + // interpolate matrices + m.m[0][0] = bone1->m[0][0] * lerp1 + bone2->m[0][0] * lerp2 + bone3->m[0][0] * lerp3; + m.m[0][1] = bone1->m[0][1] * lerp1 + bone2->m[0][1] * lerp2 + bone3->m[0][1] * lerp3; + m.m[0][2] = bone1->m[0][2] * lerp1 + bone2->m[0][2] * lerp2 + bone3->m[0][2] * lerp3; + m.m[0][3] = bone1->m[0][3] * lerp1 + bone2->m[0][3] * lerp2 + bone3->m[0][3] * lerp3; + m.m[1][0] = bone1->m[1][0] * lerp1 + bone2->m[1][0] * lerp2 + bone3->m[1][0] * lerp3; + m.m[1][1] = bone1->m[1][1] * lerp1 + bone2->m[1][1] * lerp2 + bone3->m[1][1] * lerp3; + m.m[1][2] = bone1->m[1][2] * lerp1 + bone2->m[1][2] * lerp2 + bone3->m[1][2] * lerp3; + m.m[1][3] = bone1->m[1][3] * lerp1 + bone2->m[1][3] * lerp2 + bone3->m[1][3] * lerp3; + m.m[2][0] = bone1->m[2][0] * lerp1 + bone2->m[2][0] * lerp2 + bone3->m[2][0] * lerp3; + m.m[2][1] = bone1->m[2][1] * lerp1 + bone2->m[2][1] * lerp2 + bone3->m[2][1] * lerp3; + m.m[2][2] = bone1->m[2][2] * lerp1 + bone2->m[2][2] * lerp2 + bone3->m[2][2] * lerp3; + m.m[2][3] = bone1->m[2][3] * lerp1 + bone2->m[2][3] * lerp2 + bone3->m[2][3] * lerp3; + if (bone->parent >= 0) + R_ConcatTransforms(&zymbonepose[bone->parent].m[0], &m.m[0], &out->m[0]); + else + R_ConcatTransforms(&rootmatrix.m[0], &m.m[0], &out->m[0]); + bone1++; + bone2++; + bone3++; + bone++; + out++; } - while (count--); } - - glDisableClientState(GL_VERTEX_ARRAY); } else { - order = (int *)((int)pheader + pheader->ofs_glcmds); - while(1) + // 2 poses + while(count--) { - if (!(count = *order++)) - break; - if (count > 0) - glBegin(GL_TRIANGLE_STRIP); + // interpolate matrices + m.m[0][0] = bone1->m[0][0] * lerp1 + bone2->m[0][0] * lerp2; + m.m[0][1] = bone1->m[0][1] * lerp1 + bone2->m[0][1] * lerp2; + m.m[0][2] = bone1->m[0][2] * lerp1 + bone2->m[0][2] * lerp2; + m.m[0][3] = bone1->m[0][3] * lerp1 + bone2->m[0][3] * lerp2; + m.m[1][0] = bone1->m[1][0] * lerp1 + bone2->m[1][0] * lerp2; + m.m[1][1] = bone1->m[1][1] * lerp1 + bone2->m[1][1] * lerp2; + m.m[1][2] = bone1->m[1][2] * lerp1 + bone2->m[1][2] * lerp2; + m.m[1][3] = bone1->m[1][3] * lerp1 + bone2->m[1][3] * lerp2; + m.m[2][0] = bone1->m[2][0] * lerp1 + bone2->m[2][0] * lerp2; + m.m[2][1] = bone1->m[2][1] * lerp1 + bone2->m[2][1] * lerp2; + m.m[2][2] = bone1->m[2][2] * lerp1 + bone2->m[2][2] * lerp2; + m.m[2][3] = bone1->m[2][3] * lerp1 + bone2->m[2][3] * lerp2; + if (bone->parent >= 0) + R_ConcatTransforms(&zymbonepose[bone->parent].m[0], &m.m[0], &out->m[0]); else - { - glBegin(GL_TRIANGLE_FAN); - count = -count; - } - do - { - glVertex3fv(&aliasvert[order[2] * 3]); - order += 3; - } - while (count--); + R_ConcatTransforms(&rootmatrix.m[0], &m.m[0], &out->m[0]); + bone1++; + bone2++; + bone++; + out++; } } - - glEnable (GL_TEXTURE_2D); - glColor3f (1,1,1); } - - if (!fogenabled && r_shadows.value && !(effects & EF_ADDITIVE) && shadow) + else { - int i; - float *av = aliasvert + 2, l = lightspot[2] + 0.125; - av = aliasvert + 2; - for (i = 0;i < pheader->num_xyz;i++, av+=3) - if (*av > l) - *av = l; - glDisable (GL_TEXTURE_2D); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glEnable (GL_BLEND); - glDepthMask(0); // disable zbuffer updates - glColor4f (0,0,0,0.5 * alpha); - - if (gl_vertexarrays.value) + // 1 pose + if (lerp1 != 1) { - qglVertexPointer(3, GL_FLOAT, 0, aliasvert); - glEnableClientState(GL_VERTEX_ARRAY); - - while(1) + // lerp != 1.0 + while(count--) { - if (!(count = *order++)) - break; - if (count > 0) - glBegin(GL_TRIANGLE_STRIP); + // interpolate matrices + m.m[0][0] = bone1->m[0][0] * lerp1; + m.m[0][1] = bone1->m[0][1] * lerp1; + m.m[0][2] = bone1->m[0][2] * lerp1; + m.m[0][3] = bone1->m[0][3] * lerp1; + m.m[1][0] = bone1->m[1][0] * lerp1; + m.m[1][1] = bone1->m[1][1] * lerp1; + m.m[1][2] = bone1->m[1][2] * lerp1; + m.m[1][3] = bone1->m[1][3] * lerp1; + m.m[2][0] = bone1->m[2][0] * lerp1; + m.m[2][1] = bone1->m[2][1] * lerp1; + m.m[2][2] = bone1->m[2][2] * lerp1; + m.m[2][3] = bone1->m[2][3] * lerp1; + if (bone->parent >= 0) + R_ConcatTransforms(&zymbonepose[bone->parent].m[0], &m.m[0], &out->m[0]); else - { - glBegin(GL_TRIANGLE_FAN); - count = -count; - } - do - { - qglArrayElement(order[2]); - order += 3; - } - while (count--); + R_ConcatTransforms(&rootmatrix.m[0], &m.m[0], &out->m[0]); + bone1++; + bone++; + out++; } - - glDisableClientState(GL_VERTEX_ARRAY); } else { - while(1) + // lerp == 1.0 + while(count--) { - if (!(count = *order++)) - break; - if (count > 0) - glBegin(GL_TRIANGLE_STRIP); + if (bone->parent >= 0) + R_ConcatTransforms(&zymbonepose[bone->parent].m[0], &bone1->m[0], &out->m[0]); else - { - glBegin(GL_TRIANGLE_FAN); - count = -count; - } - do - { - glVertex3fv(&aliasvert[order[2] * 3]); - order += 3; - } - while (count--); + R_ConcatTransforms(&rootmatrix.m[0], &bone1->m[0], &out->m[0]); + bone1++; + bone++; + out++; } } - - glEnable (GL_TEXTURE_2D); - glColor3f (1,1,1); - } - - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glEnable (GL_BLEND); - glDepthMask(1); -} - -void ZymoticLerpBones(int count, float lerp2, zymbonematrix *bone1, zymbonematrix *bone2, zymbone_t *bone, float rootorigin[3], float rootangles[3]) -{ - float lerp1; - zymbonematrix *out, rootmatrix, m; - lerp1 = 1 - lerp2; - out = zymbonepose; - AngleVectors(rootangles, rootmatrix.m[0], rootmatrix.m[1], rootmatrix.m[2]); - rootmatrix.m[0][3] = rootorigin[0]; - rootmatrix.m[1][3] = rootorigin[1]; - rootmatrix.m[2][3] = rootorigin[2]; - if (lerp1 != 1) // interpolation - { - while(count--) - { - // interpolate matrices - m.m[0][0] = bone1->m[0][0] * lerp1 + bone2->m[0][0] * lerp2; - m.m[0][1] = bone1->m[0][1] * lerp1 + bone2->m[0][1] * lerp2; - m.m[0][2] = bone1->m[0][2] * lerp1 + bone2->m[0][2] * lerp2; - m.m[0][3] = bone1->m[0][3] * lerp1 + bone2->m[0][3] * lerp2; - m.m[1][0] = bone1->m[1][0] * lerp1 + bone2->m[1][0] * lerp2; - m.m[1][1] = bone1->m[1][1] * lerp1 + bone2->m[1][1] * lerp2; - m.m[1][2] = bone1->m[1][2] * lerp1 + bone2->m[1][2] * lerp2; - m.m[1][3] = bone1->m[1][3] * lerp1 + bone2->m[1][3] * lerp2; - m.m[2][0] = bone1->m[2][0] * lerp1 + bone2->m[2][0] * lerp2; - m.m[2][1] = bone1->m[2][1] * lerp1 + bone2->m[2][1] * lerp2; - m.m[2][2] = bone1->m[2][2] * lerp1 + bone2->m[2][2] * lerp2; - m.m[2][3] = bone1->m[2][3] * lerp1 + bone2->m[2][3] * lerp2; - if (bone->parent >= 0) - R_ConcatTransforms(&zymbonepose[bone->parent].m[0], &m.m[0], &out->m[0]); - else - R_ConcatTransforms(&rootmatrix.m[0], &m.m[0], &out->m[0]); - bone1++; - bone2++; - bone++; - out++; - } - } - else // no interpolation - { - while(count--) - { - if (bone->parent >= 0) - R_ConcatTransforms(&zymbonepose[bone->parent].m[0], &bone1->m[0], &out->m[0]); - else - R_ConcatTransforms(&rootmatrix.m[0], &bone1->m[0], &out->m[0]); - bone1++; - bone++; - out++; - } } } @@ -852,65 +822,35 @@ void ZymoticCalcNormals(int vertcount, int shadercount, int *renderlist) void GL_DrawZymoticModelMesh(byte *colors, zymtype1header_t *m) { - int i, c, *renderlist, *texturenum; + int i, c, *renderlist; + rtexture_t **texture; if (!r_render.value) return; renderlist = (int *)(m->lump_render.start + (int) m); - texturenum = (int *)(m->lump_shaders.start + (int) m); - if (gl_vertexarrays.value) - { - qglVertexPointer(3, GL_FLOAT, 0, aliasvert); - glEnableClientState(GL_VERTEX_ARRAY); - - qglColorPointer(4, GL_UNSIGNED_BYTE, 0, colors); - glEnableClientState(GL_COLOR_ARRAY); + texture = (rtexture_t **)(m->lump_shaders.start + (int) m); + glVertexPointer(3, GL_FLOAT, 0, aliasvert); + glEnableClientState(GL_VERTEX_ARRAY); - qglTexCoordPointer(2, GL_FLOAT, 0, (float *)(m->lump_texcoords.start + (int) m)); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glColorPointer(4, GL_UNSIGNED_BYTE, 0, colors); + glEnableClientState(GL_COLOR_ARRAY); - for (i = 0;i < m->numshaders;i++) - { - c = (*renderlist++) * 3; - glBindTexture(GL_TEXTURE_2D, *texturenum++); - qglDrawElements(GL_TRIANGLES, c, GL_UNSIGNED_INT, renderlist); - renderlist += c; - } + glTexCoordPointer(2, GL_FLOAT, 0, (float *)(m->lump_texcoords.start + (int) m)); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); + for (i = 0;i < m->numshaders;i++) + { + c = (*renderlist++) * 3; + glBindTexture(GL_TEXTURE_2D, R_GetTexture(*texture)); + texture++; + glDrawElements(GL_TRIANGLES, c, GL_UNSIGNED_INT, renderlist); + renderlist += c; + } - glDisableClientState(GL_COLOR_ARRAY); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); - glDisableClientState(GL_VERTEX_ARRAY); - } - else - { - int index; - float *tex; - tex = (float *)(m->lump_texcoords.start + (int) m); + glDisableClientState(GL_COLOR_ARRAY); - for (i = 0;i < m->numshaders;i++) - { - c = *renderlist++; - glBindTexture(GL_TEXTURE_2D, *texturenum++); - glBegin(GL_TRIANGLES); - while (c--) - { - index = *renderlist++; - glTexCoord2fv(tex + index*2); - glColor4ubv(colors + index*4); - glVertex3fv(aliasvert + index*3); - index = *renderlist++; - glTexCoord2fv(tex + index*2); - glColor4ubv(colors + index*4); - glVertex3fv(aliasvert + index*3); - index = *renderlist++; - glTexCoord2fv(tex + index*2); - glColor4ubv(colors + index*4); - glVertex3fv(aliasvert + index*3); - } - glEnd(); - } - } + glDisableClientState(GL_VERTEX_ARRAY); } void GL_DrawZymoticModelMeshFog(vec3_t org, zymtype1header_t *m) @@ -927,103 +867,19 @@ void GL_DrawZymoticModelMeshFog(vec3_t org, zymtype1header_t *m) VectorSubtract(org, r_refdef.vieworg, diff); glColor4f(fogcolor[0], fogcolor[1], fogcolor[2], exp(fogdensity/DotProduct(diff,diff))); - if (gl_vertexarrays.value) - { - qglVertexPointer(3, GL_FLOAT, 0, aliasvert); - glEnableClientState(GL_VERTEX_ARRAY); - for (i = 0;i < m->numshaders;i++) - { - c = (*renderlist++) * 3; - qglDrawElements(GL_TRIANGLES, c, GL_UNSIGNED_INT, renderlist); - renderlist += c; - } + glVertexPointer(3, GL_FLOAT, 0, aliasvert); + glEnableClientState(GL_VERTEX_ARRAY); - glDisableClientState(GL_VERTEX_ARRAY); - } - else + for (i = 0;i < m->numshaders;i++) { - int index; - float *tex; - tex = (float *)(m->lump_texcoords.start + (int) m); - - glBegin(GL_TRIANGLES); - for (i = 0;i < m->numshaders;i++) - { - c = *renderlist++; - while (c--) - { - index = *renderlist++; - glVertex3fv(aliasvert + index*3); - index = *renderlist++; - glVertex3fv(aliasvert + index*3); - index = *renderlist++; - glVertex3fv(aliasvert + index*3); - } - } - glEnd(); + c = (*renderlist++) * 3; + glDrawElements(GL_TRIANGLES, c, GL_UNSIGNED_INT, renderlist); + renderlist += c; } - glEnable(GL_TEXTURE_2D); - glColor3f (1,1,1); -} - -void GL_DrawZymoticModelMeshShadow(zymtype1header_t *m) -{ - int i, c, *renderlist; - float *av, l; - if (!r_render.value) - return; - - // flatten it to make a shadow - av = aliasvert + 2; - l = lightspot[2] + 0.125; - for (i = 0;i < m->numverts;i++, av+=3) - if (*av > l) - *av = l; - - renderlist = (int *)(m->lump_render.start + (int) m); - glDisable(GL_TEXTURE_2D); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glEnable (GL_BLEND); - glDepthMask(0); // disable zbuffer updates - - glColor4f(0.0f, 0.0f, 0.0f, 0.5f); - if (gl_vertexarrays.value) - { - qglVertexPointer(3, GL_FLOAT, 0, aliasvert); - glEnableClientState(GL_VERTEX_ARRAY); - for (i = 0;i < m->numshaders;i++) - { - c = (*renderlist++) * 3; - qglDrawElements(GL_TRIANGLES, c, GL_UNSIGNED_INT, renderlist); - renderlist += c; - } - - glDisableClientState(GL_VERTEX_ARRAY); - } - else - { - int index; - float *tex; - tex = (float *)(m->lump_texcoords.start + (int) m); + glDisableClientState(GL_VERTEX_ARRAY); - glBegin(GL_TRIANGLES); - for (i = 0;i < m->numshaders;i++) - { - c = *renderlist++; - while (c--) - { - index = *renderlist++; - glVertex3fv(aliasvert + index*3); - index = *renderlist++; - glVertex3fv(aliasvert + index*3); - index = *renderlist++; - glVertex3fv(aliasvert + index*3); - } - } - glEnd(); - } glEnable(GL_TEXTURE_2D); glColor3f (1,1,1); } @@ -1033,47 +889,9 @@ void GL_DrawZymoticModelMeshShadow(zymtype1header_t *m) R_DrawZymoticFrame ================= */ -void R_DrawZymoticFrame (zymtype1header_t *m, float alpha, vec3_t color, entity_t *ent, int shadow, vec3_t org, vec3_t angles, int frame, int skinblah, int effects, int flags) +void R_DrawZymoticFrame (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) { - zymscene_t *scene; - float scenetime, scenefrac; - int sceneframe1, sceneframe2; - zymbonematrix *basebonepose; - if ((frame >= m->numscenes) || (frame < 0)) - { - Con_DPrintf ("R_ZymoticSetupFrame: no such frame %d\n", frame); - frame = 0; - } - - scene = (zymscene_t *)(m->lump_scenes.start + (int) m) + frame; - if (ent->draw_lastmodel != ent->model || ent->draw_pose != frame || ent->draw_lerpstart >= cl.time) - { - ent->draw_lastmodel = ent->model; - ent->draw_lastpose = -1; - ent->draw_pose = frame; - ent->draw_lerpstart = cl.time; - } - scenetime = (cl.time - ent->draw_lerpstart) * scene->framerate; - sceneframe1 = (int) scenetime; - sceneframe2 = sceneframe1 + 1; - scenefrac = scenetime - sceneframe1; - if (scene->flags & ZYMSCENEFLAG_NOLOOP) - { - if (sceneframe1 > (scene->length - 1)) - sceneframe1 = (scene->length - 1); - if (sceneframe2 > (scene->length - 1)) - sceneframe2 = (scene->length - 1); - } - else - { - sceneframe1 %= scene->length; - sceneframe2 %= scene->length; - } - if (sceneframe2 == sceneframe1) - scenefrac = 0; - - basebonepose = (zymbonematrix *)(m->lump_poses.start + (int) m); - ZymoticLerpBones(m->numbones, scenefrac, basebonepose + sceneframe1 * m->numbones, basebonepose + sceneframe2 * m->numbones, (zymbone_t *)(m->lump_bones.start + (int) m), org, angles); + ZymoticLerpBones(m->numbones, (zymbonematrix *)(m->lump_poses.start + (int) m), blend, (zymbone_t *)(m->lump_bones.start + (int) m), org, angles, 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)); @@ -1106,15 +924,11 @@ void R_DrawZymoticFrame (zymtype1header_t *m, float alpha, vec3_t color, entity_ if (fogenabled) GL_DrawZymoticModelMeshFog(org, m); - if (!fogenabled && r_shadows.value && !(effects & EF_ADDITIVE) && shadow) - GL_DrawZymoticModelMeshShadow(m); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable (GL_BLEND); glDepthMask(1); } -int modeldlightbits[8]; extern int r_dlightframecount; /* @@ -1123,13 +937,12 @@ R_DrawAliasModel ================= */ -void R_DrawAliasModel (entity_t *ent, int cull, float alpha, model_t *clmodel, int frame, int skin, vec3_t org, vec3_t angles, int effects, int flags, int colormap) +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) { int i; vec3_t mins, maxs, color; - mleaf_t *leaf; void *modelheader; - int *skinset; + rtexture_t **skinset; if (alpha < (1.0 / 64.0)) return; // basically completely transparent @@ -1142,30 +955,6 @@ void R_DrawAliasModel (entity_t *ent, int cull, float alpha, model_t *clmodel, i c_models++; - leaf = Mod_PointInLeaf (org, cl.worldmodel); - if (leaf->dlightframe == r_dlightframecount) - for (i = 0;i < 8;i++) - modeldlightbits[i] = leaf->dlightbits[i]; - else - for (i = 0;i < 8;i++) - modeldlightbits[i] = 0; - - // get lighting information - - if ((flags & EF_FULLBRIGHT) || (effects & EF_FULLBRIGHT)) - color[0] = color[1] = color[2] = 256; - else - R_LightPoint (color, org); - - if (r_render.value) - glDisable(GL_ALPHA_TEST); - - if (frame < 0 || frame >= clmodel->numframes) - { - frame = 0; - Con_DPrintf("invalid skin number %d for model %s\n", frame, clmodel->name); - } - if (skin < 0 || skin >= clmodel->numskins) { skin = 0; @@ -1178,7 +967,7 @@ void R_DrawAliasModel (entity_t *ent, int cull, float alpha, model_t *clmodel, i // int *skinanimrange = (int *) (clmodel->skinanimrange + (int) modelheader) + skin * 2; // int *skinanim = (int *) (clmodel->skinanim + (int) modelheader); int *skinanimrange = clmodel->skinanimrange + skin * 2; - int *skinanim = clmodel->skinanim; + rtexture_t **skinanim = clmodel->skinanim; i = skinanimrange[0]; if (skinanimrange[1] > 1) // animated i += ((int) (cl.time * 10) % skinanimrange[1]); @@ -1190,9 +979,9 @@ void R_DrawAliasModel (entity_t *ent, int cull, float alpha, model_t *clmodel, i c_alias_polys += clmodel->numtris; if (clmodel->aliastype == ALIASTYPE_ZYM) - R_DrawZymoticFrame (modelheader, alpha, color, ent, ent != &cl.viewent, org, angles, frame, 0, effects, flags); + R_DrawZymoticFrame (modelheader, alpha, color, ent, ent != &cl.viewent, org, angles, scale, blend, 0 , effects, flags); else if (clmodel->aliastype == ALIASTYPE_MD2) - R_DrawQ2AliasFrame (modelheader, alpha, color, ent, ent != &cl.viewent, org, angles, frame, skinset[0], effects, flags); + R_DrawQ2AliasFrame (modelheader, alpha, color, ent, ent != &cl.viewent, org, angles, scale, blend, skinset[0] , effects, flags); else - R_DrawAliasFrame (modelheader, alpha, color, ent, ent != &cl.viewent, org, angles, frame, skinset, colormap, effects, flags); + R_DrawAliasFrame (modelheader, alpha, color, ent, ent != &cl.viewent, org, angles, scale, blend, skinset , colormap, effects, flags); } diff --git a/gl_poly.c b/gl_poly.c index 2f53d5cd..4eb8bafe 100644 --- a/gl_poly.c +++ b/gl_poly.c @@ -4,19 +4,19 @@ transvert_t *transvert; transpoly_t *transpoly; unsigned short *transpolyindex; wallvert_t *wallvert; +wallvertcolor_t *wallvertcolor; wallpoly_t *wallpoly; skyvert_t *skyvert; skypoly_t *skypoly; -unsigned short currenttranspoly; -unsigned short currenttransvert; -unsigned short currentwallpoly; -unsigned short currentwallvert; -unsigned short currentskypoly; -unsigned short currentskyvert; +int currenttranspoly; +int currenttransvert; +int currentwallpoly; +int currentwallvert; +int currentskypoly; +int currentskyvert; cvar_t gl_multitexture = {"gl_multitexture", "1"}; -cvar_t gl_vertexarrays = {"gl_vertexarrays", "1"}; typedef struct translistitem_s { @@ -41,6 +41,7 @@ void gl_poly_start() transpoly = qmalloc(MAX_TRANSPOLYS * sizeof(transpoly_t)); transpolyindex = qmalloc(MAX_TRANSPOLYS * sizeof(unsigned short)); wallvert = qmalloc(MAX_WALLVERTS * sizeof(wallvert_t)); + wallvertcolor = qmalloc(MAX_WALLVERTS * sizeof(wallvertcolor_t)); wallpoly = qmalloc(MAX_WALLPOLYS * sizeof(wallpoly_t)); skyvert = qmalloc(MAX_SKYVERTS * sizeof(skyvert_t)); skypoly = qmalloc(MAX_SKYPOLYS * sizeof(skypoly_t)); @@ -54,6 +55,7 @@ void gl_poly_shutdown() qfree(transpoly); qfree(transpolyindex); qfree(wallvert); + qfree(wallvertcolor); qfree(wallpoly); qfree(skyvert); qfree(skypoly); @@ -62,7 +64,6 @@ void gl_poly_shutdown() void GL_Poly_Init() { Cvar_RegisterVariable (&gl_multitexture); - Cvar_RegisterVariable (&gl_vertexarrays); R_RegisterModule("GL_Poly", gl_poly_start, gl_poly_shutdown); } @@ -382,10 +383,7 @@ void transpolyrender() glEnable(GL_BLEND); glShadeModel(GL_SMOOTH); glDepthMask(0); // disable zbuffer updates - if (isG200) // Matrox G200 cards can't handle per pixel alpha - glEnable(GL_ALPHA_TEST); - else - glDisable(GL_ALPHA_TEST); + glDisable(GL_ALPHA_TEST); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); tpolytype = TPOLYTYPE_ALPHA; texnum = -1; @@ -393,7 +391,7 @@ void transpolyrender() if (gl_vertexarrays.value) { // set up the vertex array - qglInterleavedArrays(GL_T2F_C4UB_V3F, 0, transvert); + glInterleavedArrays(GL_T2F_C4UB_V3F, 0, transvert); for (i = 0;i < transpolyindices;i++) { p = &transpoly[transpolyindex[i]]; @@ -413,14 +411,14 @@ void transpolyrender() glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } } - qglDrawArrays(GL_POLYGON, p->firstvert, p->verts); + 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); - qglDrawArrays(GL_POLYGON, p->firstvert, p->verts); + glDrawArrays(GL_POLYGON, p->firstvert, p->verts); } } glDisableClientState(GL_TEXTURE_COORD_ARRAY); @@ -445,7 +443,8 @@ void transpolyrender() glEnd(); if (isG200) { - if (p->fogtexnum) // alpha + // LordHavoc: Matrox G200 cards can't handle per pixel alpha + if (p->fogtexnum) glEnable(GL_ALPHA_TEST); else glDisable(GL_ALPHA_TEST); @@ -568,6 +567,7 @@ void wallpolyrender() int i, j, texnum, lighttexnum; wallpoly_t *p; wallvert_t *vert; + wallvertcolor_t *vertcolor; if (!r_render.value) return; if (currentwallpoly < 1) @@ -582,7 +582,7 @@ void wallpolyrender() glShadeModel(GL_FLAT); // make sure zbuffer is enabled glEnable(GL_DEPTH_TEST); - glDisable(GL_ALPHA_TEST); +// glDisable(GL_ALPHA_TEST); glDepthMask(1); glColor3f(1,1,1); if (r_fullbright.value) // LordHavoc: easy to do fullbright... @@ -600,7 +600,7 @@ void wallpolyrender() glBegin(GL_POLYGON); for (j=0 ; jnumverts ; j++, vert++) { - glTexCoord2f (vert->s, vert->t); + glTexCoord2f (vert->vert[3], vert->vert[4]); glVertex3fv (vert->vert); } glEnd (); @@ -631,8 +631,8 @@ void wallpolyrender() glBegin(GL_POLYGON); for (j=0 ; jnumverts ; j++, vert++) { - qglMTexCoord2f(gl_mtex_enum, vert->s, vert->t); // texture - qglMTexCoord2f((gl_mtex_enum+1), vert->u, vert->v); // lightmap + qglMTexCoord2f(gl_mtex_enum, vert->vert[3], vert->vert[4]); // texture + qglMTexCoord2f((gl_mtex_enum+1), vert->vert[5], vert->vert[6]); // lightmap glVertex3fv (vert->vert); } glEnd (); @@ -660,7 +660,7 @@ void wallpolyrender() glBegin(GL_POLYGON); for (j=0 ; jnumverts ; j++, vert++) { - glTexCoord2f (vert->s, vert->t); + glTexCoord2f (vert->vert[3], vert->vert[4]); glVertex3fv (vert->vert); } glEnd (); @@ -681,7 +681,7 @@ void wallpolyrender() glBegin(GL_POLYGON); for (j=0 ; jnumverts ; j++, vert++) { - glTexCoord2f (vert->u, vert->v); + glTexCoord2f (vert->vert[5], vert->vert[6]); glVertex3fv (vert->vert); } glEnd (); @@ -692,7 +692,7 @@ void wallpolyrender() glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glBlendFunc(GL_SRC_ALPHA, GL_ONE); glEnable(GL_BLEND); - glDisable(GL_ALPHA_TEST); +// glDisable(GL_ALPHA_TEST); glShadeModel(GL_SMOOTH); // render vertex lit overlays ontop texnum = -1; @@ -700,8 +700,8 @@ void wallpolyrender() { if (!p->lit) continue; - for (j = 0,vert = &wallvert[p->firstvert];j < p->numverts;j++, vert++) - if (vert->r || vert->g || vert->b) + for (j = 0,vertcolor = &wallvertcolor[p->firstvert];j < p->numverts;j++, vertcolor++) + if (vertcolor->r || vertcolor->g || vertcolor->b) goto lit; continue; lit: @@ -712,12 +712,12 @@ lit: glBindTexture(GL_TEXTURE_2D, texnum); } glBegin(GL_POLYGON); - for (j = 0,vert = &wallvert[p->firstvert];j < p->numverts;j++, vert++) + for (j = 0,vert = &wallvert[p->firstvert], vertcolor = &wallvertcolor[p->firstvert];j < p->numverts;j++, vert++, vertcolor++) { // would be 2fv, but windoze Matrox G200 and probably G400 drivers don't support that (dumb...) - glTexCoord2f(vert->s, vert->t); + glTexCoord2f(vert->vert[3], vert->vert[4]); // again, vector version isn't supported I think - glColor3ub(vert->r, vert->g, vert->b); + glColor3ub(vertcolor->r, vertcolor->g, vertcolor->b); glVertex3fv(vert->vert); } glEnd(); @@ -743,7 +743,7 @@ lit: glBegin(GL_POLYGON); for (j=0 ; jnumverts ; j++, vert++) { - glTexCoord2f (vert->s, vert->t); + glTexCoord2f (vert->vert[3], vert->vert[4]); glVertex3fv (vert->vert); } glEnd(); @@ -771,7 +771,7 @@ lit: } glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glDisable(GL_ALPHA_TEST); +// glDisable(GL_ALPHA_TEST); glShadeModel(GL_SMOOTH); glDisable(GL_BLEND); glDepthMask(1); @@ -783,10 +783,10 @@ void skypolyclear() } extern char skyname[]; -extern int solidskytexture, alphaskytexture; +extern rtexture_t *solidskytexture, *alphaskytexture; void skypolyrender() { - int i, j; + int i, j, numskyverts; skypoly_t *p; skyvert_t *vert; float length, speedscale; @@ -797,13 +797,18 @@ void skypolyrender() return; // testing // Con_DPrintf("skypolyrender: %i polys %i vertices\n", currentskypoly, currentskyvert); - glDisable(GL_ALPHA_TEST); +// glDisable(GL_ALPHA_TEST); glDisable(GL_BLEND); // make sure zbuffer is enabled glEnable(GL_DEPTH_TEST); glDepthMask(1); if (!fogenabled && !skyname[0]) // normal quake sky { + glInterleavedArrays(GL_T2F_V3F, 0, skyvert); +// glTexCoordPointer(2, GL_FLOAT, sizeof(skyvert_t) - sizeof(float) * 2, &skyvert[0].tex[0]); +// glEnableClientState(GL_TEXTURE_COORD_ARRAY); +// glVertexPointer(3, GL_FLOAT, sizeof(skyvert_t) - sizeof(float) * 3, &skyvert[0].v[0]); +// glEnableClientState(GL_VERTEX_ARRAY); if(lighthalf) glColor3f(0.5f, 0.5f, 0.5f); else @@ -812,14 +817,14 @@ void skypolyrender() glEnable(GL_TEXTURE_2D); glDisable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glBindTexture(GL_TEXTURE_2D, solidskytexture); // upper clouds + glBindTexture(GL_TEXTURE_2D, R_GetTexture(solidskytexture)); // upper clouds speedscale = cl.time*8; speedscale -= (int)speedscale & ~127 ; - for (i = 0,p = &skypoly[0];i < currentskypoly;i++, p++) + numskyverts = 0; + for (i = 0, p = &skypoly[0];i < currentskypoly;i++, p++) { - vert = &skyvert[p->firstvert]; - glBegin(GL_POLYGON); - for (j=0 ; jverts ; j++, vert++) + vert = skyvert + p->firstvert; + for (j = 0;j < p->verts;j++, vert++) { VectorSubtract (vert->v, r_origin, dir); dir[2] *= 3; // flatten the sphere @@ -828,21 +833,24 @@ void skypolyrender() length = sqrt (length); length = 6*63/length; - glTexCoord2f ((speedscale + dir[0] * length) * (1.0/128), (speedscale + dir[1] * length) * (1.0/128)); - glVertex3fv (vert->v); + vert->tex[0] = (speedscale + dir[0] * length) * (1.0/128); + vert->tex[1] = (speedscale + dir[1] * length) * (1.0/128); } - glEnd (); + numskyverts += p->verts; } + GL_LockArray(0, numskyverts); + for (i = 0, p = &skypoly[0];i < currentskypoly;i++, p++) + glDrawArrays(GL_POLYGON, p->firstvert, p->verts); + GL_UnlockArray(); glEnable(GL_BLEND); glDepthMask(0); - glBindTexture(GL_TEXTURE_2D, alphaskytexture); // lower clouds + glBindTexture(GL_TEXTURE_2D, R_GetTexture(alphaskytexture)); // lower clouds speedscale = cl.time*16; speedscale -= (int)speedscale & ~127 ; - for (i = 0,p = &skypoly[0];i < currentskypoly;i++, p++) + for (i = 0, p = &skypoly[0];i < currentskypoly;i++, p++) { - vert = &skyvert[p->firstvert]; - glBegin(GL_POLYGON); - for (j=0 ; jverts ; j++, vert++) + vert = skyvert + p->firstvert; + for (j = 0;j < p->verts;j++, vert++) { VectorSubtract (vert->v, r_origin, dir); dir[2] *= 3; // flatten the sphere @@ -851,29 +859,36 @@ void skypolyrender() length = sqrt (length); length = 6*63/length; - glTexCoord2f ((speedscale + dir[0] * length) * (1.0/128), (speedscale + dir[1] * length) * (1.0/128)); - glVertex3fv (vert->v); + vert->tex[0] = (speedscale + dir[0] * length) * (1.0/128); + vert->tex[1] = (speedscale + dir[1] * length) * (1.0/128); } - glEnd (); } + GL_LockArray(0, numskyverts); + for (i = 0, p = &skypoly[0];i < currentskypoly;i++, p++) + glDrawArrays(GL_POLYGON, p->firstvert, p->verts); + GL_UnlockArray(); glDisable(GL_BLEND); glColor3f(1,1,1); glDepthMask(1); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + glDisableClientState(GL_VERTEX_ARRAY); } else { + glVertexPointer(3, GL_FLOAT, sizeof(skyvert_t) - sizeof(float) * 3, &skyvert[0].v[0]); + glEnableClientState(GL_VERTEX_ARRAY); glDisable(GL_TEXTURE_2D); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glColor3fv(fogcolor); // note: gets rendered over by skybox if fog is not enabled - for (i = 0,p = &skypoly[0];i < currentskypoly;i++, p++) - { - vert = &skyvert[p->firstvert]; - glBegin(GL_POLYGON); - for (j=0 ; jverts ; j++, vert++) - glVertex3fv (vert->v); - glEnd (); - } + numskyverts = 0; + for (i = 0, p = &skypoly[0];i < currentskypoly;i++, p++) + numskyverts += p->verts; + GL_LockArray(0, numskyverts); + for (i = 0, p = &skypoly[0];i < currentskypoly;i++, p++) + glDrawArrays(GL_POLYGON, p->firstvert, p->verts); + GL_UnlockArray(); glColor3f(1,1,1); glEnable(GL_TEXTURE_2D); + glDisableClientState(GL_VERTEX_ARRAY); } } diff --git a/gl_poly.h b/gl_poly.h index 429b97b3..24ece5f5 100644 --- a/gl_poly.h +++ b/gl_poly.h @@ -30,7 +30,8 @@ typedef struct vec_t s, t; byte r,g,b,a; vec3_t v; -} transvert_t; +} +transvert_t; typedef struct { @@ -44,14 +45,21 @@ typedef struct unsigned short firstvert; unsigned short verts; unsigned short transpolytype; -} transpoly_t; +} +transpoly_t; + +// note: must match format of glpoly_t vertices due to a memcpy used in RSurf_DrawWall +typedef struct +{ + vec_t vert[VERTEXSIZE]; // xyz st uv +} +wallvert_t; typedef struct { - vec3_t vert; - vec_t s, t, u, v; byte r,g,b,a; -} wallvert_t; +} +wallvertcolor_t; typedef struct { @@ -59,33 +67,39 @@ typedef struct unsigned short firstvert; unsigned short numverts; unsigned short lit; // doesn't need to be an unsigned short, but to keep the structure consistent... -} wallpoly_t; +} +wallpoly_t; typedef struct { + // the order and type of these is crucial to the vertex array based rendering + vec2_t tex; vec3_t v; -} skyvert_t; +} +skyvert_t; typedef struct { unsigned short firstvert; unsigned short verts; -} skypoly_t; +} +skypoly_t; extern transvert_t *transvert; extern transpoly_t *transpoly; extern unsigned short *transpolyindex; extern wallvert_t *wallvert; +extern wallvertcolor_t *wallvertcolor; extern wallpoly_t *wallpoly; extern skyvert_t *skyvert; extern skypoly_t *skypoly; -extern unsigned short currenttranspoly; -extern unsigned short currenttransvert; -extern unsigned short currentwallpoly; -extern unsigned short currentwallvert; -extern unsigned short currentskypoly; -extern unsigned short currentskyvert; +extern int currenttranspoly; +extern int currenttransvert; +extern int currentwallpoly; +extern int currentwallvert; +extern int currentskypoly; +extern int currentskyvert; #define transpolybegin(ttexnum, tglowtexnum, tfogtexnum, ttranspolytype)\ {\ @@ -126,3 +140,30 @@ extern unsigned short currentskyvert; transpoly[currenttranspoly].verts++;\ }\ } + +#define transpolyvertub(vx,vy,vz,vs,vt,vr,vg,vb,va) \ +{\ + if (currenttranspoly < MAX_TRANSPOLYS && currenttransvert < MAX_TRANSVERTS)\ + {\ + transvert[currenttransvert].s = (vs);\ + transvert[currenttransvert].t = (vt);\ + if (lighthalf)\ + {\ + transvert[currenttransvert].r = (vr) >> 1;\ + transvert[currenttransvert].g = (vg) >> 1;\ + transvert[currenttransvert].b = (vb) >> 1;\ + }\ + else\ + {\ + transvert[currenttransvert].r = (vr);\ + transvert[currenttransvert].g = (vg);\ + transvert[currenttransvert].b = (vb);\ + }\ + transvert[currenttransvert].a = (va);\ + transvert[currenttransvert].v[0] = (vx);\ + transvert[currenttransvert].v[1] = (vy);\ + transvert[currenttransvert].v[2] = (vz);\ + currenttransvert++;\ + transpoly[currenttranspoly].verts++;\ + }\ +} diff --git a/gl_rmain.c b/gl_rmain.c index 11a1c481..c4a257d2 100644 --- a/gl_rmain.c +++ b/gl_rmain.c @@ -73,7 +73,6 @@ cvar_t r_speeds = {"r_speeds","0"}; cvar_t r_speeds2 = {"r_speeds2","0"}; cvar_t r_fullbright = {"r_fullbright","0"}; //cvar_t r_lightmap = {"r_lightmap","0"}; -cvar_t r_shadows = {"r_shadows","0"}; cvar_t r_wateralpha = {"r_wateralpha","1"}; cvar_t r_dynamic = {"r_dynamic","1"}; cvar_t r_novis = {"r_novis","0"}; @@ -225,7 +224,6 @@ void GL_Main_Init() FOG_registercvars(); Cvar_RegisterVariable (&r_drawentities); Cvar_RegisterVariable (&r_drawviewmodel); - Cvar_RegisterVariable (&r_shadows); Cvar_RegisterVariable (&r_speeds); Cvar_RegisterVariable (&r_speeds2); Cvar_RegisterVariable (&contrast); @@ -257,6 +255,7 @@ extern void R_Crosshairs_Init(); extern void R_Light_Init(); extern void R_Particles_Init(); extern void R_Explosion_Init(); +extern void CL_Effects_Init(); void Render_Init() { @@ -272,6 +271,7 @@ void Render_Init() R_Light_Init(); R_Particles_Init(); R_Explosion_Init(); + CL_Effects_Init(); R_StartModules(); } @@ -280,7 +280,7 @@ void Render_Init() GL_Init =============== */ -extern char *QSG_EXTENSIONS; +extern char *ENGINE_EXTENSIONS; void GL_Init (void) { gl_vendor = glGetString (GL_VENDOR); @@ -296,10 +296,10 @@ void GL_Init (void) // Con_Printf ("%s %s\n", gl_renderer, gl_version); VID_CheckMultitexture(); - VID_CheckVertexArrays(); + VID_CheckCVA(); // LordHavoc: report supported extensions - Con_Printf ("\nQSG extensions: %s\n", QSG_EXTENSIONS); + Con_Printf ("\nengine extensions: %s\n", ENGINE_EXTENSIONS); glCullFace(GL_FRONT); glEnable(GL_TEXTURE_2D); @@ -325,13 +325,6 @@ void R_RotateForEntity (entity_t *e) } */ -// LordHavoc: if not for the fact BRIGHTFIELD particles require this, it would be removed... -#define NUMVERTEXNORMALS 162 - -float r_avertexnormals[NUMVERTEXNORMALS][3] = { -#include "anorms.h" -}; - // LordHavoc: shading stuff vec3_t shadevector; vec3_t shadecolor; @@ -341,7 +334,49 @@ float modelalpha; //================================================================================== void R_DrawBrushModel (entity_t *e); -void R_DrawSpriteModel (entity_t *e); +void R_DrawSpriteModel (entity_t *e, frameblend_t *blend); + +void R_LerpUpdate(entity_t *ent) +{ + int frame; + frame = ent->frame; + if (ent->model && ent->frame >= ent->model->numframes) + { + Con_Printf("R_LerpUpdate: no such frame%6i in \"%s\"\n", ent->frame, ent->model->name); + frame = 0; + } + + if (ent->lerp_model != ent->model) + { + // reset all interpolation information + ent->lerp_model = ent->model; + ent->frame1 = ent->frame2 = frame; + ent->frame1start = ent->frame2start = cl.time; + ent->framelerp = 1; + ent->lerp_starttime = 0; + } + else if (ent->frame2 != frame) + { + // transition to new frame + ent->frame1 = ent->frame2; + ent->frame1start = ent->frame2start; + ent->frame2 = frame; + ent->frame2start = cl.time; + ent->framelerp = 0; + ent->lerp_starttime = cl.time; + } + else + { + // lerp_starttime < 0 is used to prevent changing of framelerp + if (ent->lerp_starttime >= 0) + { + // update transition + ent->framelerp = (cl.time - ent->lerp_starttime) * 10; + ent->framelerp = bound(0, ent->framelerp, 1); + } + } +} + /* ============= @@ -370,6 +405,7 @@ void R_DrawEntitiesOnList1 (void) void R_DrawEntitiesOnList2 (void) { int i; + frameblend_t blend[4]; if (!r_drawentities.value) return; @@ -382,11 +418,18 @@ void R_DrawEntitiesOnList2 (void) switch (currententity->model->type) { case mod_alias: - R_DrawAliasModel (currententity, true, modelalpha, currententity->model, currententity->frame, currententity->skinnum, currententity->origin, currententity->angles, currententity->effects, currententity->model->flags, currententity->colormap); + if (!strcmp(currententity->model->name, "progs/flame2.mdl")) + blend[0].frame = 0; + + R_LerpUpdate(currententity); + R_LerpAnimation(currententity->model, currententity->frame1, currententity->frame2, currententity->frame1start, currententity->frame2start, currententity->framelerp, blend); + R_DrawAliasModel (currententity, true, modelalpha, currententity->model, blend, currententity->skinnum, currententity->origin, currententity->angles, currententity->scale, currententity->effects, currententity->model->flags, currententity->colormap); break; case mod_sprite: - R_DrawSpriteModel (currententity); + R_LerpUpdate(currententity); + R_LerpAnimation(currententity->model, currententity->frame1, currententity->frame2, currententity->frame1start, currententity->frame2start, currententity->framelerp, blend); + R_DrawSpriteModel (currententity, blend); break; default: @@ -402,6 +445,8 @@ 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.model) return; @@ -411,9 +456,12 @@ void R_DrawViewModel (void) currententity->scale = 1; VectorCopy(cl_entities[cl.viewentity].colormod, currententity->colormod); + R_LerpUpdate(currententity); + R_LerpAnimation(currententity->model, currententity->frame1, currententity->frame2, currententity->frame1start, currententity->frame2start, currententity->framelerp, blend); + // 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->model, currententity->frame, currententity->skinnum, currententity->origin, currententity->angles, currententity->effects, currententity->model->flags, currententity->colormap); + R_DrawAliasModel (currententity, false, modelalpha, currententity->model, blend, currententity->skinnum, currententity->origin, currententity->angles, currententity->scale, currententity->effects, currententity->model->flags, currententity->colormap); glDepthRange (gldepthmin, gldepthmax); } @@ -746,9 +794,6 @@ void R_RenderView (void) else starttime = currtime = 0; R_Clear(); - skypolyclear(); - wallpolyclear(); - transpolyclear(); skyisvisible = false; TIMEREPORT(time_clear) @@ -757,6 +802,11 @@ void R_RenderView (void) R_SetupFrame (); R_SetFrustum (); R_SetupGL (); + + skypolyclear(); + wallpolyclear(); + transpolyclear(); + TIMEREPORT(time_setup) R_MarkLeaves (); // done here so we know if we're in water @@ -777,8 +827,8 @@ void R_RenderView (void) wallpolyrender(); TIMEREPORT(time_wall) -// if (!intimerefresh) -// S_ExtraUpdate (); // don't let sound get messed up if going slow + if (!intimerefresh && !r_speeds2.value) + S_ExtraUpdate (); // don't let sound get messed up if going slow R_DrawEntitiesOnList2 (); // other models // R_RenderDlights (); diff --git a/gl_rsurf.c b/gl_rsurf.c index 7276632e..bde929ec 100644 --- a/gl_rsurf.c +++ b/gl_rsurf.c @@ -54,8 +54,6 @@ cvar_t r_dlightmap = {"r_dlightmap", "1"}; qboolean lightmaprgba, nosubimagefragments, nosubimage, skyisvisible; int lightmapbytes; -extern qboolean gl_arrays; - extern int r_dlightframecount; void gl_surf_start() @@ -81,14 +79,6 @@ void GL_Surf_Init() Cvar_RegisterVariable(&r_newworldnode); Cvar_RegisterVariable(&r_oldclip); Cvar_RegisterVariable(&r_dlightmap); - // check if it's the glquake minigl driver - if (strncasecmp(gl_vendor,"3Dfx",4)==0) - if (!gl_arrays) - { -// Cvar_SetValue("gl_nosubimagefragments", 1); -// Cvar_SetValue("gl_nosubimage", 1); - Cvar_SetValue("gl_lightmode", 0); - } R_RegisterModule("GL_Surf", gl_surf_start, gl_surf_shutdown); } @@ -100,20 +90,17 @@ int dlightdivtable[32768]; */ int R_AddDynamicLights (msurface_t *surf) { - int sdtable[18], lnum, td, maxdist, maxdist2, maxdist3, i, j, s, t, smax, tmax, red, green, blue, lit, dist2, impacts, impactt; + int sdtable[18], lnum, td, maxdist, maxdist2, maxdist3, i, s, t, smax, tmax, red, green, blue, lit, dist2, impacts, impactt; unsigned int *bl; float dist; vec3_t impact, local; // LordHavoc: use 64bit integer... shame it's not very standardized... -//#if _MSC_VER || __BORLANDC__ -// __int64 k; -//#else -// long long k; -//#endif - - // LordHavoc: later note: MSVC and hopefully all other C compilers use a 64bit result for 32bit*32bit multiply, so that was not necessary - int k; +#if _MSC_VER || __BORLANDC__ + __int64 k; +#else + long long k; +#endif lit = false; @@ -136,7 +123,7 @@ int R_AddDynamicLights (msurface_t *surf) dist = DotProduct (local, surf->plane->normal) - surf->plane->dist; // for comparisons to minimum acceptable light - maxdist = (int) ((cl_dlights[lnum].radius * cl_dlights[lnum].radius) * LIGHTSCALE); + maxdist = (int) ((cl_dlights[lnum].radius * cl_dlights[lnum].radius)); // clamp radius to avoid exceeding 32768 entry division table if (maxdist > 4194304) @@ -161,7 +148,7 @@ int R_AddDynamicLights (msurface_t *surf) // reduce calculations for (s = 0, i = impacts; s < smax; s++, i -= 16) - sdtable[s] = i * i + dist2; + sdtable[s] = i * i + dist2 + LIGHTOFFSET; maxdist3 = maxdist - (int) (dist * dist); @@ -184,9 +171,9 @@ int R_AddDynamicLights (msurface_t *surf) if (sdtable[s] < maxdist2) { k = dlightdivtable[(sdtable[s] + td) >> 7]; - j = (red * k) >> 9;bl[0] += j; - j = (green * k) >> 9;bl[1] += j; - j = (blue * k) >> 9;bl[2] += j; + bl[0] += (red * k) >> 9; + bl[1] += (green * k) >> 9; + bl[2] += (blue * k) >> 9; lit = true; } bl += 3; @@ -200,6 +187,70 @@ int R_AddDynamicLights (msurface_t *surf) } +void R_ConvertLightmap (int *in, byte *out, int width, int height, int stride) +{ + int i, j; + stride -= (width*lightmapbytes); + if (lighthalf) + { + // LordHavoc: I shift down by 8 unlike GLQuake's 7, + // the image is brightened as a processing pass + if (lightmaprgba) + { + for (i = 0;i < height;i++, out += stride) + { + for (j = 0;j < width;j++, in += 3, out += 4) + { + out[0] = min(in[0] >> 8, 255); + out[1] = min(in[1] >> 8, 255); + out[2] = min(in[2] >> 8, 255); + out[3] = 255; + } + } + } + else + { + for (i = 0;i < height;i++, out += stride) + { + for (j = 0;j < width;j++, in += 3, out += 3) + { + out[0] = min(in[0] >> 8, 255); + out[1] = min(in[1] >> 8, 255); + out[2] = min(in[2] >> 8, 255); + } + } + } + } + else + { + if (lightmaprgba) + { + for (i = 0;i < height;i++, out += stride) + { + for (j = 0;j < width;j++, in += 3, out += 4) + { + out[0] = min(in[0] >> 7, 255); + out[1] = min(in[1] >> 7, 255); + out[2] = min(in[2] >> 7, 255); + out[3] = 255; + } + } + } + else + { + for (i = 0;i < height;i++, out += stride) + { + for (j = 0;j < width;j++, in += 3, out += 3) + { + out[0] = min(in[0] >> 7, 255); + out[1] = min(in[1] >> 7, 255); + out[2] = min(in[2] >> 7, 255); + } + } + } + } +} + /* =============== R_BuildLightMap @@ -227,7 +278,7 @@ void R_BuildLightMap (msurface_t *surf, byte *dest, int stride) lightmap = surf->samples; // set to full bright if no light data - if (currententity->effects & EF_FULLBRIGHT || !cl.worldmodel->lightdata) + if (currententity && currententity->effects & EF_FULLBRIGHT || !cl.worldmodel->lightdata) { bl = blocklights; for (i=0 ; icached_dlight = R_AddDynamicLights(surf))) c_light_polys++; } - stride -= (smax*lightmapbytes); - bl = blocklights; - if (lighthalf) - { - // LordHavoc: I shift down by 8 unlike GLQuake's 7, - // the image is brightened as a processing pass - if (lightmaprgba) - { - for (i = 0;i < tmax;i++, dest += stride) - { - for (j = 0;j < smax;j++, bl += 3, dest += 4) - { - dest[0] = min(bl[0] >> 8, 255); - dest[1] = min(bl[1] >> 8, 255); - dest[2] = min(bl[2] >> 8, 255); - dest[3] = 255; - } - } - } - else - { - for (i = 0;i < tmax;i++, dest += stride) - { - for (j = 0;j < smax;j++, bl += 3, dest += 3) - { - dest[0] = min(bl[0] >> 8, 255); - dest[1] = min(bl[1] >> 8, 255); - dest[2] = min(bl[2] >> 8, 255); - } - } - } - } - else - { - if (lightmaprgba) - { - for (i = 0;i < tmax;i++, dest += stride) - { - for (j = 0;j < smax;j++, bl += 3, dest += 4) - { - dest[0] = min(bl[0] >> 7, 255); - dest[1] = min(bl[1] >> 7, 255); - dest[2] = min(bl[2] >> 7, 255); - dest[3] = 255; - } - } - } - else - { - for (i = 0;i < tmax;i++, dest += stride) - { - for (j = 0;j < smax;j++, bl += 3, dest += 3) - { - dest[0] = min(bl[0] >> 7, 255); - dest[1] = min(bl[1] >> 7, 255); - dest[2] = min(bl[2] >> 7, 255); - } - } - } - } + R_ConvertLightmap(blocklights, dest, smax, tmax, stride); } byte templight[BLOCK_WIDTH*BLOCK_HEIGHT*4]; @@ -428,7 +420,6 @@ extern float speedscale; // for top sky and bottom sky extern char skyname[]; -void R_DynamicLightPoint(vec3_t color, vec3_t org, int *dlightbits); float turbsin[256] = { #include "gl_warp_sin.h" @@ -495,9 +486,8 @@ void RSurf_DrawSky(msurface_t *s, int transform) { for (i = 0,v = p->verts[0];i < p->numverts;i++, v += VERTEXSIZE) { - skyvert[currentskyvert].v[0] = v[0]; - skyvert[currentskyvert].v[1] = v[1]; - skyvert[currentskyvert++].v[2] = v[2]; + VectorCopy(v, skyvert[currentskyvert].v); + currentskyvert++; } } } @@ -526,8 +516,8 @@ int RSurf_Light(int *dlightbits, glpoly_t *polys) cr = light->color[0]; cg = light->color[1]; cb = light->color[2]; - radius = light->radius*light->radius*LIGHTSCALE; - radius2 = radius * (256.0f / LIGHTSCALE2); + radius = light->radius*light->radius; + radius2 = radius * 256.0f; wv = wvert; for (p = polys;p;p = p->next) { @@ -557,115 +547,228 @@ void RSurf_DrawWater(msurface_t *s, texture_t *t, int transform, int alpha) int i; float os = turbsin[(int)(realtime * TURBSCALE) & 255], ot = turbsin[(int)(cl.time * TURBSCALE + 96.0) & 255]; glpoly_t *p; - float *wv, *v; - wv = wvert; - for (p = s->polys;p;p = p->next) + float *v; + // FIXME: make fog texture if water texture is transparent? + + if (s->dlightframe != r_dlightframecount) { - for (i = 0, v = p->verts[0];i < p->numverts;i++, v += VERTEXSIZE) + vec3_t temp; + // LordHavoc: fast path for no vertex lighting cases + if (transform) { - if (transform) - softwaretransform(v, wv); + if (r_waterripple.value) + { + for (p=s->polys ; p ; p=p->next) + { + transpolybegin(R_GetTexture(t->texture), R_GetTexture(t->glowtexture), 0, TPOLYTYPE_ALPHA); + for (i = 0,v = p->verts[0];i < p->numverts;i++, v += VERTEXSIZE) + { + softwaretransform(v, temp); + transpolyvert(temp[0], temp[1], temp[2] + r_waterripple.value * turbsin[(int)((temp[0]*(1.0f/32.0f)+cl.time) * TURBSCALE) & 255] * turbsin[(int)((temp[1]*(1.0f/32.0f)+realtime) * TURBSCALE) & 255] * (1.0f / 64.0f), (v[3] + os) * (1.0f/64.0f), (v[4] + ot) * (1.0f/64.0f), 128, 128, 128, alpha); + } + transpolyend(); + } + } else - VectorCopy(v, wv); + { + for (p=s->polys ; p ; p=p->next) + { + transpolybegin(R_GetTexture(t->texture), R_GetTexture(t->glowtexture), 0, TPOLYTYPE_ALPHA); + for (i = 0,v = p->verts[0];i < p->numverts;i++, v += VERTEXSIZE) + { + softwaretransform(v, temp); + transpolyvert(temp[0], temp[1], temp[2], (v[3] + os) * (1.0f/64.0f), (v[4] + ot) * (1.0f/64.0f), 128, 128, 128, alpha); + } + transpolyend(); + } + } + } + else + { if (r_waterripple.value) - wv[2] += r_waterripple.value * turbsin[(int)((wv[0]*(1.0f/32.0f)+cl.time) * TURBSCALE) & 255] * turbsin[(int)((wv[1]*(1.0f/32.0f)+realtime) * TURBSCALE) & 255] * (1.0f / 64.0f); - wv[3] = wv[4] = wv[5] = 128.0f; - wv += 6; + { + for (p=s->polys ; p ; p=p->next) + { + transpolybegin(R_GetTexture(t->texture), R_GetTexture(t->glowtexture), 0, TPOLYTYPE_ALPHA); + for (i = 0,v = p->verts[0];i < p->numverts;i++, v += VERTEXSIZE) + transpolyvert(v[0], v[1], v[2] + r_waterripple.value * turbsin[(int)((v[0]*(1.0f/32.0f)+cl.time) * TURBSCALE) & 255] * turbsin[(int)((v[1]*(1.0f/32.0f)+realtime) * TURBSCALE) & 255] * (1.0f / 64.0f), (v[3] + os) * (1.0f/64.0f), (v[4] + ot) * (1.0f/64.0f), 128, 128, 128, alpha); + transpolyend(); + } + } + else + { + for (p=s->polys ; p ; p=p->next) + { + transpolybegin(R_GetTexture(t->texture), R_GetTexture(t->glowtexture), 0, TPOLYTYPE_ALPHA); + for (i = 0,v = p->verts[0];i < p->numverts;i++, v += VERTEXSIZE) + transpolyvert(v[0], v[1], v[2], (v[3] + os) * (1.0f/64.0f), (v[4] + ot) * (1.0f/64.0f), 128, 128, 128, alpha); + transpolyend(); + } + } } } - if (s->dlightframe == r_dlightframecount) - RSurf_Light(s->dlightbits, s->polys); - wv = wvert; - // FIXME: make fog texture if water texture is transparent? - for (p=s->polys ; p ; p=p->next) + else { - transpolybegin(t->gl_texturenum, t->gl_glowtexturenum, 0, 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] + os) * (1.0f/64.0f), (v[4] + ot) * (1.0f/64.0f), wv[3], wv[4], wv[5], alpha); - transpolyend(); + float *wv; + wv = wvert; + for (p = s->polys;p;p = p->next) + { + for (i = 0, v = p->verts[0];i < p->numverts;i++, v += VERTEXSIZE) + { + if (transform) + softwaretransform(v, wv); + else + VectorCopy(v, wv); + if (r_waterripple.value) + wv[2] += r_waterripple.value * turbsin[(int)((wv[0]*(1.0f/32.0f)+cl.time) * TURBSCALE) & 255] * turbsin[(int)((wv[1]*(1.0f/32.0f)+realtime) * TURBSCALE) & 255] * (1.0f / 64.0f); + wv[3] = wv[4] = wv[5] = 128.0f; + wv += 6; + } + } + if (s->dlightframe == r_dlightframecount) + RSurf_Light(s->dlightbits, s->polys); + wv = wvert; + for (p=s->polys ; p ; p=p->next) + { + transpolybegin(R_GetTexture(t->texture), R_GetTexture(t->glowtexture), 0, 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] + os) * (1.0f/64.0f), (v[4] + ot) * (1.0f/64.0f), wv[3], wv[4], wv[5], alpha); + transpolyend(); + } } } void RSurf_DrawWall(msurface_t *s, texture_t *t, int transform) { int i, lit = false, polys = 0, verts = 0; - float *v, *wv; + float *v; glpoly_t *p; wallpoly_t *wp; wallvert_t *out; + wallvertcolor_t *outcolor; // check for lightmap modification - if (r_dynamic.value) + if (s->cached_dlight + || (r_dynamic.value && r_dlightmap.value && s->dlightframe == r_dlightframecount) + || r_ambient.value != s->cached_ambient + || lighthalf != s->cached_lighthalf + || (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); + if (r_dlightmap.value || s->dlightframe != r_dlightframecount) { - if (s->cached_dlight - || (r_dlightmap.value && s->dlightframe == r_dlightframecount) - || r_ambient.value != s->cached_ambient - || lighthalf != s->cached_lighthalf - || (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); - } - wv = wvert; - for (p = s->polys;p;p = p->next) - { - for (i = 0, v = p->verts[0];i < p->numverts;i++, v += VERTEXSIZE) + // 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->texnum = (unsigned short) R_GetTexture(t->texture); + wp->lighttexnum = (unsigned short) (lightmap_textures + s->lightmaptexturenum); + wp->glowtexnum = (unsigned short) R_GetTexture(t->glowtexture); + wp->firstvert = currentwallvert; + wp->numverts = p->numverts; + wp->lit = lit; + wp++; + currentwallpoly++; + currentwallvert += p->numverts; + v = p->verts[0]; if (transform) - softwaretransform(v, wv); + { + for (i = 0;i < p->numverts;i++, v += VERTEXSIZE, out++) + { + softwaretransform(v, out->vert); + out->vert[3] = v[3]; + out->vert[4] = v[4]; + out->vert[5] = v[5]; + out->vert[6] = v[6]; + } + } else - VectorCopy(v, wv); - wv[3] = wv[4] = wv[5] = 0.0f; - wv += 6; + { + /* + for (i = 0;i < p->numverts;i++, v += VERTEXSIZE, out++) + { + VectorCopy(v, out->vert); + out->vert[3] = v[3]; + out->vert[4] = v[4]; + out->vert[5] = v[5]; + out->vert[6] = v[6]; + } + */ + memcpy(out, v, sizeof(vec_t) * VERTEXSIZE * p->numverts); + out += p->numverts; + } } - verts += p->numverts; - polys++; } - if ((currentwallpoly + polys > MAX_WALLPOLYS) || (currentwallvert+verts > MAX_WALLVERTS)) - return; - if ((!r_dlightmap.value) && s->dlightframe == r_dlightframecount) - lit = RSurf_Light(s->dlightbits, s->polys); - wv = wvert; - wp = &wallpoly[currentwallpoly]; - out = &wallvert[currentwallvert]; - currentwallpoly += polys; - for (p = s->polys;p;p = p->next) + else { - v = p->verts[0]; - wp->texnum = (unsigned short) t->gl_texturenum; - wp->lighttexnum = (unsigned short) (lightmap_textures + s->lightmaptexturenum); - wp->glowtexnum = (unsigned short) t->gl_glowtexturenum; - wp->firstvert = currentwallvert; - wp->numverts = p->numverts; - wp->lit = lit; - wp++; - currentwallvert += p->numverts; - for (i = 0;i < p->numverts;i++, v += VERTEXSIZE, wv += 6, out++) + float *wv; + wv = wvert; + for (p = s->polys;p;p = p->next) { - if (lit) + for (i = 0, v = p->verts[0];i < p->numverts;i++, v += VERTEXSIZE) { - if (lighthalf) - { - out->r = (byte) (bound(0, (int) wv[3] >> 1, 255)); - out->g = (byte) (bound(0, (int) wv[4] >> 1, 255)); - out->b = (byte) (bound(0, (int) wv[5] >> 1, 255)); - out->a = 255; - } + if (transform) + softwaretransform(v, wv); else + VectorCopy(v, wv); + wv[3] = wv[4] = wv[5] = 0.0f; + wv += 6; + } + verts += p->numverts; + polys++; + } + if ((currentwallpoly + polys > MAX_WALLPOLYS) || (currentwallvert+verts > MAX_WALLVERTS)) + return; + if ((!r_dlightmap.value) && s->dlightframe == r_dlightframecount) + lit = RSurf_Light(s->dlightbits, s->polys); + wv = wvert; + wp = &wallpoly[currentwallpoly]; + out = &wallvert[currentwallvert]; + outcolor = &wallvertcolor[currentwallvert]; + currentwallpoly += polys; + for (p = s->polys;p;p = p->next) + { + v = p->verts[0]; + wp->texnum = (unsigned short) R_GetTexture(t->texture); + wp->lighttexnum = (unsigned short) (lightmap_textures + s->lightmaptexturenum); + wp->glowtexnum = (unsigned short) R_GetTexture(t->glowtexture); + wp->firstvert = currentwallvert; + wp->numverts = p->numverts; + wp->lit = lit; + wp++; + currentwallvert += p->numverts; + for (i = 0;i < p->numverts;i++, v += VERTEXSIZE, wv += 6, out++, outcolor++) + { + if (lit) { - out->r = (byte) (bound(0, (int) wv[3], 255)); - out->g = (byte) (bound(0, (int) wv[4], 255)); - out->b = (byte) (bound(0, (int) wv[5], 255)); - out->a = 255; + if (lighthalf) + { + outcolor->r = (byte) (bound(0, (int) wv[3] >> 1, 255)); + outcolor->g = (byte) (bound(0, (int) wv[4] >> 1, 255)); + outcolor->b = (byte) (bound(0, (int) wv[5] >> 1, 255)); + outcolor->a = 255; + } + else + { + outcolor->r = (byte) (bound(0, (int) wv[3], 255)); + outcolor->g = (byte) (bound(0, (int) wv[4], 255)); + outcolor->b = (byte) (bound(0, (int) wv[5], 255)); + outcolor->a = 255; + } } + out->vert[0] = wv[0]; + out->vert[1] = wv[1]; + out->vert[2] = wv[2]; + out->vert[3] = v[3]; + out->vert[4] = v[4]; + out->vert[5] = v[5]; + out->vert[6] = v[6]; } - out->vert[0] = wv[0]; - out->vert[1] = wv[1]; - out->vert[2] = wv[2]; - out->s = v[3]; - out->t = v[4]; - out->u = v[5]; - out->v = v[6]; } } } @@ -720,7 +823,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(t->gl_texturenum, t->gl_glowtexturenum, 0, currententity->effects & EF_ADDITIVE ? TPOLYTYPE_ADD : TPOLYTYPE_ALPHA); + transpolybegin(R_GetTexture(t->texture), R_GetTexture(t->glowtexture), 0, currententity->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->colormod[0], wv[4] * currententity->colormod[1], wv[5] * currententity->colormod[2], alpha); transpolyend(); @@ -731,7 +834,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(t->gl_texturenum, t->gl_glowtexturenum, 0, currententity->effects & EF_ADDITIVE ? TPOLYTYPE_ADD : TPOLYTYPE_ALPHA); + transpolybegin(R_GetTexture(t->texture), R_GetTexture(t->glowtexture), 0, currententity->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(); @@ -1559,10 +1662,7 @@ void GL_BuildLightmaps (void) } if (!lightmap_textures) - { - lightmap_textures = texture_extension_number; - texture_extension_number += MAX_LIGHTMAPS; - } + lightmap_textures = R_GetTextureSlots(MAX_LIGHTMAPS); for (j=1 ; jinternalflags & GLTEXF_UPLOADED)) + { + GL_UploadTexture(glt); + if (!(glt->internalflags & GLTEXF_UPLOADED)) + Host_Error("R_GetTexture: unable to upload texture\n"); + } + return glt->texnum; +} typedef struct { @@ -42,7 +59,8 @@ typedef struct int minimize, maximize; } glmode_t; -glmode_t modes[] = { +glmode_t modes[] = +{ {"GL_NEAREST", GL_NEAREST, GL_NEAREST}, {"GL_LINEAR", GL_LINEAR, GL_LINEAR}, {"GL_NEAREST_MIPMAP_NEAREST", GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST}, @@ -92,7 +110,7 @@ void Draw_TextureMode_f (void) // change all the existing mipmap texture objects for (i=0, glt=gltextures ; imipmap) + if (glt->flags & TEXF_MIPMAP) { glBindTexture(GL_TEXTURE_2D, glt->texnum); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min); @@ -101,59 +119,45 @@ void Draw_TextureMode_f (void) } } -void GL_TextureStats_Print(char *name, int total, int crc, int mip, int alpha) +void GL_TextureStats_Print(char *name, int total, int total2, int loaded, int crc, int mip, int alpha, int total2valid) { - char n[64]; - int c = 0; if (!name[0]) name = ""; - while (name[c] && c < 28) - n[c++] = name[c]; - // no need to pad since the name was moved to last -// while (c < 28) -// n[c++] = ' '; - n[c] = 0; - Con_Printf("%5i %04X %s %s %s\n", total, crc, mip ? "yes" : "no ", alpha ? "yes " : "no ", n); + Con_Printf("%5iK %c%5iK%c %04X %s %s %s %s\n", total, total2valid ? ' ' : '(', total2, total2valid ? ' ' : ')', crc, loaded ? "loaded" : " ", mip ? "mip" : " ", alpha ? "alpha" : " ", name); } -void GL_TextureStats_f(void) +void GL_TextureStats_PrintTotal(void) { - int i, s = 0, sc = 0, t = 0; + int i, t = 0, p = 0, loaded = 0, loadedt = 0, loadedp = 0; gltexture_t *glt; - Con_Printf("kbytes crc mip alpha name\n"); for (i = 0, glt = gltextures;i < numgltextures;i++, glt++) { - GL_TextureStats_Print(glt->identifier, (glt->texeldatasize + 512) >> 10, glt->crc, glt->mipmap, glt->alpha); t += glt->texeldatasize; - if (glt->identifier[0] == '&') + p += glt->inputtexeldatasize; + if (glt->internalflags & GLTEXF_UPLOADED) { - sc++; - s += glt->texeldatasize; + loaded++; + loadedt += glt->texeldatasize; + loadedp += glt->inputtexeldatasize; } } - Con_Printf("%i textures, totalling %.3fMB, %i are (usually) unnecessary model skins totalling %.3fMB\n", numgltextures, t / 1048576.0, sc, s / 1048576.0); + Con_Printf("total: %i (%.3fMB, %.3fMB original), uploaded %i (%.3fMB, %.3fMB original), upload on demand %i (%.3fMB, %.3fMB original)\n", numgltextures, t / 1048576.0, p / 1048576.0, loaded, loadedt / 1048576.0, loadedp / 1048576.0, numgltextures - loaded, (t - loadedt) / 1048576.0, (p - loadedp) / 1048576.0); } -void GL_TextureStats_PrintTotal(void) +void GL_TextureStats_f(void) { - int i, s = 0, sc = 0, t = 0; + int i; gltexture_t *glt; + Con_Printf("kbytes original crc loaded mip alpha name\n"); for (i = 0, glt = gltextures;i < numgltextures;i++, glt++) - { - t += glt->texeldatasize; - if (glt->identifier[0] == '&') - { - sc++; - s += glt->texeldatasize; - } - } - Con_Printf("%i textures, totalling %.3fMB, %i are (usually) unnecessary model skins totalling %.3fMB\n", numgltextures, t / 1048576.0, sc, s / 1048576.0); + GL_TextureStats_Print(glt->identifier, (glt->texeldatasize + 1023) / 1024, (glt->inputtexeldatasize + 1023) / 1024, glt->internalflags & GLTEXF_UPLOADED, glt->crc, glt->flags & TEXF_MIPMAP, glt->flags & TEXF_ALPHA, glt->inputtexels != NULL); + GL_TextureStats_PrintTotal(); } char engineversion[40]; //void GL_UploadTexture (gltexture_t *glt); -void gl_textures_start() +void r_textures_start() { // int i; // gltexture_t *glt; @@ -161,38 +165,39 @@ void gl_textures_start() // GL_UploadTexture(glt); } -void gl_textures_shutdown() +void r_textures_shutdown() { } -void GL_Textures_Init (void) +void R_Textures_Init (void) { Cmd_AddCommand("r_texturestats", GL_TextureStats_f); - Cvar_RegisterVariable (&gl_max_size); - Cvar_RegisterVariable (&gl_picmip); - Cvar_RegisterVariable (&gl_lerpimages); + Cvar_RegisterVariable (&r_max_size); + Cvar_RegisterVariable (&r_picmip); + Cvar_RegisterVariable (&r_lerpimages); Cvar_RegisterVariable (&r_upload); + Cvar_RegisterVariable (&r_precachetextures); #ifdef NORENDER r_upload.value = 0; #endif // 3dfx can only handle 256 wide textures if (!Q_strncasecmp ((char *)gl_renderer, "3dfx",4) || strstr((char *)gl_renderer, "Glide")) - Cvar_Set ("gl_max_size", "256"); + Cvar_Set ("r_max_size", "256"); gltextures = qmalloc(sizeof(gltexture_t) * MAX_GLTEXTURES); memset(gltextures, 0, sizeof(gltexture_t) * MAX_GLTEXTURES); Cmd_AddCommand ("gl_texturemode", &Draw_TextureMode_f); - R_RegisterModule("GL_Textures", gl_textures_start, gl_textures_shutdown); + R_RegisterModule("R_Textures", r_textures_start, r_textures_shutdown); } /* ================ -GL_FindTexture +R_FindTexture ================ */ -int GL_FindTexture (char *identifier) +int R_FindTexture (char *identifier) { int i; gltexture_t *glt; @@ -206,7 +211,7 @@ int GL_FindTexture (char *identifier) return -1; } -void GL_ResampleTextureLerpLine (byte *in, byte *out, int inwidth, int outwidth) +void R_ResampleTextureLerpLine (byte *in, byte *out, int inwidth, int outwidth) { int j, xi, oldx = 0, f, fstep, l1, l2, endx; fstep = (int) (inwidth*65536.0f/outwidth); @@ -240,12 +245,12 @@ void GL_ResampleTextureLerpLine (byte *in, byte *out, int inwidth, int outwidth) /* ================ -GL_ResampleTexture +R_ResampleTexture ================ */ -void GL_ResampleTexture (void *indata, int inwidth, int inheight, void *outdata, int outwidth, int outheight) +void R_ResampleTexture (void *indata, int inwidth, int inheight, void *outdata, int outwidth, int outheight) { - if (gl_lerpimages.value) + if (r_lerpimages.value) { int i, j, yi, oldy, f, fstep, l1, l2, endy = (inheight-1); byte *inrow, *out, *row1, *row2; @@ -256,8 +261,8 @@ void GL_ResampleTexture (void *indata, int inwidth, int inheight, void *outdata, row2 = qmalloc(outwidth*4); inrow = indata; oldy = 0; - GL_ResampleTextureLerpLine (inrow, row1, inwidth, outwidth); - GL_ResampleTextureLerpLine (inrow + inwidth*4, row2, inwidth, outwidth); + R_ResampleTextureLerpLine (inrow, row1, inwidth, outwidth); + R_ResampleTextureLerpLine (inrow + inwidth*4, row2, inwidth, outwidth); for (i = 0, f = 0;i < outheight;i++,f += fstep) { yi = f >> 16; @@ -267,9 +272,9 @@ void GL_ResampleTexture (void *indata, int inwidth, int inheight, void *outdata, if (yi == oldy+1) memcpy(row1, row2, outwidth*4); else - GL_ResampleTextureLerpLine (inrow, row1, inwidth, outwidth); + R_ResampleTextureLerpLine (inrow, row1, inwidth, outwidth); if (yi < endy) - GL_ResampleTextureLerpLine (inrow + inwidth*4, row2, inwidth, outwidth); + R_ResampleTextureLerpLine (inrow + inwidth*4, row2, inwidth, outwidth); else memcpy(row2, row1, outwidth*4); oldy = yi; @@ -326,61 +331,6 @@ void GL_ResampleTexture (void *indata, int inwidth, int inheight, void *outdata, } } -void GL_FreeTexels(gltexture_t *glt) -{ - if (glt->texels[0]) - qfree(glt->texels[0]); - glt->texels[0] = 0; -} - -void GL_AllocTexels(gltexture_t *glt, int width, int height, int mipmapped) -{ - int i, w, h, size; - if (glt->texels[0]) - GL_FreeTexels(glt); - glt->texelsize[0][0] = width; - glt->texelsize[0][1] = height; - if (mipmapped) - { - size = 0; - w = width;h = height; - i = 0; - while (i < MAXMIPS) - { - glt->texelsize[i][0] = w; - glt->texelsize[i][1] = h; - glt->texels[i++] = (void *)size; - size += w*h*4; - if (w > 1) - { - w >>= 1; - if (h > 1) - h >>= 1; - } - else if (h > 1) - h >>= 1; - else - break; - } - glt->texeldatasize = size; - while (i < MAXMIPS) - glt->texels[i++] = NULL; - glt->texels[0] = qmalloc(size); - for (i = 1;i < MAXMIPS && glt->texels[i];i++) - glt->texels[i] += (int) glt->texels[0]; - } - else - { - size = width*height*4; - glt->texeldatasize = size; - glt->texels[0] = qmalloc(size); - for (i = 1;i < MAXMIPS;i++) - glt->texels[i] = NULL; - } - if (!glt->texels[0]) - Sys_Error("GL_AllocTexels: out of memory\n"); -} - // in can be the same as out void GL_MipReduce(byte *in, byte *out, int width, int height, int destwidth, int destheight) { @@ -451,18 +401,68 @@ void GL_MipReduce(byte *in, byte *out, int width, int height, int destwidth, int } } -void GL_UploadTexture (gltexture_t *glt) +void GL_Upload32(int glslot, byte *data, int width, int height, int flags) { - int mip, width, height; + int mip, width2, height2, width3, height3, internalformat; + byte *gammadata, *buffer; + if (!r_upload.value) return; - glBindTexture(GL_TEXTURE_2D, glt->texnum); - width = glt->width; - height = glt->height; - for (mip = 0;mip < MAXMIPS && glt->texels[mip];mip++) - glTexImage2D(GL_TEXTURE_2D, mip, glt->alpha ? 4 : 3, glt->texelsize[mip][0], glt->texelsize[mip][1], 0, GL_RGBA, GL_UNSIGNED_BYTE, glt->texels[mip]); - if (glt->mipmap) + + // 3 and 4 are converted by the driver to it's preferred format for the current display mode + internalformat = 3; + if (flags & TEXF_ALPHA) + internalformat = 4; + + // calculate power of 2 size + width2 = 1;while (width2 < width) width2 <<= 1; + height2 = 1;while (height2 < height) height2 <<= 1; + // calculate final size (mipmapped downward to this) + width3 = width2 >> (int) r_picmip.value; + height3 = height2 >> (int) r_picmip.value; + while (width3 > (int) r_max_size.value) width3 >>= 1; + while (height3 > (int) r_max_size.value) height3 >>= 1; + if (width3 < 1) width3 = 1; + if (height3 < 1) height3 = 1; + + gammadata = qmalloc(width*height*4); + buffer = qmalloc(width2*height2*4); + if (!gammadata || !buffer) + Host_Error("GL_Upload32: out of memory\n"); + + Image_CopyRGBAGamma(data, gammadata, width*height); + + R_ResampleTexture(gammadata, width, height, buffer, width2, height2); + + qfree(gammadata); + + while (width2 > width3 || height2 > height3) { + GL_MipReduce(buffer, buffer, width2, height2, width3, height3); + + if (width2 > width3) + width2 >>= 1; + if (height2 > height3) + height2 >>= 1; + } + + glBindTexture(GL_TEXTURE_2D, glslot); + mip = 0; + glTexImage2D(GL_TEXTURE_2D, mip++, internalformat, width2, height2, 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer); + if (flags & TEXF_MIPMAP) + { + while (width2 > 1 || height2 > 1) + { + GL_MipReduce(buffer, buffer, width2, height2, 1, 1); + + if (width2 > 1) + width2 >>= 1; + if (height2 > 1) + height2 >>= 1; + + glTexImage2D(GL_TEXTURE_2D, mip++, internalformat, width2, height2, 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer); + } + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max); } @@ -472,6 +472,64 @@ void GL_UploadTexture (gltexture_t *glt) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max); } glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + + qfree(buffer); +} + +void GL_Upload8 (int glslot, byte *data, int width, int height, int flags) +{ + byte *data32; + data32 = qmalloc(width*height*4); + Image_Copy8bitRGBA(data, data32, width*height, d_8to24table); + GL_Upload32(glslot, data32, width, height, flags); + qfree(data32); +} + +void GL_UploadTexture (gltexture_t *glt) +{ + if (glt->inputtexels == NULL) + return; + if (glt->flags & TEXF_RGBA) + GL_Upload32(glt->texnum, glt->inputtexels, glt->width, glt->height, glt->flags); + else // 8bit + GL_Upload8(glt->texnum, glt->inputtexels, glt->width, glt->height, glt->flags); + glt->internalflags |= GLTEXF_UPLOADED; + qfree(glt->inputtexels); + glt->inputtexels = NULL; +} + +int R_CalcTexelDataSize (int width, int height, int mipmapped) +{ + int width2, height2, size; + width2 = 1;while (width2 < width) width2 <<= 1; + height2 = 1;while (height2 < height) height2 <<= 1; + // calculate final size (mipmapped downward to this) + width2 >>= (int) r_picmip.value; + height2 >>= (int) r_picmip.value; + while (width2 > (int) r_max_size.value) width2 >>= 1; + while (height2 > (int) r_max_size.value) height2 >>= 1; + if (width2 < 1) width2 = 1; + if (height2 < 1) height2 = 1; + + size = 0; + if (mipmapped) + { + while (width2 > 1 || height2 > 1) + { + size += width2 * height2; + if (width2 > 1) + width2 >>= 1; + if (height2 > 1) + height2 >>= 1; + } + size++; // count the last 1x1 mipmap + } + else + size = width2*height2; + + size *= 4; // RGBA + + return size; } /* @@ -479,49 +537,77 @@ void GL_UploadTexture (gltexture_t *glt) GL_LoadTexture ================ */ -int GL_LoadTexture (char *identifier, int width, int height, byte *data, qboolean mipmap, qboolean alpha, int bytesperpixel) +rtexture_t *R_LoadTexture (char *identifier, int width, int height, byte *data, int flags) { + int i, bytesperpixel, internalflags, precache; + gltexture_t *glt; unsigned short crc; - int i, width2, height2, width3, height3, w, h, mip; - gltexture_t *glt, *freeglt; - // LordHavoc: texture caching, turned out to be a waste of time (and immense waste of diskspace) - //char cachefilename[1024], *cachefile; if (isDedicated) - return 1; + return NULL; - freeglt = NULL; + if (!identifier[0]) + Host_Error("R_LoadTexture: no identifier\n"); - // LordHavoc: do a CRC to confirm the data really is the same as previous occurances. - crc = CRC_Block(data, width*height*bytesperpixel); - // see if the texture is already present - if (identifier[0]) + // clear the alpha flag if the texture has no transparent pixels + if (flags & TEXF_ALPHA) { - for (i=0, glt=gltextures ; iinuse) + for (i = 0;i < width * height;i++) { - if (!strcmp (identifier, glt->identifier)) + if (data[i * 4 + 3] < 255) { - // LordHavoc: everyone hates cache mismatchs, so I fixed it - if (crc != glt->crc || width != glt->width || height != glt->height) - { - Con_DPrintf("GL_LoadTexture: cache mismatch, replacing old texture\n"); - goto GL_LoadTexture_setup; // drop out with glt pointing to the texture to replace - } - if ((gl_lerpimages.value != 0) != glt->lerped) - goto GL_LoadTexture_setup; // drop out with glt pointing to the texture to replace - return glt->texnum; + alpha = true; + break; } } - else - freeglt = glt; } + else + { + for (i = 0;i < width * height;i++) + { + if (data[i] == 255) + { + alpha = true; + break; + } + } + } + if (!alpha) + flags &= ~TEXF_ALPHA; } + + if (flags & TEXF_RGBA) + bytesperpixel = 4; else - i = 0; - // LordHavoc: although this could be an else condition as it was in the original id code, - // it is more clear this way + bytesperpixel = 1; + + internalflags = 0; + if (r_lerpimages.value != 0) + internalflags |= GLTEXF_LERPED; + + // LordHavoc: do a CRC to confirm the data really is the same as previous occurances. + crc = CRC_Block(data, width*height*bytesperpixel); + // see if the texture is already present + for (i=0, glt=gltextures ; iidentifier)) + { + // LordHavoc: everyone hates cache mismatchs, so I fixed it + if (crc != glt->crc || width != glt->width || height != glt->height || flags != glt->flags) + { + Con_DPrintf("GL_LoadTexture: cache mismatch, replacing old texture\n"); + goto GL_LoadTexture_setup; // drop out with glt pointing to the texture to replace + } + if (internalflags != glt->internalflags) + goto GL_LoadTexture_setup; // drop out with glt pointing to the texture to replace + return (rtexture_t *)glt; + } + } + +/* if (freeglt) { glt = freeglt; @@ -529,152 +615,52 @@ int GL_LoadTexture (char *identifier, int width, int height, byte *data, qboolea } else { +*/ // LordHavoc: check if there are still slots available if (numgltextures >= MAX_GLTEXTURES) Sys_Error ("GL_LoadTexture: ran out of texture slots (%d)\n", MAX_GLTEXTURES); glt = &gltextures[numgltextures++]; - glt->texnum = texture_extension_number; - texture_extension_number++; + glt->texnum = gl_texture_number++; strcpy (glt->identifier, identifier); - } +// } // LordHavoc: label to drop out of the loop into the setup code GL_LoadTexture_setup: - // calculate power of 2 size - width2 = 1;while (width2 < width) width2 <<= 1; - height2 = 1;while (height2 < height) height2 <<= 1; - // calculate final size (mipmapped downward to this) - width3 = width2 >> (int) gl_picmip.value; - height3 = height2 >> (int) gl_picmip.value; - while (width3 > (int) gl_max_size.value) width3 >>= 1; - while (height3 > (int) gl_max_size.value) height3 >>= 1; - if (width3 < 1) width3 = 1; - if (height3 < 1) height3 = 1; - - // final storage - GL_AllocTexels(glt, width3, height3, mipmap); glt->crc = crc; // LordHavoc: used to verify textures are identical glt->width = width; glt->height = height; - glt->mipmap = mipmap; - glt->bytesperpixel = bytesperpixel; - glt->lerped = gl_lerpimages.value != 0; - glt->alpha = false; // updated later - glt->inuse = true; - /* - // LordHavoc: texture caching, turned out to be a waste of time (and immense waste of diskspace) - sprintf(cachefilename, "%s%x%x%x.texels", identifier, width3, height3, crc); - for (i = 0;cachefilename[i];i++) - { - if (cachefilename[i] <= ' ' || cachefilename[i] >= 127 || cachefilename[i] == '/' || cachefilename[i] == '\\' || cachefilename[i] == ':' || cachefilename[i] == '*' || cachefilename[i] == '?') - cachefilename[i] = '@'; - if (cachefilename[i] >= 'A' && cachefilename[i] <= 'Z') - cachefilename[i] += 'a' - 'A'; - } - cachefile = COM_LoadMallocFile(cachefilename, true); - if (cachefile) - { - if (cachefile[0] == 'D' && cachefile[1] == 'P' && cachefile[2] == 'C' && cachefile[3] == 'T') - { - memcpy(glt->texels[0], cachefile + 4, width3*height3*4); - qfree(cachefile); -// Con_Printf("loaded cache texture %s\n", cachefilename); - goto cacheloaded; - } - else - qfree(cachefile); - } - */ - if (width == width3 && height == height3) // perfect match - { - if (bytesperpixel == 1) // 8bit - Image_Copy8bitRGBA(data, glt->texels[0], width*height, d_8to24table); - else - Image_CopyRGBAGamma(data, glt->texels[0], width*height); - } - else if (width == width2 && height == height2) // perfect match for top level, but needs to be reduced - { - byte *temptexels2; - temptexels2 = qmalloc(width2*height2*4); // scaleup buffer - if (bytesperpixel == 1) // 8bit - Image_Copy8bitRGBA(data, temptexels2, width*height, d_8to24table); - else - Image_CopyRGBAGamma(data, temptexels2, width*height); - while (width2 > width3 || height2 > height3) - { - w = width2;h = height2; - if (width2 > width3) width2 >>= 1; - if (height2 > height3) height2 >>= 1; - if (width2 <= width3 && height2 <= height3) // size achieved - GL_MipReduce(temptexels2, glt->texels[0], w, h, width3, height3); - else - GL_MipReduce(temptexels2, temptexels2, w, h, width3, height3); - } - qfree(temptexels2); - } - else // scaling... - { - byte *temptexels; - // pre-scaleup buffer - temptexels = qmalloc(width*height*4); - if (bytesperpixel == 1) // 8bit - Image_Copy8bitRGBA(data, temptexels, width*height, d_8to24table); - else - Image_CopyRGBAGamma(data, temptexels, width*height); - if (width2 != width3 || height2 != height3) // reduced by gl_pic_mip or gl_max_size - { - byte *temptexels2; - temptexels2 = qmalloc(width2*height2*4); // scaleup buffer - GL_ResampleTexture(temptexels, width, height, temptexels2, width2, height2); - while (width2 > width3 || height2 > height3) - { - w = width2;h = height2; - if (width2 > width3) width2 >>= 1; - if (height2 > height3) height2 >>= 1; - if (width2 <= width3 && height2 <= height3) // size achieved - GL_MipReduce(temptexels2, glt->texels[0], w, h, width3, height3); - else - GL_MipReduce(temptexels2, temptexels2, w, h, width3, height3); - } - qfree(temptexels2); - } - else // copy directly - GL_ResampleTexture(temptexels, width, height, glt->texels[0], width2, height2); - qfree(temptexels); - } - /* - // LordHavoc: texture caching, turned out to be a waste of time (and immense waste of diskspace) - Con_Printf("writing cache texture %s\n", cachefilename); - cachefile = qmalloc(width3*height3*4 + 4); - cachefile[0] = 'D'; - cachefile[1] = 'P'; - cachefile[2] = 'C'; - cachefile[3] = 'T'; - memcpy(cachefile + 4, glt->texels[0], width3*height3*4); - COM_WriteFile(cachefilename, cachefile, width3*height3*4 + 4); - qfree(cachefile); -cacheloaded: - */ - if (alpha) + glt->flags = flags; + glt->internalflags = internalflags; + + if (glt->inputtexels) + qfree(glt->inputtexels); + glt->inputtexeldatasize = width*height*bytesperpixel; + glt->inputtexels = qmalloc(glt->inputtexeldatasize); + + memcpy(glt->inputtexels, data, glt->inputtexeldatasize); + + glt->texeldatasize = R_CalcTexelDataSize(width, height, flags & TEXF_MIPMAP); + + precache = false; + if (r_precachetextures.value >= 1) { - byte *in = glt->texels[0] + 3; - for (i = 0;i < width*height;i++, in += 4) - if (*in < 255) - { - glt->alpha = true; - break; - } + if (flags & TEXF_PRECACHE) + precache = true; + if (r_precachetextures.value >= 2) + precache = true; } - // this loop is skipped if there are no mipmaps to generate - for (mip = 1;mip < MAXMIPS && glt->texels[mip];mip++) - GL_MipReduce(glt->texels[mip-1], glt->texels[mip], glt->texelsize[mip-1][0], glt->texelsize[mip-1][1], 1, 1); - GL_UploadTexture(glt); - GL_FreeTexels(glt); -// if (bytesperpixel == 1) // 8bit -// GL_Upload8 (data, width, height, mipmap, alpha); -// else // 32bit -// GL_Upload32 (data, width, height, mipmap, true); + if (precache) + GL_UploadTexture(glt); - return glt->texnum; + return (rtexture_t *)glt; +} + +// only used for lightmaps +int R_GetTextureSlots(int count) +{ + int i; + i = gl_texture_number; + gl_texture_number += count; + return i; } diff --git a/gl_warp.c b/gl_warp.c index 5b37779c..c3ccd0d2 100644 --- a/gl_warp.c +++ b/gl_warp.c @@ -25,8 +25,8 @@ extern model_t *loadmodel; int skytexturenum; -int solidskytexture; -int alphaskytexture; +rtexture_t *solidskytexture; +rtexture_t *alphaskytexture; float speedscale; // for top sky and bottom sky msurface_t *warpface; @@ -176,7 +176,7 @@ void GL_SubdivideSurface (msurface_t *fa) -int skyboxside[6]; +rtexture_t *skyboxside[6]; char skyname[256]; @@ -211,7 +211,7 @@ void R_LoadSkyBox (void) continue; } } - skyboxside[i] = GL_LoadTexture(va("skyboxside%d", i), image_width, image_height, image_rgba, false, false, 4); + skyboxside[i] = R_LoadTexture(va("skyboxside%d", i), image_width, image_height, image_rgba, TEXF_RGBA | TEXF_PRECACHE); qfree(image_rgba); } } @@ -257,42 +257,42 @@ void R_SkyBox() glColor3f(0.5,0.5,0.5); else glColor3f(1,1,1); - glBindTexture(GL_TEXTURE_2D, skyboxside[3]); // front + glBindTexture(GL_TEXTURE_2D, R_GetTexture(skyboxside[3])); // front glBegin(GL_QUADS); R_SkyBoxPolyVec(1, 0, 1, -1, 1); R_SkyBoxPolyVec(1, 1, 1, -1, -1); R_SkyBoxPolyVec(0, 1, 1, 1, -1); R_SkyBoxPolyVec(0, 0, 1, 1, 1); glEnd(); - glBindTexture(GL_TEXTURE_2D, skyboxside[1]); // back + glBindTexture(GL_TEXTURE_2D, R_GetTexture(skyboxside[1])); // back glBegin(GL_QUADS); R_SkyBoxPolyVec(1, 0, -1, 1, 1); R_SkyBoxPolyVec(1, 1, -1, 1, -1); R_SkyBoxPolyVec(0, 1, -1, -1, -1); R_SkyBoxPolyVec(0, 0, -1, -1, 1); glEnd(); - glBindTexture(GL_TEXTURE_2D, skyboxside[0]); // right + glBindTexture(GL_TEXTURE_2D, R_GetTexture(skyboxside[0])); // right glBegin(GL_QUADS); R_SkyBoxPolyVec(1, 0, 1, 1, 1); R_SkyBoxPolyVec(1, 1, 1, 1, -1); R_SkyBoxPolyVec(0, 1, -1, 1, -1); R_SkyBoxPolyVec(0, 0, -1, 1, 1); glEnd(); - glBindTexture(GL_TEXTURE_2D, skyboxside[2]); // left + glBindTexture(GL_TEXTURE_2D, R_GetTexture(skyboxside[2])); // left glBegin(GL_QUADS); R_SkyBoxPolyVec(1, 0, -1, -1, 1); R_SkyBoxPolyVec(1, 1, -1, -1, -1); R_SkyBoxPolyVec(0, 1, 1, -1, -1); R_SkyBoxPolyVec(0, 0, 1, -1, 1); glEnd(); - glBindTexture(GL_TEXTURE_2D, skyboxside[4]); // up + glBindTexture(GL_TEXTURE_2D, R_GetTexture(skyboxside[4])); // up glBegin(GL_QUADS); R_SkyBoxPolyVec(1, 0, 1, -1, 1); R_SkyBoxPolyVec(1, 1, 1, 1, 1); R_SkyBoxPolyVec(0, 1, -1, 1, 1); R_SkyBoxPolyVec(0, 0, -1, -1, 1); glEnd(); - glBindTexture(GL_TEXTURE_2D, skyboxside[5]); // down + glBindTexture(GL_TEXTURE_2D, R_GetTexture(skyboxside[5])); // down glBegin(GL_QUADS); R_SkyBoxPolyVec(1, 0, 1, 1, -1); R_SkyBoxPolyVec(1, 1, 1, -1, -1); @@ -331,7 +331,6 @@ void skydomecalc(float *dome, float dx, float dy, float dz) } } -extern cvar_t gl_vertexarrays; void skydome(float *source, float s, float texscale) { vec_t vert[33*33][3], tex[33*33][2], *v, *t; @@ -346,33 +345,15 @@ void skydome(float *source, float s, float texscale) *v++ = *source++ + r_refdef.vieworg[1]; *v++ = *source++ + r_refdef.vieworg[2]; } - if (gl_vertexarrays.value) - { - qglTexCoordPointer(2, GL_FLOAT, 0, tex); - qglVertexPointer(3, GL_FLOAT, 0, vert); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - glEnableClientState(GL_VERTEX_ARRAY); -// qglInterleavedArrays(GL_T2F_V3F, 0, vert); - for (i = 0;i < (32*66);i+=66) - qglDrawElements(GL_TRIANGLE_STRIP, 66, GL_UNSIGNED_SHORT, &skydomeindices[i]); - glDisableClientState(GL_VERTEX_ARRAY); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - } - else - { - index = skydomeindices; - for (i = 0;i < (32*66);i+=66) - { - glBegin(GL_TRIANGLE_STRIP); - for (j = 0;j < 66;j++) - { - // Matrox G200 (and possibly G400) drivers don't support TexCoord2fv... - glTexCoord2f(tex[*index][0], tex[*index][1]); - glVertex3fv(&vert[*index++][0]); - } - glEnd(); - } - } + glTexCoordPointer(2, GL_FLOAT, 0, tex); + glVertexPointer(3, GL_FLOAT, 0, vert); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glEnableClientState(GL_VERTEX_ARRAY); +// glInterleavedArrays(GL_T2F_V3F, 0, vert); + for (i = 0;i < (32*66);i+=66) + glDrawElements(GL_TRIANGLE_STRIP, 66, GL_UNSIGNED_SHORT, &skydomeindices[i]); + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); } void R_SkyDome() @@ -465,7 +446,7 @@ void R_InitSky (byte *src, int bytesperpixel) ((byte *)&transpix)[3] = 0; } - solidskytexture = GL_LoadTexture ("sky_solidtexture", 128, 128, (byte *) trans, false, false, 4); + solidskytexture = R_LoadTexture ("sky_solidtexture", 128, 128, (byte *) trans, TEXF_RGBA | TEXF_PRECACHE); if (bytesperpixel == 4) { @@ -486,6 +467,6 @@ void R_InitSky (byte *src, int bytesperpixel) } } - alphaskytexture = GL_LoadTexture ("sky_alphatexture", 128, 128, (byte *) trans, false, true, 4); + alphaskytexture = R_LoadTexture ("sky_alphatexture", 128, 128, (byte *) trans, TEXF_ALPHA | TEXF_RGBA | TEXF_PRECACHE); } diff --git a/glquake.h b/glquake.h index b6d2d32b..c9e0e039 100644 --- a/glquake.h +++ b/glquake.h @@ -37,18 +37,16 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include //#include +extern qboolean isG200; +extern qboolean isRagePro; +extern qboolean gl_mtexable; +extern qboolean gl_supportslockarrays; + extern void GL_BeginRendering (int *x, int *y, int *width, int *height); extern void GL_EndRendering (void); -extern int texture_extension_number; - extern float gldepthmin, gldepthmax; -extern void GL_Upload32 (void *data, int width, int height, qboolean mipmap, qboolean alpha); -extern void GL_Upload8 (byte *data, int width, int height, qboolean mipmap, qboolean alpha); -extern int GL_LoadTexture (char *identifier, int width, int height, byte *data, qboolean mipmap, qboolean alpha, int bytesperpixel); -extern int GL_FindTexture (char *identifier); - typedef struct { float x, y, z; @@ -109,14 +107,11 @@ extern cvar_t r_drawentities; extern cvar_t r_drawviewmodel; extern cvar_t r_speeds; extern cvar_t r_fullbright; -extern cvar_t r_shadows; extern cvar_t r_wateralpha; extern cvar_t r_dynamic; extern cvar_t r_novis; extern cvar_t r_waterripple; -extern cvar_t gl_max_size; - extern float r_world_matrix[16]; extern const char *gl_vendor; @@ -132,8 +127,6 @@ extern const char *gl_extensions; #define APIENTRY /* */ #endif -extern qboolean gl_mtexable; - // LordHavoc: ARB multitexure support extern int gl_mtex_enum; @@ -142,13 +135,15 @@ extern int gl_mtex_enum; #define GLAPIENTRY APIENTRY #endif -// Micro$oft dropped GL support beyond 1.1, so... -#ifdef WIN32 +// multitexture +extern void (GLAPIENTRY *qglMTexCoord2f) (GLenum, GLfloat, GLfloat); +extern void (GLAPIENTRY *qglSelectTexture) (GLenum); +extern void (GLAPIENTRY *qglLockArraysEXT) (GLint first, GLint count); +extern void (GLAPIENTRY *qglUnlockArraysEXT) (void); -//#define GL_POLYGON_OFFSET_POINT 0x2A01 -//#define GL_POLYGON_OFFSET_LINE 0x2A02 -//#define GL_POLYGON_OFFSET_FILL 0x8037 +#ifndef GL_ACTIVE_TEXTURE_ARB +// multitexture #define GL_ACTIVE_TEXTURE_ARB 0x84E0 #define GL_CLIENT_ACTIVE_TEXTURE_ARB 0x84E1 #define GL_MAX_TEXTURES_UNITS_ARB 0x84E2 @@ -157,39 +152,10 @@ extern int gl_mtex_enum; #define GL_TEXTURE2_ARB 0x84C2 #define GL_TEXTURE3_ARB 0x84C3 // LordHavoc: ARB supports 32+ texture units, but hey I only use 2 anyway... +#endif -// LordHavoc: vertex array defines -#define GL_VERTEX_ARRAY 0x8074 -#define GL_NORMAL_ARRAY 0x8075 -#define GL_COLOR_ARRAY 0x8076 -#define GL_TEXTURE_COORD_ARRAY 0x8078 - -//extern void (GLAPIENTRY *qglPolygonOffset)(GLfloat factor, GLfloat units); -extern void (GLAPIENTRY *qglVertexPointer)(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr); -//extern void (GLAPIENTRY *qglNormalPointer)(GLenum type, GLsizei stride, const GLvoid *ptr); -extern void (GLAPIENTRY *qglColorPointer)(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr); -extern void (GLAPIENTRY *qglTexCoordPointer)(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr); -extern void (GLAPIENTRY *qglArrayElement)(GLint i); -//extern void (GLAPIENTRY *qglDrawArrays)(GLenum mode, GLint first, GLsizei count); -extern void (GLAPIENTRY *qglDrawElements)(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices); - -extern void (GLAPIENTRY *qglMTexCoord2f) (GLenum, GLfloat, GLfloat); -extern void (GLAPIENTRY *qglSelectTexture) (GLenum); -//extern void (GLAPIENTRY *glColorTableEXT)(int, int, int, int, int, const void*); - +#ifdef WIN32 #else - -//#define qglPolygonOffset glPolygonOffset -#define qglVertexPointer glVertexPointer -//#define qglNormalPointer glNormalPointer -#define qglColorPointer glColorPointer -#define qglTexCoordPointer glTexCoordPointer -#define qglArrayElement glArrayElement -//#define qglDrawArrays glDrawArrays -#define qglDrawElements glDrawElements - -extern void (GLAPIENTRY *qglMTexCoord2f) (GLenum, GLfloat, GLfloat); -extern void (GLAPIENTRY *qglSelectTexture) (GLenum); //#ifndef MESA //extern void (GLAPIENTRY *glColorTableEXT)(int, int, int, int, int, const void*); //#endif @@ -220,10 +186,14 @@ extern vec_t fogdensity; #include "r_modules.h" -extern cvar_t gl_vertexarrays; extern qboolean lighthalf; -extern void R_DrawAliasModel (entity_t *ent, int cull, float alpha, model_t *clmodel, int frame, int skin, vec3_t org, vec3_t angles, int effects, int flags, int colormap); +#include "r_lerpanim.h" + +void GL_LockArray(int first, int count); +void GL_UnlockArray(); + +void R_DrawAliasModel (entity_t *ent, int cull, float alpha, model_t *clmodel, frameblend_t *blend, int skin, vec3_t org, vec3_t angles, vec_t scale, int effects, int flags, int colormap); extern cvar_t r_render; extern cvar_t r_upload; diff --git a/host.c b/host.c index e179da68..3d687b6d 100644 --- a/host.c +++ b/host.c @@ -23,7 +23,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. /* -A server can allways be started, even if the system started out as a client +A server can always be started, even if the system started out as a client to a remote system. A client can NOT be started if the system started as a dedicated server. @@ -35,6 +35,7 @@ Memory is cleared / released when a server or client begins, not when they end. quakeparms_t host_parms; qboolean host_initialized; // true if into command execution +qboolean hostloopactive = 0; // LordHavoc: used to turn Host_Error into Sys_Error if Host_Frame has not yet run double host_frametime; double host_realframetime; // LordHavoc: the real frametime, before slowmo and clamping are applied (used for console scrolling) @@ -118,15 +119,26 @@ Host_Error This shuts down both the client and server ================ */ -char hosterrorstring[1024]; +char hosterrorstring[4096]; +extern qboolean hostloopactive; void Host_Error (char *error, ...) { va_list argptr; static qboolean inerror = false; - + + // LordHavoc: if host_frame loop has not been run yet, do a Sys_Error instead + if (!hostloopactive) + { + char string[4096]; + va_start (argptr,error); + vsprintf (string,error,argptr); + va_end (argptr); + Sys_Error ("%s", string); + } + if (inerror) { - char string[1024]; + char string[4096]; va_start (argptr,error); vsprintf (string,error,argptr); va_end (argptr); @@ -538,6 +550,7 @@ qboolean Host_FilterTime (float time) } host_frametime *= slowmo.value; + cl.frametime = host_frametime; return true; } @@ -570,16 +583,17 @@ Host_ServerFrame ================== */ -double frametimetotal = 0, lastservertime = 0; void Host_ServerFrame (void) { + static double frametimetotal = 0, lastservertime = 0; frametimetotal += host_frametime; // LordHavoc: cap server at sys_ticrate in listen games if (!isDedicated && svs.maxclients > 1 && ((realtime - lastservertime) < sys_ticrate.value)) return; // run the world state - sv_frametime = pr_global_struct->frametime = frametimetotal; + sv.frametime = pr_global_struct->frametime = frametimetotal; frametimetotal = 0; + lastservertime = realtime; // pr_global_struct->frametime = host_frametime; // set the time and clear the general datagram @@ -617,6 +631,7 @@ void _Host_Frame (float time) if (setjmp (host_abortserver) ) return; // something bad happened, or the server disconnected + hostloopactive = 1; // keep the random time dependent rand (); @@ -667,9 +682,7 @@ void _Host_Frame (float time) // fetch results from server if (cls.state == ca_connected) - { CL_ReadFromServer (); - } // update video if (host_speeds.value) @@ -693,11 +706,11 @@ void _Host_Frame (float time) if (host_speeds.value) { - pass1 = (time1 - time3)*1000; + pass1 = (time1 - time3)*1000000; time3 = Sys_FloatTime (); - pass2 = (time2 - time1)*1000; - pass3 = (time3 - time2)*1000; - Con_Printf ("%3i tot %3i server %3i gfx %3i snd\n", + pass2 = (time2 - time1)*1000000; + pass3 = (time3 - time2)*1000000; + Con_Printf ("%6ius total %6ius server %6ius gfx %6ius snd\n", pass1+pass2+pass3, pass1, pass2, pass3); } diff --git a/host_cmd.c b/host_cmd.c index 4783279d..f9f32256 100644 --- a/host_cmd.c +++ b/host_cmd.c @@ -923,7 +923,7 @@ void Host_Kill_f (void) if (sv_player->v.health <= 0) { - SV_ClientPrintf ("Can't suicide -- allready dead!\n"); + SV_ClientPrintf ("Can't suicide -- already dead!\n"); return; } @@ -985,7 +985,7 @@ void Host_PreSpawn_f (void) if (host_client->spawned) { - Con_Printf ("prespawn not valid -- allready spawned\n"); + Con_Printf ("prespawn not valid -- already spawned\n"); return; } @@ -1016,7 +1016,7 @@ void Host_Spawn_f (void) if (host_client->spawned) { - Con_Printf ("Spawn not valid -- allready spawned\n"); + Con_Printf ("Spawn not valid -- already spawned\n"); return; } @@ -1026,7 +1026,7 @@ void Host_Spawn_f (void) // run the entrance script if (sv.loadgame) - { // loaded games are fully inited allready + { // loaded games are fully inited already // if this is the last client to be connected, unpause sv.paused = false; @@ -1469,59 +1469,12 @@ void Host_Viewframe_f (void) void PrintFrameName (model_t *m, int frame) { - if (m->type != mod_alias) - return; - switch(m->aliastype) - { - case ALIASTYPE_MDL: - { - maliashdr_t *mheader; - maliasframe_t *frameinfo; - - mheader = (maliashdr_t *)Mod_Extradata (m); - if (!mheader) - return; - if (frame < 0 || frame >= mheader->numframes) - frame = 0; - frameinfo = &((maliasframe_t *)(mheader->framedata + (int) mheader))[frame]; - - Con_Printf ("frame %i: %s\n", frame, frameinfo->name); - } - break; - case ALIASTYPE_MD2: - { - md2mem_t *mheader; - md2memframe_t *frameinfo; - - mheader = (md2mem_t *)Mod_Extradata (m); - if (!mheader) - return; - if (frame < 0 || frame >= mheader->num_frames) - frame = 0; - frameinfo = (md2memframe_t *)(mheader->ofs_frames + (int) mheader) + frame; - - Con_Printf ("frame %i: %s\n", frame, frameinfo->name); - } - break; - case ALIASTYPE_ZYM: - { - zymtype1header_t *mheader; - zymscene_t *scene; - - mheader = (zymtype1header_t *)Mod_Extradata (m); - if (!mheader) - return; - if (frame < 0 || frame >= mheader->numscenes) - frame = 0; - scene = (zymscene_t *)(mheader->lump_scenes.start + (int) mheader) + frame; - - Con_Printf ("frame %i: %s\n", frame, scene->name); - } - break; - default: - Con_Printf("frame %i: (unknown alias model type)\n", frame); - break; - } + int data; + data = (int) Mod_Extradata(m); + if (m->ofs_scenes && data) + Con_Printf("frame %i: %s\n", frame, ((animscene_t *) (m->ofs_scenes + data))[frame].name); + else + Con_Printf("frame %i\n", frame); } /* diff --git a/image.c b/image.c index 622ff526..7b05a23f 100644 --- a/image.c +++ b/image.c @@ -490,48 +490,49 @@ byte* loadimagepixelsmask (char* filename, qboolean complain, int matchwidth, in } } -int loadtextureimage (char* filename, int matchwidth, int matchheight, qboolean complain, qboolean mipmap) +rtexture_t *loadtextureimage (char* filename, int matchwidth, int matchheight, qboolean complain, qboolean mipmap, qboolean precache) { - int texnum; byte *data; + rtexture_t *rt; if (!(data = loadimagepixels (filename, complain, matchwidth, matchheight))) return 0; - texnum = GL_LoadTexture (filename, image_width, image_height, data, mipmap, true, 4); + rt = R_LoadTexture (filename, image_width, image_height, data, TEXF_ALPHA | TEXF_RGBA | (mipmap ? TEXF_MIPMAP : 0) | (mipmap ? TEXF_PRECACHE : 0)); qfree(data); - return texnum; + return rt; } -int loadtextureimagemask (char* filename, int matchwidth, int matchheight, qboolean complain, qboolean mipmap) +rtexture_t *loadtextureimagemask (char* filename, int matchwidth, int matchheight, qboolean complain, qboolean mipmap, qboolean precache) { - int texnum; byte *data; + rtexture_t *rt; if (!(data = loadimagepixelsmask (filename, complain, matchwidth, matchheight))) return 0; - texnum = GL_LoadTexture (filename, image_width, image_height, data, mipmap, true, 4); + rt = R_LoadTexture (filename, image_width, image_height, data, TEXF_ALPHA | TEXF_RGBA | (mipmap ? TEXF_MIPMAP : 0) | (mipmap ? TEXF_PRECACHE : 0)); qfree(data); - return texnum; + return rt; } -int image_masktexnum; -int loadtextureimagewithmask (char* filename, int matchwidth, int matchheight, qboolean complain, qboolean mipmap) +rtexture_t *image_masktex; +rtexture_t *loadtextureimagewithmask (char* filename, int matchwidth, int matchheight, qboolean complain, qboolean mipmap, qboolean precache) { - int texnum, count; + int count; byte *data; char *filename2; - image_masktexnum = 0; + rtexture_t *rt; + image_masktex = NULL; if (!(data = loadimagepixels (filename, complain, matchwidth, matchheight))) return 0; - texnum = GL_LoadTexture (filename, image_width, image_height, data, mipmap, true, 4); + rt = R_LoadTexture (filename, image_width, image_height, data, TEXF_ALPHA | TEXF_RGBA | (mipmap ? TEXF_MIPMAP : 0) | (mipmap ? TEXF_PRECACHE : 0)); count = image_makemask(data, data, image_width * image_height); if (count) { filename2 = qmalloc(strlen(filename) + 6); sprintf(filename2, "%s_mask", filename); - image_masktexnum = GL_LoadTexture (filename2, image_width, image_height, data, mipmap, true, 4); + image_masktex = R_LoadTexture (filename2, image_width, image_height, data, TEXF_ALPHA | TEXF_RGBA | (mipmap ? TEXF_MIPMAP : 0) | (mipmap ? TEXF_PRECACHE : 0)); qfree(filename2); } qfree(data); - return texnum; + return rt; } void Image_WriteTGARGB_preflipped (char *filename, int width, int height, byte *data) diff --git a/image.h b/image.h index ebaafd58..60a9759c 100644 --- a/image.h +++ b/image.h @@ -3,11 +3,11 @@ extern void Image_Copy8bitRGBA(byte *in, byte *out, int pixels, int *pal); extern void Image_CopyRGBAGamma(byte *in, byte *out, int pixels); extern int image_makemask (byte *in, byte *out, int size); extern byte* loadimagepixels (char* filename, qboolean complain, int matchwidth, int matchheight); -extern int loadtextureimage (char* filename, int matchwidth, int matchheight, qboolean complain, qboolean mipmap); +extern rtexture_t *loadtextureimage (char* filename, int matchwidth, int matchheight, qboolean complain, qboolean mipmap, qboolean precache); extern byte* loadimagepixelsmask (char* filename, qboolean complain, int matchwidth, int matchheight); -extern int loadtextureimagemask (char* filename, int matchwidth, int matchheight, qboolean complain, qboolean mipmap); -extern int image_masktexnum; -extern int loadtextureimagewithmask (char* filename, int matchwidth, int matchheight, qboolean complain, qboolean mipmap); +extern rtexture_t *loadtextureimagemask (char* filename, int matchwidth, int matchheight, qboolean complain, qboolean mipmap, qboolean precache); +extern rtexture_t *image_masktex; +extern rtexture_t *loadtextureimagewithmask (char* filename, int matchwidth, int matchheight, qboolean complain, qboolean mipmap, qboolean precache); extern void Image_WriteTGARGB_preflipped (char *filename, int width, int height, byte *data); extern void Image_WriteTGARGB (char *filename, int width, int height, byte *data); extern void Image_WriteTGARGBA (char *filename, int width, int height, byte *data); diff --git a/in_svgalib.c b/in_svgalib.c index 524d0d0f..ea8460d7 100644 --- a/in_svgalib.c +++ b/in_svgalib.c @@ -355,13 +355,14 @@ void IN_Move(usercmd_t *cmd) if ((in_mlook.state & 1)) V_StopPitchDrift(); + // LordHavoc: changed limits on pitch from -70 to 80, to -90 to 90 if ((in_mlook.state & 1) && !(in_strafe.state & 1)) { cl.viewangles[PITCH] += m_pitch.value * mouse_y; - if (cl.viewangles[PITCH] > 80) { - cl.viewangles[PITCH] = 80; + if (cl.viewangles[PITCH] > 90) { + cl.viewangles[PITCH] = 90; } - if (cl.viewangles[PITCH] < -70) { - cl.viewangles[PITCH] = -70; + if (cl.viewangles[PITCH] < -90) { + cl.viewangles[PITCH] = -90; } } else { if ((in_strafe.state & 1) && noclip_anglehack) { diff --git a/in_win.c b/in_win.c index 9b9f4fcb..fb055bbb 100644 --- a/in_win.c +++ b/in_win.c @@ -702,14 +702,15 @@ void IN_MouseMove (usercmd_t *cmd) if (in_mlook.state & 1) V_StopPitchDrift (); - + + // LordHavoc: changed limits on pitch from -70 to 80, to -90 to 90 if ( (in_mlook.state & 1) && !(in_strafe.state & 1)) { cl.viewangles[PITCH] += m_pitch.value * mouse_y; - if (cl.viewangles[PITCH] > 80) - cl.viewangles[PITCH] = 80; - if (cl.viewangles[PITCH] < -70) - cl.viewangles[PITCH] = -70; + if (cl.viewangles[PITCH] > 90) + cl.viewangles[PITCH] = 90; + if (cl.viewangles[PITCH] < -90) + cl.viewangles[PITCH] = -90; } else { @@ -1090,7 +1091,7 @@ void IN_JoyMove (usercmd_t *cmd) speed = cl_movespeedkey.value; else speed = 1; - aspeed = speed * host_frametime; + aspeed = speed * host_realframetime; // loop through the axes for (i = 0; i < JOY_MAX_AXES; i++) diff --git a/makefile b/makefile index 6d54c3fb..ea8fb191 100644 --- a/makefile +++ b/makefile @@ -1,5 +1,13 @@ + +#uncomment one of these according to your sound driver +#if you use ALSA version 0.9.x SND=snd_alsa_0_9.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 cpu_noasm.o crc.o cvar.o fractalnoise.o gl_draw.o gl_poly.o gl_refrag.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 net_vcr.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 +#if you use ALSA version 0.5.x +#SND=snd_alsa_0_5.o +#if you use the kernel sound driver or OSS +#SND=snd_oss.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_refrag.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 net_vcr.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 OPTIMIZATIONS= -O6 -ffast-math -funroll-loops -fomit-frame-pointer -fexpensive-optimizations diff --git a/mathlib.c b/mathlib.c index ba4f3d4a..9d847add 100644 --- a/mathlib.c +++ b/mathlib.c @@ -31,8 +31,125 @@ int nanmask = 255<<23; #define DEG2RAD( a ) ( a * M_PI ) / 180.0F +float m_bytenormals[NUMVERTEXNORMALS][3] = +{ +{-0.525731, 0.000000, 0.850651}, {-0.442863, 0.238856, 0.864188}, +{-0.295242, 0.000000, 0.955423}, {-0.309017, 0.500000, 0.809017}, +{-0.162460, 0.262866, 0.951056}, {0.000000, 0.000000, 1.000000}, +{0.000000, 0.850651, 0.525731}, {-0.147621, 0.716567, 0.681718}, +{0.147621, 0.716567, 0.681718}, {0.000000, 0.525731, 0.850651}, +{0.309017, 0.500000, 0.809017}, {0.525731, 0.000000, 0.850651}, +{0.295242, 0.000000, 0.955423}, {0.442863, 0.238856, 0.864188}, +{0.162460, 0.262866, 0.951056}, {-0.681718, 0.147621, 0.716567}, +{-0.809017, 0.309017, 0.500000}, {-0.587785, 0.425325, 0.688191}, +{-0.850651, 0.525731, 0.000000}, {-0.864188, 0.442863, 0.238856}, +{-0.716567, 0.681718, 0.147621}, {-0.688191, 0.587785, 0.425325}, +{-0.500000, 0.809017, 0.309017}, {-0.238856, 0.864188, 0.442863}, +{-0.425325, 0.688191, 0.587785}, {-0.716567, 0.681718, -0.147621}, +{-0.500000, 0.809017, -0.309017}, {-0.525731, 0.850651, 0.000000}, +{0.000000, 0.850651, -0.525731}, {-0.238856, 0.864188, -0.442863}, +{0.000000, 0.955423, -0.295242}, {-0.262866, 0.951056, -0.162460}, +{0.000000, 1.000000, 0.000000}, {0.000000, 0.955423, 0.295242}, +{-0.262866, 0.951056, 0.162460}, {0.238856, 0.864188, 0.442863}, +{0.262866, 0.951056, 0.162460}, {0.500000, 0.809017, 0.309017}, +{0.238856, 0.864188, -0.442863}, {0.262866, 0.951056, -0.162460}, +{0.500000, 0.809017, -0.309017}, {0.850651, 0.525731, 0.000000}, +{0.716567, 0.681718, 0.147621}, {0.716567, 0.681718, -0.147621}, +{0.525731, 0.850651, 0.000000}, {0.425325, 0.688191, 0.587785}, +{0.864188, 0.442863, 0.238856}, {0.688191, 0.587785, 0.425325}, +{0.809017, 0.309017, 0.500000}, {0.681718, 0.147621, 0.716567}, +{0.587785, 0.425325, 0.688191}, {0.955423, 0.295242, 0.000000}, +{1.000000, 0.000000, 0.000000}, {0.951056, 0.162460, 0.262866}, +{0.850651, -0.525731, 0.000000}, {0.955423, -0.295242, 0.000000}, +{0.864188, -0.442863, 0.238856}, {0.951056, -0.162460, 0.262866}, +{0.809017, -0.309017, 0.500000}, {0.681718, -0.147621, 0.716567}, +{0.850651, 0.000000, 0.525731}, {0.864188, 0.442863, -0.238856}, +{0.809017, 0.309017, -0.500000}, {0.951056, 0.162460, -0.262866}, +{0.525731, 0.000000, -0.850651}, {0.681718, 0.147621, -0.716567}, +{0.681718, -0.147621, -0.716567}, {0.850651, 0.000000, -0.525731}, +{0.809017, -0.309017, -0.500000}, {0.864188, -0.442863, -0.238856}, +{0.951056, -0.162460, -0.262866}, {0.147621, 0.716567, -0.681718}, +{0.309017, 0.500000, -0.809017}, {0.425325, 0.688191, -0.587785}, +{0.442863, 0.238856, -0.864188}, {0.587785, 0.425325, -0.688191}, +{0.688191, 0.587785, -0.425325}, {-0.147621, 0.716567, -0.681718}, +{-0.309017, 0.500000, -0.809017}, {0.000000, 0.525731, -0.850651}, +{-0.525731, 0.000000, -0.850651}, {-0.442863, 0.238856, -0.864188}, +{-0.295242, 0.000000, -0.955423}, {-0.162460, 0.262866, -0.951056}, +{0.000000, 0.000000, -1.000000}, {0.295242, 0.000000, -0.955423}, +{0.162460, 0.262866, -0.951056}, {-0.442863, -0.238856, -0.864188}, +{-0.309017, -0.500000, -0.809017}, {-0.162460, -0.262866, -0.951056}, +{0.000000, -0.850651, -0.525731}, {-0.147621, -0.716567, -0.681718}, +{0.147621, -0.716567, -0.681718}, {0.000000, -0.525731, -0.850651}, +{0.309017, -0.500000, -0.809017}, {0.442863, -0.238856, -0.864188}, +{0.162460, -0.262866, -0.951056}, {0.238856, -0.864188, -0.442863}, +{0.500000, -0.809017, -0.309017}, {0.425325, -0.688191, -0.587785}, +{0.716567, -0.681718, -0.147621}, {0.688191, -0.587785, -0.425325}, +{0.587785, -0.425325, -0.688191}, {0.000000, -0.955423, -0.295242}, +{0.000000, -1.000000, 0.000000}, {0.262866, -0.951056, -0.162460}, +{0.000000, -0.850651, 0.525731}, {0.000000, -0.955423, 0.295242}, +{0.238856, -0.864188, 0.442863}, {0.262866, -0.951056, 0.162460}, +{0.500000, -0.809017, 0.309017}, {0.716567, -0.681718, 0.147621}, +{0.525731, -0.850651, 0.000000}, {-0.238856, -0.864188, -0.442863}, +{-0.500000, -0.809017, -0.309017}, {-0.262866, -0.951056, -0.162460}, +{-0.850651, -0.525731, 0.000000}, {-0.716567, -0.681718, -0.147621}, +{-0.716567, -0.681718, 0.147621}, {-0.525731, -0.850651, 0.000000}, +{-0.500000, -0.809017, 0.309017}, {-0.238856, -0.864188, 0.442863}, +{-0.262866, -0.951056, 0.162460}, {-0.864188, -0.442863, 0.238856}, +{-0.809017, -0.309017, 0.500000}, {-0.688191, -0.587785, 0.425325}, +{-0.681718, -0.147621, 0.716567}, {-0.442863, -0.238856, 0.864188}, +{-0.587785, -0.425325, 0.688191}, {-0.309017, -0.500000, 0.809017}, +{-0.147621, -0.716567, 0.681718}, {-0.425325, -0.688191, 0.587785}, +{-0.162460, -0.262866, 0.951056}, {0.442863, -0.238856, 0.864188}, +{0.162460, -0.262866, 0.951056}, {0.309017, -0.500000, 0.809017}, +{0.147621, -0.716567, 0.681718}, {0.000000, -0.525731, 0.850651}, +{0.425325, -0.688191, 0.587785}, {0.587785, -0.425325, 0.688191}, +{0.688191, -0.587785, 0.425325}, {-0.955423, 0.295242, 0.000000}, +{-0.951056, 0.162460, 0.262866}, {-1.000000, 0.000000, 0.000000}, +{-0.850651, 0.000000, 0.525731}, {-0.955423, -0.295242, 0.000000}, +{-0.951056, -0.162460, 0.262866}, {-0.864188, 0.442863, -0.238856}, +{-0.951056, 0.162460, -0.262866}, {-0.809017, 0.309017, -0.500000}, +{-0.864188, -0.442863, -0.238856}, {-0.951056, -0.162460, -0.262866}, +{-0.809017, -0.309017, -0.500000}, {-0.681718, 0.147621, -0.716567}, +{-0.681718, -0.147621, -0.716567}, {-0.850651, 0.000000, -0.525731}, +{-0.688191, 0.587785, -0.425325}, {-0.587785, 0.425325, -0.688191}, +{-0.425325, 0.688191, -0.587785}, {-0.425325, -0.688191, -0.587785}, +{-0.587785, -0.425325, -0.688191}, {-0.688191, -0.587785, -0.425325}, +}; + +byte NormalToByte(vec3_t n) +{ + int i, best; + float bestdistance, distance; + + best = 0; + bestdistance = DotProduct (n, m_bytenormals[0]); + for (i = 1;i < NUMVERTEXNORMALS;i++) + { + distance = DotProduct (n, m_bytenormals[i]); + if (distance > bestdistance) + { + bestdistance = distance; + best = i; + } + } + return best; +} + +// note: uses byte partly to force unsigned for the validity check +void ByteToNormal(byte num, vec3_t n) +{ + if (num < NUMVERTEXNORMALS) + VectorCopy(m_bytenormals[num], n) + else + VectorClear(n) // FIXME: complain? +} + +#if 0 +// LordHavoc: no longer used at all void ProjectPointOnPlane( vec3_t dst, const vec3_t p, const vec3_t normal ) { +#if 0 + // LordHavoc: the old way... float d; vec3_t n; float inv_denom; @@ -48,21 +165,32 @@ void ProjectPointOnPlane( vec3_t dst, const vec3_t p, const vec3_t normal ) dst[0] = p[0] - d * n[0]; dst[1] = p[1] - d * n[1]; dst[2] = p[2] - d * n[2]; +#else + // LordHavoc: optimized to death and beyond + float d; + + // LordHavoc: the normal is a unit vector by definition, + // therefore inv_denom was pointless. + d = DotProduct(normal, p); + dst[0] = p[0] - d * normal[0]; + dst[1] = p[1] - d * normal[1]; + dst[2] = p[2] - d * normal[2]; +#endif } +#endif -/* -** assumes "src" is normalized -*/ +// assumes "src" is normalized void PerpendicularVector( vec3_t dst, const vec3_t src ) { +#if 0 + // LordHavoc: the old way... int pos; int i; - float minelem = 1.0F; + float minelem, d; vec3_t tempvec; - /* - ** find the smallest magnitude axially aligned vector - */ + // find the smallest magnitude axially aligned vector + minelem = 1.0F; for ( pos = 0, i = 0; i < 3; i++ ) { if ( fabs( src[i] ) < minelem ) @@ -71,27 +199,91 @@ void PerpendicularVector( vec3_t dst, const vec3_t src ) minelem = fabs( src[i] ); } } - tempvec[0] = tempvec[1] = tempvec[2] = 0.0F; + VectorClear(tempvec); tempvec[pos] = 1.0F; - /* - ** project the point onto the plane defined by src - */ + // project the point onto the plane defined by src ProjectPointOnPlane( dst, tempvec, src ); - /* - ** normalize the result - */ - VectorNormalize( dst ); + // normalize the result + VectorNormalize(dst); +#else + // LordHavoc: optimized to death and beyond + int pos; + float minelem; + + if (src[0]) + { + dst[0] = 0; + if (src[1]) + { + dst[1] = 0; + if (src[2]) + { + dst[2] = 0; + pos = 0; + minelem = fabs(src[0]); + if (fabs(src[1]) < minelem) + { + pos = 1; + minelem = fabs(src[1]); + } + if (fabs(src[2]) < minelem) + pos = 2; + + dst[pos] = 1; + dst[0] -= src[pos] * src[0]; + dst[1] -= src[pos] * src[1]; + dst[2] -= src[pos] * src[2]; + + // normalize the result + VectorNormalize(dst); + } + else + dst[2] = 1; + } + else + { + dst[1] = 1; + dst[2] = 0; + } + } + else + { + dst[0] = 1; + dst[1] = 0; + dst[2] = 0; + } +#endif } + #ifdef _WIN32 #pragma optimize( "", off ) #endif +// LordHavoc: like AngleVectors, but taking a forward vector instead of angles, useful! +void VectorVectors(const vec3_t forward, vec3_t right, vec3_t up) +{ + float d; + + right[0] = forward[2]; + right[1] = -forward[0]; + right[2] = forward[1]; + + d = DotProduct(forward, right); + right[0] -= d * forward[0]; + right[1] -= d * forward[1]; + right[2] -= d * forward[2]; + VectorNormalize(right); + CrossProduct(right, forward, up); +} + void RotatePointAroundVector( vec3_t dst, const vec3_t dir, const vec3_t point, float degrees ) { +#if 0 + // LordHavoc: the old way, cryptic brute force... float m[3][3]; float im[3][3]; float zrot[3][3]; @@ -140,9 +332,130 @@ void RotatePointAroundVector( vec3_t dst, const vec3_t dir, const vec3_t point, R_ConcatRotations( tmpmat, im, rot ); for ( i = 0; i < 3; i++ ) - { dst[i] = rot[i][0] * point[0] + rot[i][1] * point[1] + rot[i][2] * point[2]; - } +#elif 0 + // LordHavoc: on the path to unintelligible code... +// float m[3][3]; +// float im[3][3]; +// float zrot[3][3]; + float tmpmat[3][3]; +// float rot[3][3]; + float angle, c, s; +// int i; + vec3_t vr, vu, vf; + + angle = DEG2RAD(degrees); + + c = cos(angle); + s = sin(angle); + + vf[0] = dir[0]; + vf[1] = dir[1]; + vf[2] = dir[2]; + + PerpendicularVector(vr, dir); + CrossProduct(vr, vf, vu); + +// m [0][0] = vr[0];m [0][1] = vu[0];m [0][2] = vf[0]; +// m [1][0] = vr[1];m [1][1] = vu[1];m [1][2] = vf[1]; +// m [2][0] = vr[2];m [2][1] = vu[2];m [2][2] = vf[2]; +// im [0][0] = vr[0];im [0][1] = vr[1];im [0][2] = vr[2]; +// im [1][0] = vu[0];im [1][1] = vu[1];im [1][2] = vu[2]; +// im [2][0] = vf[0];im [2][1] = vf[1];im [2][2] = vf[2]; +// zrot[0][0] = c;zrot[0][1] = s;zrot[0][2] = 0; +// zrot[1][0] = -s;zrot[1][1] = c;zrot[1][2] = 0; +// zrot[2][0] = 0;zrot[2][1] = 0;zrot[2][2] = 1; + +// tmpmat[0][0] = m[0][0] * zrot[0][0] + m[0][1] * zrot[1][0] + m[0][2] * zrot[2][0]; +// tmpmat[0][1] = m[0][0] * zrot[0][1] + m[0][1] * zrot[1][1] + m[0][2] * zrot[2][1]; +// tmpmat[0][2] = m[0][0] * zrot[0][2] + m[0][1] * zrot[1][2] + m[0][2] * zrot[2][2]; +// tmpmat[1][0] = m[1][0] * zrot[0][0] + m[1][1] * zrot[1][0] + m[1][2] * zrot[2][0]; +// tmpmat[1][1] = m[1][0] * zrot[0][1] + m[1][1] * zrot[1][1] + m[1][2] * zrot[2][1]; +// tmpmat[1][2] = m[1][0] * zrot[0][2] + m[1][1] * zrot[1][2] + m[1][2] * zrot[2][2]; +// tmpmat[2][0] = m[2][0] * zrot[0][0] + m[2][1] * zrot[1][0] + m[2][2] * zrot[2][0]; +// tmpmat[2][1] = m[2][0] * zrot[0][1] + m[2][1] * zrot[1][1] + m[2][2] * zrot[2][1]; +// tmpmat[2][2] = m[2][0] * zrot[0][2] + m[2][1] * zrot[1][2] + m[2][2] * zrot[2][2]; + + tmpmat[0][0] = vr[0] * c + vu[0] * -s; + tmpmat[0][1] = vr[0] * s + vu[0] * c; +// tmpmat[0][2] = vf[0]; + tmpmat[1][0] = vr[1] * c + vu[1] * -s; + tmpmat[1][1] = vr[1] * s + vu[1] * c; +// tmpmat[1][2] = vf[1]; + tmpmat[2][0] = vr[2] * c + vu[2] * -s; + tmpmat[2][1] = vr[2] * s + vu[2] * c; +// tmpmat[2][2] = vf[2]; + +// rot[0][0] = tmpmat[0][0] * vr[0] + tmpmat[0][1] * vu[0] + tmpmat[0][2] * vf[0]; +// rot[0][1] = tmpmat[0][0] * vr[1] + tmpmat[0][1] * vu[1] + tmpmat[0][2] * vf[1]; +// rot[0][2] = tmpmat[0][0] * vr[2] + tmpmat[0][1] * vu[2] + tmpmat[0][2] * vf[2]; +// rot[1][0] = tmpmat[1][0] * vr[0] + tmpmat[1][1] * vu[0] + tmpmat[1][2] * vf[0]; +// rot[1][1] = tmpmat[1][0] * vr[1] + tmpmat[1][1] * vu[1] + tmpmat[1][2] * vf[1]; +// rot[1][2] = tmpmat[1][0] * vr[2] + tmpmat[1][1] * vu[2] + tmpmat[1][2] * vf[2]; +// rot[2][0] = tmpmat[2][0] * vr[0] + tmpmat[2][1] * vu[0] + tmpmat[2][2] * vf[0]; +// rot[2][1] = tmpmat[2][0] * vr[1] + tmpmat[2][1] * vu[1] + tmpmat[2][2] * vf[1]; +// rot[2][2] = tmpmat[2][0] * vr[2] + tmpmat[2][1] * vu[2] + tmpmat[2][2] * vf[2]; + +// rot[0][0] = tmpmat[0][0] * vr[0] + tmpmat[0][1] * vu[0] + vf[0] * vf[0]; +// rot[0][1] = tmpmat[0][0] * vr[1] + tmpmat[0][1] * vu[1] + vf[0] * vf[1]; +// rot[0][2] = tmpmat[0][0] * vr[2] + tmpmat[0][1] * vu[2] + vf[0] * vf[2]; +// rot[1][0] = tmpmat[1][0] * vr[0] + tmpmat[1][1] * vu[0] + vf[1] * vf[0]; +// rot[1][1] = tmpmat[1][0] * vr[1] + tmpmat[1][1] * vu[1] + vf[1] * vf[1]; +// rot[1][2] = tmpmat[1][0] * vr[2] + tmpmat[1][1] * vu[2] + vf[1] * vf[2]; +// rot[2][0] = tmpmat[2][0] * vr[0] + tmpmat[2][1] * vu[0] + vf[2] * vf[0]; +// rot[2][1] = tmpmat[2][0] * vr[1] + tmpmat[2][1] * vu[1] + vf[2] * vf[1]; +// rot[2][2] = tmpmat[2][0] * vr[2] + tmpmat[2][1] * vu[2] + vf[2] * vf[2]; + +// dst[0] = rot[0][0] * point[0] + rot[0][1] * point[1] + rot[0][2] * point[2]; +// dst[1] = rot[1][0] * point[0] + rot[1][1] * point[1] + rot[1][2] * point[2]; +// dst[2] = rot[2][0] * point[0] + rot[2][1] * point[1] + rot[2][2] * point[2]; + + dst[0] = (tmpmat[0][0] * vr[0] + tmpmat[0][1] * vu[0] + vf[0] * vf[0]) * point[0] + + (tmpmat[0][0] * vr[1] + tmpmat[0][1] * vu[1] + vf[0] * vf[1]) * point[1] + + (tmpmat[0][0] * vr[2] + tmpmat[0][1] * vu[2] + vf[0] * vf[2]) * point[2]; + dst[1] = (tmpmat[1][0] * vr[0] + tmpmat[1][1] * vu[0] + vf[1] * vf[0]) * point[0] + + (tmpmat[1][0] * vr[1] + tmpmat[1][1] * vu[1] + vf[1] * vf[1]) * point[1] + + (tmpmat[1][0] * vr[2] + tmpmat[1][1] * vu[2] + vf[1] * vf[2]) * point[2]; + dst[2] = (tmpmat[2][0] * vr[0] + tmpmat[2][1] * vu[0] + vf[2] * vf[0]) * point[0] + + (tmpmat[2][0] * vr[1] + tmpmat[2][1] * vu[1] + vf[2] * vf[1]) * point[1] + + (tmpmat[2][0] * vr[2] + tmpmat[2][1] * vu[2] + vf[2] * vf[2]) * point[2]; +#else + // LordHavoc: optimized to death and beyond, cryptic in an entirely new way + float t0, t1; + float angle, c, s; + vec3_t vr, vu, vf; + + angle = DEG2RAD(degrees); + + c = cos(angle); + s = sin(angle); + + vf[0] = dir[0]; + vf[1] = dir[1]; + vf[2] = dir[2]; + +// PerpendicularVector(vr, dir); +// CrossProduct(vr, vf, vu); + VectorVectors(vf, vr, vu); + + t0 = vr[0] * c + vu[0] * -s; + t1 = vr[0] * s + vu[0] * c; + dst[0] = (t0 * vr[0] + t1 * vu[0] + vf[0] * vf[0]) * point[0] + + (t0 * vr[1] + t1 * vu[1] + vf[0] * vf[1]) * point[1] + + (t0 * vr[2] + t1 * vu[2] + vf[0] * vf[2]) * point[2]; + + t0 = vr[1] * c + vu[1] * -s; + t1 = vr[1] * s + vu[1] * c; + dst[1] = (t0 * vr[0] + t1 * vu[0] + vf[1] * vf[0]) * point[0] + + (t0 * vr[1] + t1 * vu[1] + vf[1] * vf[1]) * point[1] + + (t0 * vr[2] + t1 * vu[2] + vf[1] * vf[2]) * point[2]; + + t0 = vr[2] * c + vu[2] * -s; + t1 = vr[2] * s + vu[2] * c; + dst[2] = (t0 * vr[0] + t1 * vu[0] + vf[2] * vf[0]) * point[0] + + (t0 * vr[1] + t1 * vu[1] + vf[2] * vf[1]) * point[1] + + (t0 * vr[2] + t1 * vu[2] + vf[2] * vf[2]) * point[2]; +#endif } #ifdef _WIN32 @@ -164,6 +477,20 @@ float anglemod(float a) return a; } +// LordHavoc note 1: +// BoxOnPlaneSide did a switch on a 'signbits' value and had optimized +// assembly in an attempt to accelerate it further, very inefficient +// considering that signbits of the frustum planes only changed each +// frame, and the world planes changed only at load time. +// So, to optimize it further I took the obvious route of storing a function +// pointer in the plane struct itself, and shrunk each of the individual +// cases to a single return statement. +// LordHavoc note 2: +// realized axial cases would be a nice speedup for world geometry, although +// never useful for the frustum planes. +int BoxOnPlaneSideX (vec3_t emins, vec3_t emaxs, mplane_t *p) {return p->dist <= emins[0] ? 1 : (p->dist >= emaxs[0] ? 2 : 3);} +int BoxOnPlaneSideY (vec3_t emins, vec3_t emaxs, mplane_t *p) {return p->dist <= emins[1] ? 1 : (p->dist >= emaxs[1] ? 2 : 3);} +int BoxOnPlaneSideZ (vec3_t emins, vec3_t emaxs, mplane_t *p) {return p->dist <= emins[2] ? 1 : (p->dist >= emaxs[2] ? 2 : 3);} int BoxOnPlaneSide0 (vec3_t emins, vec3_t emaxs, mplane_t *p) {return (((p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2]) >= p->dist) | (((p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2]) < p->dist) << 1));} int BoxOnPlaneSide1 (vec3_t emins, vec3_t emaxs, mplane_t *p) {return (((p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2]) >= p->dist) | (((p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2]) < p->dist) << 1));} int BoxOnPlaneSide2 (vec3_t emins, vec3_t emaxs, mplane_t *p) {return (((p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2]) >= p->dist) | (((p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2]) < p->dist) << 1));} @@ -175,39 +502,53 @@ int BoxOnPlaneSide7 (vec3_t emins, vec3_t emaxs, mplane_t *p) {return (((p->norm void BoxOnPlaneSideClassify(mplane_t *p) { - if (p->normal[2] < 0) // 4 + switch(p->type) { - if (p->normal[1] < 0) // 2 + case 0: // x axis + p->BoxOnPlaneSideFunc = BoxOnPlaneSideX; + break; + case 1: // y axis + p->BoxOnPlaneSideFunc = BoxOnPlaneSideY; + break; + case 2: // z axis + p->BoxOnPlaneSideFunc = BoxOnPlaneSideZ; + break; + default: + if (p->normal[2] < 0) // 4 { - if (p->normal[0] < 0) // 1 - p->BoxOnPlaneSideFunc = BoxOnPlaneSide7; + if (p->normal[1] < 0) // 2 + { + if (p->normal[0] < 0) // 1 + p->BoxOnPlaneSideFunc = BoxOnPlaneSide7; + else + p->BoxOnPlaneSideFunc = BoxOnPlaneSide6; + } else - p->BoxOnPlaneSideFunc = BoxOnPlaneSide6; + { + if (p->normal[0] < 0) // 1 + p->BoxOnPlaneSideFunc = BoxOnPlaneSide5; + else + p->BoxOnPlaneSideFunc = BoxOnPlaneSide4; + } } else { - if (p->normal[0] < 0) // 1 - p->BoxOnPlaneSideFunc = BoxOnPlaneSide5; + if (p->normal[1] < 0) // 2 + { + if (p->normal[0] < 0) // 1 + p->BoxOnPlaneSideFunc = BoxOnPlaneSide3; + else + p->BoxOnPlaneSideFunc = BoxOnPlaneSide2; + } else - p->BoxOnPlaneSideFunc = BoxOnPlaneSide4; - } - } - else - { - if (p->normal[1] < 0) // 2 - { - if (p->normal[0] < 0) // 1 - p->BoxOnPlaneSideFunc = BoxOnPlaneSide3; - else - p->BoxOnPlaneSideFunc = BoxOnPlaneSide2; - } - else - { - if (p->normal[0] < 0) // 1 - p->BoxOnPlaneSideFunc = BoxOnPlaneSide1; - else - p->BoxOnPlaneSideFunc = BoxOnPlaneSide0; + { + if (p->normal[0] < 0) // 1 + p->BoxOnPlaneSideFunc = BoxOnPlaneSide1; + else + p->BoxOnPlaneSideFunc = BoxOnPlaneSide0; + } } + break; } } @@ -222,19 +563,35 @@ void AngleVectors (vec3_t angles, vec3_t forward, vec3_t right, vec3_t up) angle = angles[PITCH] * (M_PI*2 / 360); sp = sin(angle); cp = cos(angle); - angle = angles[ROLL] * (M_PI*2 / 360); - sr = sin(angle); - cr = cos(angle); - - forward[0] = cp*cy; - forward[1] = cp*sy; - forward[2] = -sp; - right[0] = (-1*sr*sp*cy+-1*cr*-sy); - right[1] = (-1*sr*sp*sy+-1*cr*cy); - right[2] = -1*sr*cp; - up[0] = (cr*sp*cy+-sr*-sy); - up[1] = (cr*sp*sy+-sr*cy); - up[2] = cr*cp; + // LordHavoc: this is only to hush up gcc complaining about 'might be used uninitialized' variables + // (they are NOT used uninitialized, but oh well) + cr = 0; + sr = 0; + if (right || up) + { + angle = angles[ROLL] * (M_PI*2 / 360); + sr = sin(angle); + cr = cos(angle); + } + + if (forward) + { + forward[0] = cp*cy; + forward[1] = cp*sy; + forward[2] = -sp; + } + if (right) + { + right[0] = (-1*sr*sp*cy+-1*cr*-sy); + right[1] = (-1*sr*sp*sy+-1*cr*cy); + right[2] = -1*sr*cp; + } + if (up) + { + up[0] = (cr*sp*cy+-sr*-sy); + up[1] = (cr*sp*sy+-sr*cy); + up[2] = cr*cp; + } } int VectorCompare (vec3_t v1, vec3_t v2) diff --git a/mathlib.h b/mathlib.h index 3b669e90..fde3d3e5 100644 --- a/mathlib.h +++ b/mathlib.h @@ -20,8 +20,13 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // mathlib.h typedef float vec_t; +typedef vec_t vec2_t[2]; typedef vec_t vec3_t[3]; +typedef vec_t vec4_t[4]; typedef vec_t vec5_t[5]; +typedef vec_t vec6_t[6]; +typedef vec_t vec7_t[7]; +typedef vec_t vec8_t[8]; typedef int fixed4_t; typedef int fixed8_t; @@ -53,6 +58,8 @@ extern int nanmask; #define VectorDistance2(a, b) ((a[0] - b[0]) * (a[0] - b[0]) + (a[1] - b[1]) * (a[1] - b[1]) + (a[2] - b[2]) * (a[2] - b[2])) #define VectorDistance(a, b) (sqrt(VectorDistance2(a,b))) #define VectorLength(a) sqrt(DotProduct(a, a)) +#define VectorScaleQuick(in, scale, out) {(out)[0] = (in)[0] * (scale);(out)[1] = (in)[1] * (scale);(out)[2] = (in)[2] * (scale);} +#define 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];} void VectorMA (vec3_t veca, float scale, vec3_t vecb, vec3_t vecc); @@ -70,6 +77,12 @@ void VectorInverse (vec3_t v); void VectorScale (vec3_t in, vec_t scale, vec3_t out); int Q_log2(int val); +#define NUMVERTEXNORMALS 162 +extern float m_bytenormals[NUMVERTEXNORMALS][3]; + +byte NormalToByte(vec3_t n); +void ByteToNormal(byte num, vec3_t n); + void R_ConcatRotations (float in1[3][3], float in2[3][3], float out[3][3]); void R_ConcatTransforms (float in1[3][4], float in2[3][4], float out[3][4]); @@ -79,6 +92,8 @@ int GreatestCommonDivisor (int i1, int i2); void AngleVectors (vec3_t angles, vec3_t forward, vec3_t right, vec3_t up); float anglemod(float a); +// LordHavoc: like AngleVectors, but taking a forward vector instead of angles, useful! +void VectorVectors(const vec3_t forward, vec3_t right, vec3_t up); void BoxOnPlaneSideClassify(struct mplane_s *p); diff --git a/menu.c b/menu.c index 28de58ec..0e856961 100644 --- a/menu.c +++ b/menu.c @@ -1333,7 +1333,7 @@ void M_AdjustSliders (int dir) Cvar_SetValue ("volume", volume.value); break; - case 8: // allways run + case 8: // always run if (cl_forwardspeed.value > 200) { Cvar_SetValue ("cl_forwardspeed", 200); diff --git a/model_alias.c b/model_alias.c index ba66d724..f29d3a9e 100644 --- a/model_alias.c +++ b/model_alias.c @@ -20,6 +20,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "quakedef.h" +cvar_t r_mipskins = {"r_mipskins", "1", true}; + /* =============== Mod_AliasInit @@ -27,6 +29,7 @@ Mod_AliasInit */ void Mod_AliasInit (void) { + Cvar_RegisterVariable(&r_mipskins); } int posenum; @@ -40,11 +43,9 @@ int vertonseam[MAXVERTS]; int vertremap[MAXVERTS]; unsigned short temptris[MAXVERTS][3]; -#define NUMVERTEXNORMALS 162 -extern float r_avertexnormals[NUMVERTEXNORMALS][3]; -void Mod_ConvertAliasVerts (int inverts, vec3_t scale, vec3_t translate, trivertx_t *v, trivert2 *out) +void Mod_ConvertAliasVerts (int inverts, vec3_t scale, vec3_t translate, trivertx_t *v, trivertx_t *out) { - int i, j; + int i, j, invalidnormals = 0; vec3_t temp; for (i = 0;i < inverts;i++) { @@ -64,19 +65,27 @@ void Mod_ConvertAliasVerts (int inverts, vec3_t scale, vec3_t translate, trivert if (j >= 0) { VectorCopy(v[i].v, out[j].v); - out[j].n[0] = (signed char) (r_avertexnormals[v[i].lightnormalindex][0] * 127.0); - out[j].n[1] = (signed char) (r_avertexnormals[v[i].lightnormalindex][1] * 127.0); - out[j].n[2] = (signed char) (r_avertexnormals[v[i].lightnormalindex][2] * 127.0); + out[j].lightnormalindex = v[i].lightnormalindex; + if (out[j].lightnormalindex >= NUMVERTEXNORMALS) + { + invalidnormals++; + out[j].lightnormalindex = 0; + } } j = vertremap[i+inverts]; // onseam if (j >= 0) { VectorCopy(v[i].v, out[j].v); - out[j].n[0] = (signed char) (r_avertexnormals[v[i].lightnormalindex][0] * 127.0); - out[j].n[1] = (signed char) (r_avertexnormals[v[i].lightnormalindex][1] * 127.0); - out[j].n[2] = (signed char) (r_avertexnormals[v[i].lightnormalindex][2] * 127.0); + out[j].lightnormalindex = v[i].lightnormalindex; + if (out[j].lightnormalindex >= NUMVERTEXNORMALS) + { + invalidnormals++; + out[j].lightnormalindex = 0; + } } } + if (invalidnormals) + Con_Printf("Mod_ConvertAliasVerts: %i invalid normal indices found\n", invalidnormals); } /* @@ -84,17 +93,18 @@ void Mod_ConvertAliasVerts (int inverts, vec3_t scale, vec3_t translate, trivert Mod_LoadAliasFrame ================= */ -void * Mod_LoadAliasFrame (void *pin, maliasframe_t *frame, maliashdr_t *mheader, int inverts, int outverts, trivert2 **posevert) +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(frame->name, pdaliasframe->name); - frame->start = posenum; - frame->length = 1; - frame->rate = 10.0f; // unnecessary but... + strcpy(scene->name, pdaliasframe->name); + scene->firstframe = posenum; + scene->framecount = 1; + scene->framerate = 10.0f; // unnecessary but... + scene->loop = true; pinframe = (trivertx_t *)(pdaliasframe + 1); @@ -113,7 +123,7 @@ void * Mod_LoadAliasFrame (void *pin, maliasframe_t *frame, maliashdr_t *mheader Mod_LoadAliasGroup ================= */ -void *Mod_LoadAliasGroup (void *pin, maliasframe_t *frame, maliashdr_t *mheader, int inverts, int outverts, trivert2 **posevert) +void *Mod_LoadAliasGroup (void *pin, maliashdr_t *mheader, int inverts, int outverts, trivertx_t **posevert, animscene_t *scene) { int i, numframes; void *ptemp; @@ -121,13 +131,14 @@ void *Mod_LoadAliasGroup (void *pin, maliasframe_t *frame, maliashdr_t *mheader, numframes = LittleLong (((daliasgroup_t *)pin)->numframes); - strcpy(frame->name, "group"); - frame->start = posenum; - frame->length = numframes; + strcpy(scene->name, ((daliasframe_t *) (sizeof(daliasinterval_t) * numframes + sizeof(daliasgroup_t) + (int) pin))->name); + scene->firstframe = posenum; + scene->framecount = numframes; interval = LittleFloat (((daliasinterval_t *)(((daliasgroup_t *)pin) + 1))->interval); // FIXME: support variable framerate groups? if (interval < 0.01f) Host_Error("Mod_LoadAliasGroup: invalid interval"); - frame->rate = 1.0f / interval; + scene->framerate = 1.0f / interval; + scene->loop = true; ptemp = (void *)(((daliasinterval_t *)(((daliasgroup_t *)pin) + 1)) + numframes); @@ -219,7 +230,7 @@ void Mod_FloodFillSkin( byte *skin, int skinwidth, int skinheight ) } } -int GL_SkinSplitShirt(byte *in, byte *out, int width, int height, unsigned short bits, char *name) +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]; @@ -244,12 +255,12 @@ int GL_SkinSplitShirt(byte *in, byte *out, int width, int height, unsigned short out++; } if (passed) - return GL_LoadTexture (name, width, height, out - width*height, true, false, 1); + return R_LoadTexture (name, width, height, out - width*height, (r_mipskins.value ? TEXF_MIPMAP : 0) | (precache ? TEXF_PRECACHE : 0)); else - return 0; + return NULL; } -int GL_SkinSplit(byte *in, byte *out, int width, int height, unsigned short bits, char *name) +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]; @@ -270,9 +281,9 @@ int GL_SkinSplit(byte *in, byte *out, int width, int height, unsigned short bits out++; } if (passed) - return GL_LoadTexture (name, width, height, out - width*height, true, false, 1); + return R_LoadTexture (name, width, height, out - width*height, (r_mipskins.value ? TEXF_MIPMAP : 0) | (precache ? TEXF_PRECACHE : 0)); else - return 0; + return NULL; } int GL_SkinCheck(byte *in, int width, int height, unsigned short bits) @@ -292,7 +303,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, int *skintexnum) +void Mod_LoadSkin (maliashdr_t *mheader, char *basename, byte *skindata, byte *skintemp, int width, int height, rtexture_t **skintex) { #if 0 int skin_normal, skin_pants, skin_shirt, skin_glow, skin_body, temp; @@ -341,26 +352,31 @@ void Mod_LoadSkin (maliashdr_t *mheader, char *basename, byte *skindata, byte *s } } #else - skintexnum[0] = loadtextureimage(va("%s_normal", basename), 0, 0, false, true); - skintexnum[1] = 0; - skintexnum[2] = 0; - skintexnum[3] = loadtextureimage(va("%s_glow" , basename), 0, 0, false, true); - skintexnum[4] = 0; - if (skintexnum[0]) + skintex[0] = loadtextureimage(va("%s_normal", basename), 0, 0, false, r_mipskins.value, true); + skintex[1] = NULL; + skintex[2] = NULL; + skintex[3] = loadtextureimage(va("%s_glow" , basename), 0, 0, false, r_mipskins.value, true); + skintex[4] = NULL; + if (skintex[0]) { - skintexnum[1] = loadtextureimage(va("%s_pants" , basename), 0, 0, false, true); - skintexnum[2] = loadtextureimage(va("%s_shirt" , basename), 0, 0, false, true); + skintex[1] = loadtextureimage(va("%s_pants" , basename), 0, 0, false, r_mipskins.value, true); + skintex[2] = loadtextureimage(va("%s_shirt" , basename), 0, 0, false, r_mipskins.value, true); } else { - skintexnum[0] = loadtextureimage(basename, 0, 0, false, true); - if (!skintexnum[0]) + skintex[0] = loadtextureimage(basename, 0, 0, false, true, true); + if (!skintex[0]) { - skintexnum[0] = GL_SkinSplit(skindata, skintemp, width, height, 0x3FBD, va("&%s_normal", basename)); // normal (no special colors) - skintexnum[1] = GL_SkinSplitShirt(skindata, skintemp, width, height, 0x0040, va("&%s_pants", basename)); // pants - skintexnum[2] = GL_SkinSplitShirt(skindata, skintemp, width, height, 0x0002, va("&%s_shirt", basename)); // shirt - skintexnum[3] = GL_SkinSplit(skindata, skintemp, width, height, 0xC000, va("%s_glow", basename)); // glow - skintexnum[4] = GL_SkinSplit(skindata, skintemp, width, height, 0x3FFF, va("%s_body", basename)); // body (normal + pants + shirt, but not glow) + skintex[1] = GL_SkinSplitShirt(skindata, skintemp, width, height, 0x0040, va("%s_pants", basename), false); // pants + skintex[2] = GL_SkinSplitShirt(skindata, skintemp, width, height, 0x0002, va("%s_shirt", basename), false); // shirt + skintex[3] = GL_SkinSplit(skindata, skintemp, width, height, 0xC000, va("%s_glow", basename), true); // glow + if (skintex[1] || skintex[2]) + { + skintex[0] = GL_SkinSplit(skindata, skintemp, width, height, 0x3FBD, va("%s_normal", basename), false); // normal (no special colors) + skintex[4] = GL_SkinSplit(skindata, skintemp, width, height, 0x3FFF, va("%s_body", basename), true); // body (normal + pants + shirt, but not glow) + } + else + skintex[0] = GL_SkinSplit(skindata, skintemp, width, height, 0x3FFF, va("%s_base", basename), true); // no special colors } } #endif @@ -380,7 +396,8 @@ void *Mod_LoadAllSkins (maliashdr_t *mheader, int numskins, daliasskintype_t *ps daliasskingroup_t *pinskingroup; int groupskins; daliasskininterval_t *pinskinintervals; - int skinranges, skincount, *skintexnum, *skinrange, skinnum; + int skinranges, skincount, *skinrange, skinnum; + rtexture_t **skintex; void *temp; byte *skintemp = NULL; @@ -414,7 +431,7 @@ void *Mod_LoadAllSkins (maliashdr_t *mheader, int numskins, daliasskintype_t *ps pskintype = temp; skinrange = loadmodel->skinanimrange; - skintexnum = loadmodel->skinanim; + skintex = loadmodel->skinanim; // skinrange = Hunk_AllocName (sizeof(int) * (skinranges + skincount), loadname); // skintexnum = skinrange + skinranges * 2; // loadmodel->skinanimrange = (int) skinrange - (int) pheader; @@ -429,8 +446,8 @@ void *Mod_LoadAllSkins (maliashdr_t *mheader, int numskins, daliasskintype_t *ps *skinrange++ = 1; // single skin skinnum++; sprintf (name, "%s_%i", loadmodel->name, i); - Mod_LoadSkin(mheader, name, (byte *)pskintype, skintemp, width, height, skintexnum); - skintexnum += 5; + Mod_LoadSkin(mheader, name, (byte *)pskintype, skintemp, width, height, skintex); + skintex += 5; pskintype = (daliasskintype_t *)((byte *)(pskintype) + s); } else @@ -447,8 +464,8 @@ void *Mod_LoadAllSkins (maliashdr_t *mheader, int numskins, daliasskintype_t *ps for (j = 0;j < groupskins;j++) { sprintf (name, "%s_%i_%i", loadmodel->name, i, j); - Mod_LoadSkin(mheader, name, (byte *)pskintype, skintemp, width, height, skintexnum); - skintexnum += 5; + Mod_LoadSkin(mheader, name, (byte *)pskintype, skintemp, width, height, skintex); + skintex += 5; pskintype = (daliasskintype_t *)((byte *)(pskintype) + s); } } @@ -482,8 +499,8 @@ void *Mod_SkipAllSkins (int numskins, daliasskintype_t *pskintype, int skinsize) Mod_LoadAliasModel ================= */ -#define BOUNDI(VALUE,MIN,MAX) if (VALUE < MIN || VALUE >= MAX) Host_Error("model %s has an invalid VALUE (%d exceeds %d - %d)\n", mod->name, VALUE, MIN, MAX); -#define BOUNDF(VALUE,MIN,MAX) if (VALUE < MIN || VALUE >= MAX) Host_Error("model %s has an invalid VALUE (%f exceeds %f - %f)\n", mod->name, VALUE, MIN, MAX); +#define BOUNDI(VALUE,MIN,MAX) if (VALUE < MIN || VALUE >= MAX) Host_Error("model %s has an invalid ##VALUE (%d exceeds %d - %d)\n", mod->name, VALUE, MIN, MAX); +#define BOUNDF(VALUE,MIN,MAX) if (VALUE < MIN || VALUE >= MAX) Host_Error("model %s has an invalid ##VALUE (%f exceeds %f - %f)\n", mod->name, VALUE, MIN, MAX); void Mod_LoadAliasModel (model_t *mod, void *buffer) { int i, j, version, numframes, start, end, total, numverts, numtris, numposes, numskins, skinwidth, skinheight, f, totalverts; @@ -495,8 +512,8 @@ void Mod_LoadAliasModel (model_t *mod, void *buffer) float *pouttexcoords, scales, scalet; maliashdr_t *mheader; unsigned short *pouttris; - maliasframe_t *frame; - trivert2 *posevert; + trivertx_t *posevert; + animscene_t *animscenes; start = Hunk_LowMark (); @@ -547,7 +564,6 @@ void Mod_LoadAliasModel (model_t *mod, void *buffer) // rebuild the model mheader = Hunk_AllocName (sizeof(maliashdr_t), va("%s model header", loadname)); mod->flags = LittleLong (pinmodel->flags); - mod->type = mod_alias; // endian-adjust and copy the data, starting with the alias model header mheader->numverts = numverts; mod->numtris = mheader->numtris = numtris; @@ -640,9 +656,7 @@ void Mod_LoadAliasModel (model_t *mod, void *buffer) // load the frames posenum = 0; - frame = Hunk_AllocName(sizeof(maliasframe_t) * numframes, va("%s frame info", loadname)); - mheader->framedata = (int) frame - (int) mheader; - posevert = Hunk_AllocName(sizeof(trivert2) * numposes * totalverts, va("%s vertex data", loadname)); + posevert = Hunk_AllocName(sizeof(trivertx_t) * numposes * totalverts, va("%s vertex data", loadname)); mheader->posedata = (int) posevert - (int) mheader; pframetype = (daliasframetype_t *)&pintriangles[numtris]; @@ -650,14 +664,18 @@ void Mod_LoadAliasModel (model_t *mod, void *buffer) aliasbboxmin[0] = aliasbboxmin[1] = aliasbboxmin[2] = 1000000000; aliasbboxmax[0] = aliasbboxmax[1] = aliasbboxmax[2] = -1000000000; - for (i=0 ; inumframes, va("%s sceneinfo", loadname)); + + for (i = 0;i < numframes;i++) { if ((aliasframetype_t) LittleLong (pframetype->type) == ALIAS_SINGLE) - pframetype = (daliasframetype_t *) Mod_LoadAliasFrame (pframetype + 1, frame++, mheader, numverts, totalverts, &posevert); + pframetype = (daliasframetype_t *) Mod_LoadAliasFrame (pframetype + 1, mheader, numverts, totalverts, &posevert, animscenes + i); else - pframetype = (daliasframetype_t *) Mod_LoadAliasGroup (pframetype + 1, frame++, mheader, numverts, totalverts, &posevert); + pframetype = (daliasframetype_t *) Mod_LoadAliasGroup (pframetype + 1, mheader, numverts, totalverts, &posevert, animscenes + i); } + mod->ofs_scenes = (int) animscenes - (int) mheader; + // 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; @@ -669,8 +687,8 @@ void Mod_LoadAliasModel (model_t *mod, void *buffer) // move the complete, relocatable alias model to the cache end = Hunk_LowMark (); - total = end - start; - + mod->cachesize = total = end - start; + Cache_Alloc (&mod->cache, total, loadname); if (!mod->cache.data) return; @@ -679,9 +697,9 @@ 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, trivert2 *out) +void Mod_ConvertQ2AliasVerts (int numverts, vec3_t scale, vec3_t translate, trivertx_t *v, trivertx_t *out) { - int i; + int i, invalidnormals = 0; vec3_t temp; for (i = 0;i < numverts;i++) { @@ -696,62 +714,15 @@ 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]; - out[i].n[0] = (signed char) (r_avertexnormals[v[i].lightnormalindex][0] * 127.0); - out[i].n[1] = (signed char) (r_avertexnormals[v[i].lightnormalindex][1] * 127.0); - out[i].n[2] = (signed char) (r_avertexnormals[v[i].lightnormalindex][2] * 127.0); - } - /* - int i, j; - vec3_t t1, t2; - struct - { - vec3_t v; - vec3_t normal; - int count; - } tempvert[MD2MAX_VERTS]; - temptris_t *tris; - // decompress vertices - for (i = 0;i < numverts;i++) - { - VectorCopy(v[i].v, out[i].v); - tempvert[i].v[0] = v[i].v[0] * scale[0] + translate[0]; - tempvert[i].v[1] = v[i].v[1] * scale[1] + translate[1]; - tempvert[i].v[2] = v[i].v[2] * scale[2] + translate[2]; - tempvert[i].normal[0] = tempvert[i].normal[1] = tempvert[i].normal[2] = 0; - tempvert[i].count = 0; - // update bounding box - if (tempvert[i].v[0] < aliasbboxmin[0]) aliasbboxmin[0] = tempvert[i].v[0]; - if (tempvert[i].v[1] < aliasbboxmin[1]) aliasbboxmin[1] = tempvert[i].v[1]; - if (tempvert[i].v[2] < aliasbboxmin[2]) aliasbboxmin[2] = tempvert[i].v[2]; - if (tempvert[i].v[0] > aliasbboxmax[0]) aliasbboxmax[0] = tempvert[i].v[0]; - if (tempvert[i].v[1] > aliasbboxmax[1]) aliasbboxmax[1] = tempvert[i].v[1]; - if (tempvert[i].v[2] > aliasbboxmax[2]) aliasbboxmax[2] = tempvert[i].v[2]; - } - // calculate surface normals - tris = temptris; - for (i = 0;i < numtris;i++) - { - VectorSubtract(tempvert[tris->v[0]].v, tempvert[tris->v[1]].v, t1); - VectorSubtract(tempvert[tris->v[2]].v, tempvert[tris->v[1]].v, t2); - CrossProduct(t1, t2, tris->normal); - VectorNormalize(tris->normal); - // add surface normal to vertices - for (j = 0;j < 3;j++) + out[i].lightnormalindex = v[i].lightnormalindex; + if (out[i].lightnormalindex >= NUMVERTEXNORMALS) { - VectorAdd(tris->normal, tempvert[tris->v[j]].normal, tempvert[tris->v[j]].normal); - tempvert[tris->v[j]].count++; + invalidnormals++; + out[i].lightnormalindex = 0; } - tris++; - } - // average normals and write out 1.7bit format - for (i = 0;i < pheader->numtris;i++) - { - VectorNormalize(tempvert[i].normal); - out[i].n[0] = (signed char) (tempvert[i].normal[0] * 127.0); - out[i].n[1] = (signed char) (tempvert[i].normal[1] * 127.0); - out[i].n[2] = (signed char) (tempvert[i].normal[2] * 127.0); } - */ + if (invalidnormals) + Con_Printf("Mod_ConvertQ2AliasVerts: %i invalid normal indices found\n", invalidnormals); } /* @@ -766,9 +737,10 @@ void Mod_LoadQ2AliasModel (model_t *mod, void *buffer) md2mem_t *pheader; md2triangle_t *pintriangles, *pouttriangles; md2frame_t *pinframe; - md2memframe_t *poutframe; + md2frame_t *poutframe; char *pinskins; // temptris_t *tris; + animscene_t *animscenes; start = Hunk_LowMark (); @@ -785,7 +757,7 @@ void Mod_LoadQ2AliasModel (model_t *mod, void *buffer) mod->type = mod_alias; mod->aliastype = ALIASTYPE_MD2; - framesize = sizeof(md2memframesize_t) + LittleLong(pinmodel->num_xyz) * sizeof(trivert2); + framesize = sizeof(md2framesize_t) + LittleLong(pinmodel->num_xyz) * sizeof(trivertx_t); // LordHavoc: calculate size for in memory version size = sizeof(md2mem_t) + LittleLong(pinmodel->num_st) * sizeof(md2stvert_t) @@ -818,7 +790,7 @@ void Mod_LoadQ2AliasModel (model_t *mod, void *buffer) Host_Error ("%s has invalid number of vertices: %i", mod->name, LittleLong(pinmodel->num_xyz)); if (LittleLong(pinmodel->num_frames < 1) || LittleLong(pinmodel->num_frames) > MD2MAX_FRAMES) Host_Error ("%s has invalid number of frames: %i", mod->name, LittleLong(pinmodel->num_frames)); - if (LittleLong(pinmodel->num_skins < 0) || LittleLong(pinmodel->num_skins) > MD2MAX_SKINS) + if (LittleLong(pinmodel->num_skins < 0) || LittleLong(pinmodel->num_skins) > MAX_SKINS) Host_Error ("%s has invalid number of skins: %i", mod->name, LittleLong(pinmodel->num_skins)); pheader->framesize = framesize; @@ -832,7 +804,8 @@ void Mod_LoadQ2AliasModel (model_t *mod, void *buffer) // load the skins if (pheader->num_skins) { - int *skin, *skinrange; + rtexture_t **skin; + int *skinrange; skinrange = loadmodel->skinanimrange; skin = loadmodel->skinanim; // skinrange = Hunk_AllocName (sizeof(int) * (pheader->num_skins * 2), loadname); @@ -844,11 +817,11 @@ void Mod_LoadQ2AliasModel (model_t *mod, void *buffer) { *skinrange++ = i; *skinrange++ = 1; - *skin++ = loadtextureimage (pinskins, 0, 0, true, true); - *skin++ = 0; // the extra 4 layers are currently unused - *skin++ = 0; - *skin++ = 0; - *skin++ = 0; + *skin++ = loadtextureimage (pinskins, 0, 0, true, r_mipskins.value, true); + *skin++ = NULL; // the extra 4 layers are currently unused + *skin++ = NULL; + *skin++ = NULL; + *skin++ = NULL; pinskins += MD2MAX_SKINNAME; } } @@ -860,9 +833,9 @@ void Mod_LoadQ2AliasModel (model_t *mod, void *buffer) pheader->ofs_tris = (int) pouttriangles - (int) pheader; // tris = temptris; // swap the triangle list - for (i=0 ; inum_tris ; i++) + for (i = 0;i < pheader->num_tris;i++) { - for (j=0 ; j<3 ; j++) + for (j = 0;j < 3;j++) { temptris[i][j] = pouttriangles->index_xyz[j] = LittleShort (pintriangles->index_xyz[j]); pouttriangles->index_st[j] = LittleShort (pintriangles->index_st[j]); @@ -883,19 +856,31 @@ void Mod_LoadQ2AliasModel (model_t *mod, void *buffer) pinframe = (void*) ((int) pinmodel + LittleLong(pinmodel->ofs_frames)); poutframe = (void*) pouttriangles; pheader->ofs_frames = (int) poutframe - (int) pheader; - for (i=0 ; inum_frames ; i++) + + animscenes = Hunk_AllocName(sizeof(animscene_t) * mod->numframes, va("%s sceneinfo", loadname)); + + for (i = 0;i < pheader->num_frames;i++) { + strcpy(poutframe->name, pinframe->name); for (j = 0;j < 3;j++) { - strcpy(poutframe->name, pinframe->name); poutframe->scale[j] = LittleFloat(pinframe->scale[j]); poutframe->translate[j] = LittleFloat(pinframe->translate[j]); } Mod_ConvertQ2AliasVerts (pheader->num_xyz, poutframe->scale, poutframe->translate, &pinframe->verts[0], &poutframe->verts[0]); + + strcpy(animscenes[i].name, poutframe->name); + animscenes[i].firstframe = i; + animscenes[i].framecount = 1; + animscenes[i].framerate = 10; + animscenes[i].loop = true; + pinframe = (void*) &pinframe->verts[j]; poutframe = (void*) &poutframe->verts[j]; } + mod->ofs_scenes = (int) animscenes - (int) pheader; + // LordHavoc: model bbox for (j = 0;j < 3;j++) { @@ -912,7 +897,7 @@ void Mod_LoadQ2AliasModel (model_t *mod, void *buffer) // move the complete, relocatable alias model to the cache end = Hunk_LowMark (); - total = end - start; + mod->cachesize = total = end - start; Cache_Alloc (&mod->cache, total, loadname); if (!mod->cache.data) @@ -931,11 +916,13 @@ void swapintblock(int *m, int size) void Mod_LoadZymoticModel (model_t *mod, void *buffer) { - int i, pbase, start, end, total, *skin, *skinrange, *texturenum; + int i, pbase, start, end, total, *skinrange; + rtexture_t **texture, **skin; char *shadername; zymtype1header_t *pinmodel, *pheader; zymscene_t *scene; zymbone_t *bone; + animscene_t *animscenes; start = Hunk_LowMark (); @@ -999,17 +986,18 @@ void Mod_LoadZymoticModel (model_t *mod, void *buffer) // loadmodel->skinanim = (int) skin - (int) pheader; *skinrange++ = 0; *skinrange++ = 1; - *skin++ = 0; - *skin++ = 0; - *skin++ = 0; - *skin++ = 0; - *skin++ = 0; + *skin++ = NULL; + *skin++ = NULL; + *skin++ = NULL; + *skin++ = NULL; + *skin++ = NULL; loadmodel->numskins = 1; // go through the lumps, swapping things // zymlump_t lump_scenes; // zymscene_t scene[numscenes]; // name and other information for each scene (see zymscene struct) scene = (void *) (pheader->lump_scenes.start + pbase); + animscenes = Hunk_AllocName(sizeof(animscene_t) * mod->numframes, va("%s sceneinfo", loadname)); for (i = 0;i < pheader->numscenes;i++) { scene->mins[0] = BigFloat(scene->mins[0]); @@ -1023,8 +1011,16 @@ void Mod_LoadZymoticModel (model_t *mod, void *buffer) scene->flags = BigLong(scene->flags); scene->start = BigLong(scene->start); scene->length = BigLong(scene->length); + + memcpy(animscenes[i].name, scene->name, 32); + animscenes[i].firstframe = scene->start; + animscenes[i].framecount = scene->length; + animscenes[i].framerate = scene->framerate; + animscenes[i].loop = (scene->flags & ZYMSCENEFLAG_NOLOOP) == 0; + scene++; } + mod->ofs_scenes = (int) animscenes - pbase; // zymlump_t lump_poses; // float pose[numposes][numbones][6]; // animation data swapintblock((void *) (pheader->lump_poses.start + pbase), pheader->lump_poses.length); @@ -1052,13 +1048,13 @@ void Mod_LoadZymoticModel (model_t *mod, void *buffer) // zymlump_t lump_shaders; // char shadername[numshaders][32]; // shaders used on this model shadername = (void *) (pheader->lump_shaders.start + pbase); - texturenum = (void *) shadername; + texture = (void *) shadername; for (i = 0;i < pheader->numshaders;i++) { - int j; - j = loadtextureimage(shadername, 0, 0, true, true); + rtexture_t *rt; + rt = loadtextureimage(shadername, 0, 0, true, r_mipskins.value, true); shadername += 32; - *texturenum++ = j; // reuse shader name list for texture numbers + *texture++ = rt; // reuse shader name list for texture pointers } // zymlump_t lump_trizone; // byte trizone[numtris]; // see trizone explanation @@ -1073,7 +1069,7 @@ void Mod_LoadZymoticModel (model_t *mod, void *buffer) // move the complete, relocatable alias model to the cache end = Hunk_LowMark (); - total = end - start; + mod->cachesize = total = end - start; Cache_Alloc (&mod->cache, total, loadname); if (!mod->cache.data) diff --git a/model_alias.h b/model_alias.h index 73e83107..4d30cdae 100644 --- a/model_alias.h +++ b/model_alias.h @@ -61,13 +61,6 @@ typedef struct mtriangle_s { } mtriangle_t; */ -// LordHavoc: new vertex format -typedef struct { - byte v[3]; // location - signed char n[3]; // surface normal for lighting *127.0 -} trivert2; - -#define MAX_SKINS 32 typedef struct { int ident; int version; @@ -86,14 +79,6 @@ typedef struct { float size; } daliashdr_t; -typedef struct -{ - char name[16]; // LordHavoc: only kept this for reasons of viewthing support - unsigned short start; - unsigned short length; - float rate; // in poses per second -} maliasframe_t; - typedef struct { vec3_t scale; @@ -102,7 +87,6 @@ typedef struct int numtris; int numframes; int numposes; - int framedata; // LordHavoc: unsigned short start int texdata; // LordHavoc: texture coordinate array int posedata; // LordHavoc: vertex data for all the poses int tridata; // LordHavoc: vertex indices for the triangles @@ -129,7 +113,6 @@ typedef struct #define MD2MAX_TRIANGLES 4096 #define MD2MAX_VERTS 4096 #define MD2MAX_FRAMES 1024 -#define MD2MAX_SKINS 32 #define MD2MAX_SKINNAME 64 // sanity checking size #define MD2MAX_SIZE (16777216) @@ -154,21 +137,12 @@ typedef struct trivertx_t verts[1]; // variable sized } md2frame_t; -// LordHavoc: memory representation is different than disk -typedef struct -{ - float scale[3]; // multiply byte verts by this - float translate[3]; // then add this - char name[16]; // LordHavoc: kept for viewthing - trivert2 verts[1]; // variable sized -} md2memframe_t; - -// must match md2memframe_t, this is just used for sizeof() +// must match md2frame_t, this is just used for sizeof() typedef struct { float scale[3]; // multiply byte verts by this float translate[3]; // then add this -} md2memframesize_t; +} md2framesize_t; // the glcmd format: diff --git a/model_brush.c b/model_brush.c index 86d565a2..33350406 100644 --- a/model_brush.c +++ b/model_brush.c @@ -39,7 +39,56 @@ void Mod_BrushInit (void) memset (mod_novis, 0xff, sizeof(mod_novis)); } -// Mod_PointInLeaf moved to cpu_noasm.c +/* +=============== +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"); + + node = model->nodes; + if (node->contents < 0) + return (mleaf_t *)node; + while (1) + { + node = node->children[(node->plane->type < 3 ? p[node->plane->type] : DotProduct (p,node->plane->normal)) < node->plane->dist]; + if (node->contents < 0) + return (mleaf_t *)node; + } + + return NULL; // never reached +} +/* +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"); + + node = model->nodes; + while (1) + { + if (node->contents < 0) + return (mleaf_t *)node; + plane = node->plane; + d = DotProduct (p,plane->normal) - plane->dist; + if (d > 0) + node = node->children[0]; + else + node = node->children[1]; + } + + return NULL; // never reached +} +*/ /* =================== @@ -104,7 +153,7 @@ Mod_LoadTextures */ void Mod_LoadTextures (lump_t *l) { - int i, j, num, max, altmax, bytesperpixel, freeimage, transparent, fullbrights; + int i, j, num, max, altmax; miptex_t *mt; texture_t *tx, *tx2; texture_t *anims[10]; @@ -156,143 +205,135 @@ void Mod_LoadTextures (lump_t *l) for (;j < 16;j++) tx->name[j] = 0; - tx->width = mt->width; - tx->height = mt->height; for (j=0 ; joffsets[j] = 0; - freeimage = true; - transparent = true; - fullbrights = false; - bytesperpixel = 4; - data = loadimagepixels(tx->name, false, 0, 0); //tx->width, tx->height); - if (!data) // no external texture found + tx->transparent = false; + data = loadimagepixels(tx->name, false, 0, 0); + if (data) + { + if (!hlbsp && !strncmp(tx->name,"sky",3) && image_width == 256 && image_height == 128) // LordHavoc: HL sky textures are entirely unrelated + { + tx->width = image_width; + tx->height = image_height; + tx->transparent = false; + tx->texture = NULL; + tx->glowtexture = NULL; + R_InitSky (data, 4); + } + else + { + tx->width = mt->width; + tx->height = mt->height; + tx->transparent = true; + tx->texture = R_LoadTexture (tx->name, image_width, image_height, data, TEXF_MIPMAP | TEXF_ALPHA | TEXF_RGBA | TEXF_PRECACHE); + tx->glowtexture = NULL; + } + qfree(data); + } + else { - if (hlbsp) + if (!hlbsp && !strncmp(tx->name,"sky",3) && mt->width == 256 && mt->height == 128) // LordHavoc: HL sky textures are entirely unrelated { - if (mt->offsets[0]) // texture included + tx->width = mt->width; + tx->height = mt->height; + tx->transparent = false; + tx->texture = NULL; + tx->glowtexture = NULL; + R_InitSky ((byte *)((int) mt + mt->offsets[0]), 1); + } + else + { + if (hlbsp) { - freeimage = true; - transparent = true; - bytesperpixel = 4; - data = W_ConvertWAD3Texture(mt); - tx->width = image_width; - tx->height = image_height; - /* - byte *in, *out, *pal; -// int palsize; - int d, p; - bytesperpixel = 4; - freeimage = true; - transparent = false; - in = (byte *)((int) mt + mt->offsets[0]); - data = out = qmalloc(mt->width * mt->height * 4); - pal = in + (((mt->width * mt->height) * 85) >> 6); -// palsize = pal[1] * 0x100 + pal[0]; -// if (palsize >= 256) -// palsize = 256; - pal += 2; - for (d = 0;d < mt->width * mt->height;d++) + if (mt->offsets[0]) // texture included { - p = *in++; - if (mt->name[0] == '{' && p == 255) + data = W_ConvertWAD3Texture(mt); + if (data) { - out[0] = out[1] = out[2] = out[3] = 0; - transparent = true; + tx->width = mt->width; + tx->height = mt->height; + tx->transparent = true; + tx->texture = R_LoadTexture (tx->name, mt->width, mt->height, data, TEXF_MIPMAP | TEXF_ALPHA | TEXF_RGBA | TEXF_PRECACHE); + tx->glowtexture = NULL; + qfree(data); } - else + } + if (!data) + { + data = W_GetTexture(mt->name); + // get the size from the wad texture + if (data) { - p *= 3; - out[0] = pal[p]; - out[1] = pal[p+1]; - out[2] = pal[p+2]; - out[3] = 255; + tx->width = image_width; + tx->height = image_height; + tx->transparent = true; + tx->texture = R_LoadTexture (tx->name, image_width, image_height, data, TEXF_MIPMAP | TEXF_ALPHA | TEXF_RGBA | TEXF_PRECACHE); + tx->glowtexture = NULL; + qfree(data); } - out += 4; } - */ - } - if (!data) - { - freeimage = true; - transparent = true; - bytesperpixel = 4; - data = W_GetTexture(mt->name); - tx->width = image_width; - tx->height = image_height; - } - if (!data) - { - freeimage = false; - transparent = false; - bytesperpixel = 1; - data = (byte *)((int) r_notexture_mip + r_notexture_mip->offsets[0]); - tx->width = tx->height = 16; + if (!data) + { + tx->width = r_notexture_mip->width; + tx->height = r_notexture_mip->height; + tx->transparent = false; + tx->texture = R_LoadTexture ("notexture", tx->width, tx->height, (byte *)((int) r_notexture_mip + r_notexture_mip->offsets[0]), TEXF_MIPMAP | TEXF_PRECACHE); + tx->glowtexture = NULL; + } } - } - else - { - if (mt->offsets[0]) // texture included + else { - freeimage = false; - transparent = false; - bytesperpixel = 1; - data = (byte *)((int) mt + mt->offsets[0]); - tx->width = mt->width; - tx->height = mt->height; - if (r_fullbrights.value && tx->name[0] != '*') + if (mt->offsets[0]) // texture included { - for (j = 0;j < tx->width*tx->height;j++) + int fullbrights; + data = (byte *)((int) mt + mt->offsets[0]); + tx->width = mt->width; + tx->height = mt->height; + tx->transparent = false; + fullbrights = false; + if (r_fullbrights.value && tx->name[0] != '*') { - if (data[j] >= 224) // fullbright + for (j = 0;j < tx->width*tx->height;j++) { - fullbrights = true; - break; + if (data[j] >= 224) // fullbright + { + fullbrights = true; + break; + } } } + if (fullbrights) + { + char name[64]; + byte *data2; + data2 = qmalloc(tx->width*tx->height); + for (j = 0;j < tx->width*tx->height;j++) + data2[j] = data[j] >= 224 ? 0 : data[j]; // no fullbrights + tx->texture = R_LoadTexture (tx->name, tx->width, tx->height, data2, TEXF_MIPMAP | TEXF_PRECACHE); + strcpy(name, tx->name); + strcat(name, "_glow"); + for (j = 0;j < tx->width*tx->height;j++) + data2[j] = data[j] >= 224 ? data[j] : 0; // only fullbrights + tx->glowtexture = R_LoadTexture (name, tx->width, tx->height, data2, TEXF_MIPMAP | TEXF_PRECACHE); + qfree(data2); + } + else + { + tx->texture = R_LoadTexture (tx->name, tx->width, tx->height, data, TEXF_MIPMAP | TEXF_PRECACHE); + tx->glowtexture = NULL; + } + } + else // no texture, and no external replacement texture was found + { + tx->width = r_notexture_mip->width; + tx->height = r_notexture_mip->height; + tx->transparent = false; + tx->texture = R_LoadTexture ("notexture", tx->width, tx->height, (byte *)((int) r_notexture_mip + r_notexture_mip->offsets[0]), TEXF_MIPMAP | TEXF_PRECACHE); + tx->glowtexture = NULL; } - } - else // no texture, and no external replacement texture was found - { - freeimage = false; - transparent = false; - bytesperpixel = 1; - data = (byte *)((int) r_notexture_mip + r_notexture_mip->offsets[0]); - tx->width = tx->height = 16; } } } - if (!hlbsp && !strncmp(tx->name,"sky",3) && tx->width == 256 && tx->height == 128) // LordHavoc: HL sky textures are entirely unrelated - { - tx->transparent = false; - R_InitSky (data, bytesperpixel); - } - else - { - if (fullbrights) - { - char name[64]; - byte *data2; - tx->transparent = false; - data2 = qmalloc(tx->width*tx->height); - for (j = 0;j < tx->width*tx->height;j++) - data2[j] = data[j] >= 224 ? 0 : data[j]; // no fullbrights - tx->gl_texturenum = GL_LoadTexture (tx->name, tx->width, tx->height, data2, true, false, 1); - strcpy(name, tx->name); - strcat(name, "_glow"); - for (j = 0;j < tx->width*tx->height;j++) - data2[j] = data[j] >= 224 ? data[j] : 0; // only fullbrights - tx->gl_glowtexturenum = GL_LoadTexture (name, tx->width, tx->height, data2, true, false, 1); - qfree(data2); - } - else - { - tx->transparent = transparent; - tx->gl_texturenum = GL_LoadTexture (tx->name, tx->width, tx->height, data, true, transparent, bytesperpixel); - tx->gl_glowtexturenum = 0; - } - } - if (freeimage) - qfree(data); } // @@ -304,7 +345,7 @@ void Mod_LoadTextures (lump_t *l) if (!tx || tx->name[0] != '+') continue; if (tx->anim_next) - continue; // allready sequenced + continue; // already sequenced // find the number of frames in the animation memset (anims, 0, sizeof(anims)); @@ -773,7 +814,7 @@ void Mod_LoadFaces (lump_t *l) // if (!strncmp(out->texinfo->texture->name,"*",1)) // turbulent if (out->texinfo->texture->name[0] == '*') // LordHavoc: faster check { - out->flags |= (SURF_DRAWTURB | SURF_DRAWTILED); + out->flags |= (SURF_DRAWTURB | SURF_DRAWTILED | SURF_LIGHTBOTHSIDES); // LordHavoc: some turbulent textures should be fullbright and solid if (!strncmp(out->texinfo->texture->name,"*lava",5) || !strncmp(out->texinfo->texture->name,"*teleport",9) diff --git a/model_brush.h b/model_brush.h index 2ca09612..33b05069 100644 --- a/model_brush.h +++ b/model_brush.h @@ -55,8 +55,8 @@ typedef struct texture_s { char name[16]; unsigned width, height; - int gl_texturenum; - int gl_glowtexturenum; // LordHavoc: fullbrights on walls + rtexture_t *texture; + rtexture_t *glowtexture; // LordHavoc: fullbrights on walls struct msurface_s *texturechain; // for gl_texsort drawing int anim_total; // total tenths in sequence ( 0 = no) int anim_min, anim_max; // time for this frame min <=time< max @@ -77,6 +77,8 @@ typedef struct texture_s // LordHavoc: added these for lava and teleport textures #define SURF_DRAWNOALPHA 0x100 #define SURF_DRAWFULLBRIGHT 0x200 +// LordHavoc: light both sides +#define SURF_LIGHTBOTHSIDES 0x400 // !!! if this is changed, it must be changed in asm_draw.h too !!! typedef struct diff --git a/model_shared.c b/model_shared.c index d9d0efbc..1aaac8e4 100644 --- a/model_shared.c +++ b/model_shared.c @@ -34,7 +34,8 @@ extern void Mod_LoadQ2AliasModel (model_t *mod, void *buffer); extern void Mod_LoadZymoticModel (model_t *mod, void *buffer); model_t *Mod_LoadModel (model_t *mod, qboolean crash); -#define MAX_MOD_KNOWN 512 +// LordHavoc: increased from 512 to 2048 +#define MAX_MOD_KNOWN 2048 model_t mod_known[MAX_MOD_KNOWN]; int mod_numknown; @@ -87,7 +88,7 @@ void Mod_ClearAll (void) model_t *mod; for (i=0 , mod=mod_known ; itype != mod_alias) + if (!mod->cachesize) mod->needload = true; } @@ -137,10 +138,8 @@ void Mod_TouchModel (char *name) mod = Mod_FindName (name); if (!mod->needload) - { - if (mod->type == mod_alias) + if (mod->cachesize) Cache_Check (&mod->cache); - } } /* @@ -157,7 +156,7 @@ model_t *Mod_LoadModel (model_t *mod, qboolean crash) if (!mod->needload) { - if (mod->type == mod_alias) + if (mod->cachesize) { d = Cache_Check (&mod->cache); if (d) @@ -263,7 +262,7 @@ void Mod_Print (void) Con_Printf ("Cached models:\n"); for (i=0, mod=mod_known ; i < mod_numknown ; i++, mod++) { - Con_Printf ("%8p : %s\n",mod->cache.data, mod->name); + Con_Printf ("%4iK : %8p : %s\n", (mod->cachesize + 1023) / 1024, mod->cache.data, mod->name); } } diff --git a/model_shared.h b/model_shared.h index d3a701a7..1d50a07b 100644 --- a/model_shared.h +++ b/model_shared.h @@ -35,6 +35,19 @@ m*_t structures are in-memory typedef enum {mod_brush, mod_sprite, mod_alias} modtype_t; +typedef struct animscene_s +{ + char name[32]; // for viewthing support + int firstframe; + int framecount; + int loop; // true or false + float framerate; +} +animscene_t; + +#define MAX_SKINS 256 + + #include "model_brush.h" #include "model_sprite.h" #include "model_alias.h" @@ -42,7 +55,7 @@ typedef enum {mod_brush, mod_sprite, mod_alias} modtype_t; typedef struct model_s { char name[MAX_QPATH]; - qboolean needload; // bmodels and sprites don't cache normally + qboolean needload; // bmodels don't cache normally modtype_t type; int aliastype; // LordHavoc: Q2 model support @@ -108,11 +121,16 @@ typedef struct model_s // LordHavoc: useful for sprites and models int numtris; int numskins; - int skinanimrange[1024]; // array of start and length pairs, note: offset from ->cache.data - int skinanim[1024*5]; // texture numbers for each frame (indexed by animrange), note: offset from ->cache.data, second note: normal pants shirt glow body (normal contains no shirt/pants/glow colors and body is normal + pants + shirt, but not glow) + 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 // additional model data cache_user_t cache; // only access through Mod_Extradata + int cachesize; // size of cached data (zero if not cached) } model_t; diff --git a/model_sprite.c b/model_sprite.c index 4db67bca..fda321ee 100644 --- a/model_sprite.c +++ b/model_sprite.c @@ -24,6 +24,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "quakedef.h" +cvar_t r_mipsprites = {"r_mipsprites", "1", true}; + /* =============== Mod_SpriteInit @@ -31,6 +33,7 @@ Mod_SpriteInit */ void Mod_SpriteInit (void) { + Cvar_RegisterVariable(&r_mipsprites); } void Mod_Sprite_StripExtension(char *in, char *out) @@ -53,7 +56,7 @@ void Mod_Sprite_StripExtension(char *in, char *out) Mod_LoadSpriteFrame ================= */ -void * Mod_LoadSpriteFrame (void * pin, mspriteframe_t **ppframe, int framenum, int bytesperpixel) +void * Mod_LoadSpriteFrame (void * pin, mspriteframe_t *frame, int framenum, int bytesperpixel) { dspriteframe_t *pinframe; mspriteframe_t *pspriteframe; @@ -67,14 +70,12 @@ void * Mod_LoadSpriteFrame (void * pin, mspriteframe_t **ppframe, int framenum, height = LittleLong (pinframe->height); size = width * height * bytesperpixel; - pspriteframe = Hunk_AllocName (sizeof (mspriteframe_t), va("%s frames", loadname)); + pspriteframe = frame; memset (pspriteframe, 0, sizeof (mspriteframe_t)); - *ppframe = pspriteframe; - - pspriteframe->width = width; - pspriteframe->height = height; +// pspriteframe->width = width; +// pspriteframe->height = height; origin[0] = LittleLong (pinframe->origin[0]); origin[1] = LittleLong (pinframe->origin[1]); @@ -85,11 +86,11 @@ void * Mod_LoadSpriteFrame (void * pin, mspriteframe_t **ppframe, int framenum, Mod_Sprite_StripExtension(loadmodel->name, tempname); sprintf (name, "%s_%i", tempname, framenum); - pspriteframe->gl_texturenum = loadtextureimagewithmask(name, 0, 0, false, true); - pspriteframe->gl_fogtexturenum = image_masktexnum; - if (pspriteframe->gl_texturenum == 0) + pspriteframe->texture = loadtextureimagewithmask(name, 0, 0, false, r_mipsprites.value, true); + pspriteframe->fogtexture = image_masktex; + if (!pspriteframe->texture) { - pspriteframe->gl_texturenum = GL_LoadTexture (name, width, height, (byte *)(pinframe + 1), true, true, bytesperpixel); + pspriteframe->texture = R_LoadTexture (name, width, height, (byte *)(pinframe + 1), TEXF_ALPHA | (bytesperpixel > 1 ? TEXF_RGBA : 0) | (r_mipsprites.value ? TEXF_MIPMAP : 0) | TEXF_PRECACHE); // make fog version (just alpha) pixbuf = pixel = qmalloc(width*height*4); inpixel = (byte *)(pinframe + 1); @@ -119,7 +120,7 @@ void * Mod_LoadSpriteFrame (void * pin, mspriteframe_t **ppframe, int framenum, } } sprintf (name, "%s_%ifog", loadmodel->name, framenum); - pspriteframe->gl_fogtexturenum = GL_LoadTexture (name, width, height, pixbuf, true, true, 4); + pspriteframe->fogtexture = R_LoadTexture (name, width, height, pixbuf, TEXF_ALPHA | TEXF_RGBA | (r_mipsprites.value ? TEXF_MIPMAP : 0) | TEXF_PRECACHE); qfree(pixbuf); } @@ -132,45 +133,15 @@ void * Mod_LoadSpriteFrame (void * pin, mspriteframe_t **ppframe, int framenum, Mod_LoadSpriteGroup ================= */ -void * Mod_LoadSpriteGroup (void * pin, mspriteframe_t **ppframe, int framenum, int bytesperpixel) +void *Mod_LoadSpriteGroup (void * pin, mspriteframe_t *frame, int numframes, int framenum, int bytesperpixel) { - dspritegroup_t *pingroup; - mspritegroup_t *pspritegroup; - int i, numframes; - dspriteinterval_t *pin_intervals; - float *poutintervals; - void *ptemp; - - pingroup = (dspritegroup_t *)pin; - - numframes = LittleLong (pingroup->numframes); - - pspritegroup = Hunk_AllocName (sizeof (mspritegroup_t) + (numframes - 1) * sizeof (pspritegroup->frames[0]), va("%s frames", loadname)); + int i; + void *ptemp; - pspritegroup->numframes = numframes; + ptemp = (void *)(sizeof(dspriteinterval_t) * numframes + sizeof(dspritegroup_t) + (int) pin); - *ppframe = (mspriteframe_t *)pspritegroup; - - pin_intervals = (dspriteinterval_t *)(pingroup + 1); - - poutintervals = Hunk_AllocName (numframes * sizeof (float), va("%s frames", loadname)); - - pspritegroup->intervals = poutintervals; - - for (i=0 ; iinterval); - if (*poutintervals <= 0.0) - Host_Error ("Mod_LoadSpriteGroup: interval<=0"); - - poutintervals++; - pin_intervals++; - } - - ptemp = (void *)pin_intervals; - - for (i=0 ; iframes[i], framenum * 100 + i, bytesperpixel); + for (i = 0;i < numframes;i++) + ptemp = Mod_LoadSpriteFrame (ptemp, frame++, framenum * 100 + i, bytesperpixel); return ptemp; } @@ -183,15 +154,16 @@ Mod_LoadSpriteModel */ void Mod_LoadSpriteModel (model_t *mod, void *buffer) { - int i; - int version; + int i, j, version, numframes, realframes, size, bytesperpixel, start, end, total, maxwidth, maxheight; dsprite_t *pin; msprite_t *psprite; - int numframes; - int size; dspriteframetype_t *pframetype; - // LordHavoc: 32bit textures - int bytesperpixel; + dspriteframe_t *pframe; + animscene_t *animscenes; + mspriteframe_t *frames; + dspriteframe_t **framedata; + + start = Hunk_LowMark (); mod->flags = EF_FULLBRIGHT; // LordHavoc: hack to allow sprites to be non-fullbright @@ -204,6 +176,9 @@ void Mod_LoadSpriteModel (model_t *mod, void *buffer) } } + // build a list of frames while parsing + framedata = qmalloc(65536*sizeof(dspriteframe_t)); + pin = (dsprite_t *)buffer; version = LittleLong (pin->version); @@ -214,31 +189,28 @@ void Mod_LoadSpriteModel (model_t *mod, void *buffer) } // LordHavoc: 32bit textures if (version != SPRITE_VERSION && version != SPRITE32_VERSION) - Host_Error ("%s has wrong version number " - "(%i should be %i or %i)", mod->name, version, SPRITE_VERSION, SPRITE32_VERSION); + Host_Error ("%s has wrong version number (%i should be %i or %i)", mod->name, version, SPRITE_VERSION, SPRITE32_VERSION); bytesperpixel = 1; if (version == SPRITE32_VERSION) bytesperpixel = 4; numframes = LittleLong (pin->numframes); - size = sizeof (msprite_t) + (numframes - 1) * sizeof (psprite->frames); + psprite = Hunk_AllocName (sizeof(msprite_t), va("%s info", loadname)); - psprite = Hunk_AllocName (size, va("%s info", loadname)); - - mod->cache.data = psprite; +// mod->cache.data = psprite; psprite->type = LittleLong (pin->type); - psprite->maxwidth = LittleLong (pin->width); - psprite->maxheight = LittleLong (pin->height); - psprite->beamlength = LittleFloat (pin->beamlength); + maxwidth = LittleLong (pin->width); + maxheight = LittleLong (pin->height); +// psprite->beamlength = LittleFloat (pin->beamlength); mod->synctype = LittleLong (pin->synctype); - psprite->numframes = numframes; +// psprite->numframes = numframes; - mod->mins[0] = mod->mins[1] = -psprite->maxwidth/2; - mod->maxs[0] = mod->maxs[1] = psprite->maxwidth/2; - mod->mins[2] = -psprite->maxheight/2; - mod->maxs[2] = psprite->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 @@ -250,18 +222,75 @@ void Mod_LoadSpriteModel (model_t *mod, void *buffer) pframetype = (dspriteframetype_t *)(pin + 1); - for (i=0 ; inumframes, va("%s sceneinfo", loadname)); + + realframes = 0; + + for (i = 0;i < numframes;i++) { spriteframetype_t frametype; frametype = LittleLong (pframetype->type); - psprite->frames[i].type = frametype; + sprintf(animscenes[i].name, "frame%i", i); + animscenes[i].firstframe = realframes; + animscenes[i].loop = true; if (frametype == SPR_SINGLE) - pframetype = (dspriteframetype_t *) Mod_LoadSpriteFrame (pframetype + 1, &psprite->frames[i].frameptr, i, bytesperpixel); + { + animscenes[i].framecount = 1; + animscenes[i].framerate = 10; + pframe = (dspriteframe_t *) (pframetype + 1); + framedata[realframes] = pframe; + size = LittleLong(pframe->width) * LittleLong(pframe->height) * bytesperpixel; + pframetype = (dspriteframetype_t *) (size + sizeof(dspriteframe_t) + (int) pframe); + realframes++; + } else - pframetype = (dspriteframetype_t *) Mod_LoadSpriteGroup (pframetype + 1, &psprite->frames[i].frameptr, i, bytesperpixel); + { + j = LittleLong(((dspritegroup_t *) (sizeof(dspriteframetype_t) + (int) pframetype))->numframes); + animscenes[i].framecount = j; + // FIXME: support variable framerate? + animscenes[i].framerate = 1.0f / LittleFloat(((dspriteinterval_t *) (sizeof(dspritegroup_t) + sizeof(dspriteframetype_t) + (int) pframetype))->interval); + pframe = (dspriteframe_t *) (sizeof(dspriteinterval_t) * j + sizeof(dspritegroup_t) + sizeof(dspriteframetype_t) + (int) pframetype); + while (j--) + { + framedata[realframes] = pframe; + size = LittleLong(pframe->width) * LittleLong(pframe->height) * bytesperpixel; + pframe = (dspriteframe_t *) (size + sizeof(dspriteframe_t) + (int) pframe); + realframes++; + } + pframetype = (dspriteframetype_t *) pframe; + } } + mod->ofs_scenes = (int) animscenes - (int) psprite; + + frames = Hunk_AllocName(sizeof(mspriteframe_t) * realframes, va("%s frames", loadname)); + + realframes = 0; + for (i = 0;i < numframes;i++) + { + for (j = 0;j < animscenes[i].framecount;j++) + { + Mod_LoadSpriteFrame (framedata[realframes], frames + realframes, i, bytesperpixel); + realframes++; + } + } + + psprite->ofs_frames = (int) frames - (int) psprite; + + qfree(framedata); + mod->type = mod_sprite; + +// move the complete, relocatable sprite model to the cache + end = Hunk_LowMark (); + mod->cachesize = total = end - start; + + Cache_Alloc (&mod->cache, total, loadname); + if (!mod->cache.data) + return; + memcpy (mod->cache.data, psprite, total); + + Hunk_FreeToLowMark (start); } diff --git a/model_sprite.h b/model_sprite.h index c07c8883..595f2266 100644 --- a/model_sprite.h +++ b/model_sprite.h @@ -31,32 +31,19 @@ SPRITE MODELS // FIXME: shorten these? typedef struct mspriteframe_s { - int width; - int height; +// int width; +// int height; float up, down, left, right; - int gl_texturenum, gl_fogtexturenum; + rtexture_t *texture, *fogtexture; } mspriteframe_t; -typedef struct -{ - int numframes; - float *intervals; - mspriteframe_t *frames[1]; -} mspritegroup_t; - -typedef struct -{ - spriteframetype_t type; - mspriteframe_t *frameptr; -} mspriteframedesc_t; - typedef struct { int type; - int maxwidth; - int maxheight; - int numframes; - float beamlength; // remove? - void *cachespot; // remove? - mspriteframedesc_t frames[1]; +// int maxwidth; +// int maxheight; +// int numframes; +// float beamlength; // remove? +// void *cachespot; // remove? + int ofs_frames; } msprite_t; diff --git a/net.h b/net.h index 71dc2541..b41cadce 100644 --- a/net.h +++ b/net.h @@ -28,7 +28,7 @@ struct qsockaddr #define NET_NAMELEN 64 -#define NET_MAXMESSAGE 8192 +#define NET_MAXMESSAGE 16384 #define NET_HEADERSIZE (2 * sizeof(unsigned int)) #define NET_DATAGRAMSIZE (MAX_DATAGRAM + NET_HEADERSIZE) diff --git a/pr_cmds.c b/pr_cmds.c index e9c3effd..e4ba51a9 100644 --- a/pr_cmds.c +++ b/pr_cmds.c @@ -31,6 +31,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. =============================================================================== */ + char *PF_VarString (int first) { int i; @@ -44,60 +45,65 @@ char *PF_VarString (int first) return out; } -char *QSG_EXTENSIONS = "\ -DP_BLOOD \ -DP_BLOODSHOWER \ -DP_CORPSE \ -DP_DRAWONLYTOCLIENT \ -DP_EXPLOSION3 \ -DP_PARTICLECUBE \ -DP_PARTICLERAIN \ -DP_PARTICLESNOW \ -DP_GETLIGHT \ -DP_NODRAWTOCLIENT \ -DP_RANDOMVEC \ +char *ENGINE_EXTENSIONS = "\ +DP_ENT_ALPHA \ +DP_ENT_COLORMOD \ +DP_ENT_DELTACOMPRESS \ +DP_ENT_GLOW \ +DP_ENT_SCALE \ +DP_ENT_VIEWMODEL \ +DP_GFX_FOG \ +DP_HALFLIFE_MAP \ +DP_INPUTBUTTONS \ +DP_MONSTERWALK \ +DP_MOVETYPEFOLLOW \ +DP_SOLIDCORPSE \ DP_REGISTERCVAR \ -DP_SPARK \ DP_SPRITE32 \ -DP_MODEL32 \ -DP_TRACEBOX \ -DP_MINMAXBOUND \ -DP_FINDFLOAT \ -NEH_PLAY2 \ -QSG_ALPHA \ -QSG_BUTTONS \ -QSG_CHANGEPITCH \ -QSG_COLORMOD \ -QSG_DELTA \ -QSG_ETOS \ -QSG_FOG \ -QSG_FOLLOW \ -QSG_GLOW \ -QSG_MATH \ -QSG_MONSTERWALK \ -QSG_QUAKE2MODEL \ -QSG_SCALE \ -QSG_SKYBOX \ -QSG_TRACETOSS \ -QSG_VIEWMODEL \ -QSG_COPYENT \ +DP_SV_DRAWONLYTOCLIENT \ +DP_SV_NODRAWTOCLIENT \ +DP_SV_SETCOLOR \ +DP_SV_EFFECT \ +DP_TE_BLOOD \ +DP_TE_BLOODSHOWER \ +DP_TE_EXPLOSIONRGB \ +DP_TE_PARTICLECUBE \ +DP_TE_PARTICLERAIN \ +DP_TE_PARTICLESNOW \ +DP_TE_SPARK \ +DP_QC_CHANGEPITCH \ +DP_QC_COPYENTITY \ +DP_QC_ETOS \ +DP_QC_FINDFLOAT \ +DP_QC_FINDCHAIN \ +DP_QC_FINDCHAINFLOAT \ +DP_QC_GETLIGHT \ +DP_QC_SINCOSSQRTPOW \ +DP_QC_MINMAXBOUND \ +DP_QC_RANDOMVEC \ +DP_QC_TRACEBOX \ +DP_QC_TRACETOSS \ +DP_QUAKE2_MODEL \ +NEH_CMD_PLAY2 \ "; qboolean checkextension(char *name) { int len; - char *e; + char *e, *start; len = strlen(name); - for (e = QSG_EXTENSIONS;*e;e++) + for (e = ENGINE_EXTENSIONS;*e;e++) { while (*e == ' ') e++; if (!*e) break; - if (!strncasecmp(e, name, len)) - return true; + start = e; while (*e && *e != ' ') e++; + if (e - start == len) + if (!strncasecmp(e, name, len)) + return true; } return false; } @@ -132,8 +138,7 @@ void PF_error (void) edict_t *ed; s = PF_VarString(0); - Con_Printf ("======SERVER ERROR in %s:\n%s\n" - ,pr_strings + pr_xfunction->s_name,s); + Con_Printf ("======SERVER ERROR in %s:\n%s\n", pr_strings + pr_xfunction->s_name, s); ed = PROG_TO_EDICT(pr_global_struct->self); ED_Print (ed); @@ -156,13 +161,13 @@ void PF_objerror (void) edict_t *ed; s = PF_VarString(0); - Con_Printf ("======OBJECT ERROR in %s:\n%s\n" - ,pr_strings + pr_xfunction->s_name,s); + Con_Printf ("======OBJECT ERROR in %s:\n%s\n", pr_strings + pr_xfunction->s_name, s); ed = PROG_TO_EDICT(pr_global_struct->self); ED_Print (ed); ED_Free (ed); - - Host_Error ("Program error"); + +// LordHavoc: bug fix - no longer kills server +// Host_Error ("Program error"); } @@ -180,6 +185,20 @@ void PF_makevectors (void) AngleVectors (G_VECTOR(OFS_PARM0), pr_global_struct->v_forward, pr_global_struct->v_right, pr_global_struct->v_up); } +/* +============== +PF_vectorvectors + +Writes new values for v_forward, v_up, and v_right based on the given forward vector +vectorvectors(vector, vector) +============== +*/ +void PF_vectorvectors (void) +{ + VectorNormalize2(G_VECTOR(OFS_PARM0), pr_global_struct->v_forward); + VectorVectors(pr_global_struct->v_forward, pr_global_struct->v_right, pr_global_struct->v_up); +} + /* ================= PF_setorigin @@ -203,6 +222,7 @@ void PF_setorigin (void) void SetMinMaxSize (edict_t *e, float *min, float *max, qboolean rotate) { + /* float *angles; vec3_t rmin, rmax; float bounds[2][3]; @@ -210,11 +230,14 @@ void SetMinMaxSize (edict_t *e, float *min, float *max, qboolean rotate) float a; vec3_t base, transformed; int i, j, k, l; + */ + int i; for (i=0 ; i<3 ; i++) if (min[i] > max[i]) PR_RunError ("backwards mins/maxs"); + /* rotate = false; // FIXME: implement rotation properly again if (!rotate) @@ -271,7 +294,13 @@ void SetMinMaxSize (edict_t *e, float *min, float *max, qboolean rotate) VectorCopy (rmin, e->v.mins); VectorCopy (rmax, e->v.maxs); VectorSubtract (max, min, e->v.size); + */ +// set derived values + VectorCopy (min, e->v.mins); + VectorCopy (max, e->v.maxs); + VectorSubtract (max, min, e->v.size); + SV_LinkEdict (e, false); } @@ -280,6 +309,7 @@ void SetMinMaxSize (edict_t *e, float *min, float *max, qboolean rotate) PF_setsize the size box is rotated by the current angle +LordHavoc: no it isn't... setsize (entity, minvector, maxvector) ================= @@ -528,11 +558,19 @@ void PF_vectoangles (void) } else { - yaw = (int) (atan2(value1[1], value1[0]) * 180 / M_PI); - if (yaw < 0) - yaw += 360; + // LordHavoc: optimized a bit + if (value1[0]) + { + yaw = (atan2(value1[1], value1[0]) * 180 / M_PI); + if (yaw < 0) + yaw += 360; + } + else if (value1[1] > 0) + yaw = 90; + else + yaw = 270; - forward = sqrt (value1[0]*value1[0] + value1[1]*value1[1]); + forward = sqrt(value1[0]*value1[0] + value1[1]*value1[1]); pitch = (int) (atan2(value1[2], forward) * 180 / M_PI); if (pitch < 0) pitch += 360; @@ -633,7 +671,7 @@ Each entity can have eight independant sound sources, like voice, weapon, feet, etc. Channel 0 is an auto-allocate channel, the others override anything -allready running on that entity/channel pair. +already running on that entity/channel pair. An attenuation of 0 will play full volume everywhere in the level. Larger attenuations will drop off. @@ -675,9 +713,9 @@ break() */ void PF_break (void) { -Con_Printf ("break statement\n"); -*(int *)-4 = 0; // dump to debugger -// PR_RunError ("break statement"); +// Con_Printf ("break statement\n"); +// *(int *)-4 = 0; // dump to debugger + PR_RunError ("break statement"); } /* @@ -864,7 +902,7 @@ PF_checkclient Returns a client (or object that has a client enemy) that would be a valid target. -If there are more than one valid options, they are cycled each frame +If there is more than one valid option, they are cycled each frame If (self.origin + self.viewofs) is not in the PVS of the current target, it is not returned at all. @@ -872,7 +910,6 @@ it is not returned at all. name checkclient () ================= */ -#define MAX_CHECK 16 int c_invis, c_notvis; void PF_checkclient (void) { @@ -1108,8 +1145,11 @@ void PF_Find (void) e = G_EDICTNUM(OFS_PARM0); f = G_INT(OFS_PARM1); s = G_STRING(OFS_PARM2); - if (!s) - PR_RunError ("PF_Find: bad search string"); + if (!s || !s[0]) + { + RETURN_EDICT(sv.edicts); + return; + } for (e++ ; e < sv.num_edicts ; e++) { @@ -1156,6 +1196,72 @@ void PF_FindFloat (void) RETURN_EDICT(sv.edicts); } +// chained search for strings in entity fields +// entity(.string field, string match) findchain = #402; +void PF_findchain (void) +{ + int i; + int f; + char *s, *t; + edict_t *ent, *chain; + + chain = (edict_t *)sv.edicts; + + f = G_INT(OFS_PARM0); + s = G_STRING(OFS_PARM1); + if (!s || !s[0]) + { + RETURN_EDICT(sv.edicts); + return; + } + + ent = NEXT_EDICT(sv.edicts); + for (i = 1;i < sv.num_edicts;i++, ent = NEXT_EDICT(ent)) + { + if (ent->free) + continue; + t = E_STRING(ent,f); + if (!t) + continue; + if (strcmp(t,s)) + continue; + + ent->v.chain = EDICT_TO_PROG(chain); + chain = ent; + } + + RETURN_EDICT(chain); +} + +// LordHavoc: chained search for float, int, and entity reference fields +// entity(.string field, float match) findchainfloat = #403; +void PF_findchainfloat (void) +{ + int i; + int f; + float s; + edict_t *ent, *chain; + + chain = (edict_t *)sv.edicts; + + f = G_INT(OFS_PARM0); + s = G_FLOAT(OFS_PARM1); + + ent = NEXT_EDICT(sv.edicts); + for (i = 1;i < sv.num_edicts;i++, ent = NEXT_EDICT(ent)) + { + if (ent->free) + continue; + if (E_FLOAT(ent,f) != s) + continue; + + ent->v.chain = EDICT_TO_PROG(chain); + chain = ent; + } + + RETURN_EDICT(chain); +} + void PR_CheckEmptyString (char *s) { if (s[0] <= ' ') @@ -1192,7 +1298,7 @@ void PF_precache_sound (void) PR_RunError ("PF_precache_sound: overflow"); } -int blahblah = 0; +extern qboolean hlbsp; void PF_precache_model (void) { char *s; @@ -1202,6 +1308,8 @@ void PF_precache_model (void) PR_RunError ("PF_Precache_*: Precache can only be done in spawn functions"); s = G_STRING(OFS_PARM0); + if (hlbsp && ((!s) || (!s[0]))) + return; G_INT(OFS_RETURN) = G_INT(OFS_PARM0); PR_CheckEmptyString (s); @@ -1210,11 +1318,7 @@ void PF_precache_model (void) if (!sv.model_precache[i]) { sv.model_precache[i] = s; - if (sv.active < 0) - blahblah++; sv.models[i] = Mod_ForName (s, true); - if (sv.active < 0) - blahblah++; return; } if (!strcmp(sv.model_precache[i], s)) @@ -1699,9 +1803,17 @@ void PF_makestatic (void) ent = G_EDICT(OFS_PARM0); - MSG_WriteByte (&sv.signon,svc_spawnstatic); - - MSG_WriteByte (&sv.signon, SV_ModelIndex(pr_strings + ent->v.model)); + i = SV_ModelIndex(pr_strings + ent->v.model); + if (i >= 256) + { + MSG_WriteByte (&sv.signon,svc_spawnstatic2); + MSG_WriteShort (&sv.signon, i); + } + else + { + MSG_WriteByte (&sv.signon,svc_spawnstatic); + MSG_WriteByte (&sv.signon, i); + } MSG_WriteByte (&sv.signon, ent->v.frame); MSG_WriteByte (&sv.signon, ent->v.colormap); @@ -1829,7 +1941,7 @@ void PF_registercvar (void) name = G_STRING(OFS_PARM1); value = G_STRING(OFS_PARM2); G_FLOAT(OFS_RETURN) = 0; -// first check to see if it has allready been defined +// first check to see if it has already been defined if (Cvar_FindVar (name)) return; @@ -1988,6 +2100,405 @@ void PF_setcolor (void) MSG_WriteByte (&sv.reliable_datagram, i); } +/* +================= +PF_effect + +effect(origin, modelname, startframe, framecount, framerate) +================= +*/ +void PF_effect (void) +{ + char *s; + s = G_STRING(OFS_PARM1); + if (!s || !s[0]) + PR_RunError("effect: no model specified\n"); + + SV_StartEffect(G_VECTOR(OFS_PARM0), SV_ModelIndex(s), G_FLOAT(OFS_PARM2), G_FLOAT(OFS_PARM3), G_FLOAT(OFS_PARM4)); +} + +void PF_te_blood (void) +{ + if (G_FLOAT(OFS_PARM2) < 1) + return; + MSG_WriteByte(&sv.datagram, svc_temp_entity); + MSG_WriteByte(&sv.datagram, TE_BLOOD); + // origin + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]); + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]); + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]); + // velocity + MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[0], 127)); + MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[1], 127)); + MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[2], 127)); + // count + MSG_WriteByte(&sv.datagram, bound(0, (int) G_FLOAT(OFS_PARM2), 255)); +} + +void PF_te_bloodshower (void) +{ + if (G_FLOAT(OFS_PARM3) < 1) + return; + MSG_WriteByte(&sv.datagram, svc_temp_entity); + MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER); + // min + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]); + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]); + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]); + // max + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]); + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]); + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]); + // speed + MSG_WriteFloatCoord(&sv.datagram, G_FLOAT(OFS_PARM2)); + // count + MSG_WriteShort(&sv.datagram, bound(0, G_FLOAT(OFS_PARM3), 65535)); +} + +void PF_te_explosionrgb (void) +{ + MSG_WriteByte(&sv.datagram, svc_temp_entity); + MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB); + // origin + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]); + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]); + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]); + // color + MSG_WriteByte(&sv.datagram, bound(0, (int) (G_VECTOR(OFS_PARM1)[0] * 255), 255)); + MSG_WriteByte(&sv.datagram, bound(0, (int) (G_VECTOR(OFS_PARM1)[1] * 255), 255)); + MSG_WriteByte(&sv.datagram, bound(0, (int) (G_VECTOR(OFS_PARM1)[2] * 255), 255)); +} + +void PF_te_particlecube (void) +{ + if (G_FLOAT(OFS_PARM3) < 1) + return; + MSG_WriteByte(&sv.datagram, svc_temp_entity); + MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE); + // min + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]); + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]); + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]); + // max + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]); + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]); + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]); + // velocity + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]); + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]); + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]); + // count + MSG_WriteShort(&sv.datagram, bound(0, G_FLOAT(OFS_PARM3), 65535)); + // color + MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM4)); + // gravity true/false + MSG_WriteByte(&sv.datagram, ((int) G_FLOAT(OFS_PARM5)) != 0); + // randomvel + MSG_WriteFloatCoord(&sv.datagram, G_FLOAT(OFS_PARM6)); +} + +void PF_te_particlerain (void) +{ + if (G_FLOAT(OFS_PARM3) < 1) + return; + MSG_WriteByte(&sv.datagram, svc_temp_entity); + MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN); + // min + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]); + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]); + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]); + // max + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]); + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]); + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]); + // velocity + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]); + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]); + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]); + // count + MSG_WriteShort(&sv.datagram, bound(0, G_FLOAT(OFS_PARM3), 65535)); + // color + MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM4)); +} + +void PF_te_particlesnow (void) +{ + if (G_FLOAT(OFS_PARM3) < 1) + return; + MSG_WriteByte(&sv.datagram, svc_temp_entity); + MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW); + // min + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]); + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]); + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]); + // max + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]); + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]); + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]); + // velocity + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]); + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]); + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]); + // count + MSG_WriteShort(&sv.datagram, bound(0, G_FLOAT(OFS_PARM3), 65535)); + // color + MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM4)); +} + +void PF_te_spark (void) +{ + if (G_FLOAT(OFS_PARM2) < 1) + return; + MSG_WriteByte(&sv.datagram, svc_temp_entity); + MSG_WriteByte(&sv.datagram, TE_SPARK); + // origin + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]); + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]); + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]); + // velocity + MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[0], 127)); + MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[1], 127)); + MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[2], 127)); + // count + MSG_WriteByte(&sv.datagram, bound(0, (int) G_FLOAT(OFS_PARM2), 255)); +} + +void PF_te_gunshotquad (void) +{ + MSG_WriteByte(&sv.datagram, svc_temp_entity); + MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD); + // origin + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]); + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]); + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]); +} + +void PF_te_spikequad (void) +{ + MSG_WriteByte(&sv.datagram, svc_temp_entity); + MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD); + // origin + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]); + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]); + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]); +} + +void PF_te_superspikequad (void) +{ + MSG_WriteByte(&sv.datagram, svc_temp_entity); + MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD); + // origin + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]); + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]); + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]); +} + +void PF_te_explosionquad (void) +{ + MSG_WriteByte(&sv.datagram, svc_temp_entity); + MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD); + // origin + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]); + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]); + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]); +} + +void PF_te_smallflash (void) +{ + MSG_WriteByte(&sv.datagram, svc_temp_entity); + MSG_WriteByte(&sv.datagram, TE_SMALLFLASH); + // origin + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]); + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]); + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]); +} + +void PF_te_customflash (void) +{ + if (G_FLOAT(OFS_PARM1) < 8 || G_FLOAT(OFS_PARM2) < (1.0 / 256.0)) + return; + MSG_WriteByte(&sv.datagram, svc_temp_entity); + MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH); + // origin + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]); + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]); + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]); + // radius + MSG_WriteByte(&sv.datagram, bound(0, G_FLOAT(OFS_PARM1) / 8 - 1, 255)); + // lifetime + MSG_WriteByte(&sv.datagram, bound(0, G_FLOAT(OFS_PARM2) / 256 - 1, 255)); + // color + MSG_WriteByte(&sv.datagram, bound(0, G_VECTOR(OFS_PARM3)[0] * 255, 255)); + MSG_WriteByte(&sv.datagram, bound(0, G_VECTOR(OFS_PARM3)[1] * 255, 255)); + MSG_WriteByte(&sv.datagram, bound(0, G_VECTOR(OFS_PARM3)[2] * 255, 255)); +} + +void PF_te_gunshot (void) +{ + MSG_WriteByte(&sv.datagram, svc_temp_entity); + MSG_WriteByte(&sv.datagram, TE_GUNSHOT); + // origin + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]); + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]); + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]); +} + +void PF_te_spike (void) +{ + MSG_WriteByte(&sv.datagram, svc_temp_entity); + MSG_WriteByte(&sv.datagram, TE_SPIKE); + // origin + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]); + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]); + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]); +} + +void PF_te_superspike (void) +{ + MSG_WriteByte(&sv.datagram, svc_temp_entity); + MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE); + // origin + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]); + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]); + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]); +} + +void PF_te_explosion (void) +{ + MSG_WriteByte(&sv.datagram, svc_temp_entity); + MSG_WriteByte(&sv.datagram, TE_EXPLOSION); + // origin + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]); + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]); + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]); +} + +void PF_te_tarexplosion (void) +{ + MSG_WriteByte(&sv.datagram, svc_temp_entity); + MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION); + // origin + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]); + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]); + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]); +} + +void PF_te_wizspike (void) +{ + MSG_WriteByte(&sv.datagram, svc_temp_entity); + MSG_WriteByte(&sv.datagram, TE_WIZSPIKE); + // origin + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]); + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]); + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]); +} + +void PF_te_knightspike (void) +{ + MSG_WriteByte(&sv.datagram, svc_temp_entity); + MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE); + // origin + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]); + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]); + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]); +} + +void PF_te_lavasplash (void) +{ + MSG_WriteByte(&sv.datagram, svc_temp_entity); + MSG_WriteByte(&sv.datagram, TE_LAVASPLASH); + // origin + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]); + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]); + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]); +} + +void PF_te_teleport (void) +{ + MSG_WriteByte(&sv.datagram, svc_temp_entity); + MSG_WriteByte(&sv.datagram, TE_TELEPORT); + // origin + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]); + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]); + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]); +} + +void PF_te_explosion2 (void) +{ + MSG_WriteByte(&sv.datagram, svc_temp_entity); + MSG_WriteByte(&sv.datagram, TE_EXPLOSION2); + // origin + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]); + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]); + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]); + // color + MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM1)); +} + +void PF_te_lightning1 (void) +{ + MSG_WriteByte(&sv.datagram, svc_temp_entity); + MSG_WriteByte(&sv.datagram, TE_LIGHTNING1); + // owner entity + MSG_WriteShort(&sv.datagram, G_EDICTNUM(OFS_PARM0)); + // start + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]); + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]); + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]); + // end + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]); + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]); + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]); +} + +void PF_te_lightning2 (void) +{ + MSG_WriteByte(&sv.datagram, svc_temp_entity); + MSG_WriteByte(&sv.datagram, TE_LIGHTNING2); + // owner entity + MSG_WriteShort(&sv.datagram, G_EDICTNUM(OFS_PARM0)); + // start + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]); + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]); + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]); + // end + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]); + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]); + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]); +} + +void PF_te_lightning3 (void) +{ + MSG_WriteByte(&sv.datagram, svc_temp_entity); + MSG_WriteByte(&sv.datagram, TE_LIGHTNING3); + // owner entity + MSG_WriteShort(&sv.datagram, G_EDICTNUM(OFS_PARM0)); + // start + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]); + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]); + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]); + // end + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]); + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]); + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]); +} + +void PF_te_beam (void) +{ + MSG_WriteByte(&sv.datagram, svc_temp_entity); + MSG_WriteByte(&sv.datagram, TE_BEAM); + // owner entity + MSG_WriteShort(&sv.datagram, G_EDICTNUM(OFS_PARM0)); + // start + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]); + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]); + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]); + // end + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]); + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]); + MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]); +} + void PF_Fixme (void) { PR_RunError ("unimplemented builtin"); // LordHavoc: was misspelled (bulitin) @@ -2085,37 +2596,67 @@ PF_precache_file, PF_setspawnparms, -PF_Fixme, // #79 LordHavoc: dunno who owns 79-89, so these are just padding -PF_Fixme, // #80 -PF_Fixme, // #81 -PF_Fixme, // #82 -PF_Fixme, // #83 -PF_Fixme, // #84 -PF_Fixme, // #85 -PF_Fixme, // #86 -PF_Fixme, // #87 -PF_Fixme, // #88 -PF_Fixme, // #89 - -PF_tracebox, // #90 LordHavoc builtin range (9x) -PF_randomvec, // #91 -PF_GetLight, // #92 -PF_registercvar, // #93 -PF_min, // #94 -PF_max, // #95 -PF_bound, // #96 -PF_pow, // #97 -PF_FindFloat, // #98 -PF_checkextension, // #99 +PF_Fixme, // #79 LordHavoc: dunno who owns 79-89, so these are just padding +PF_Fixme, // #80 +PF_Fixme, // #81 +PF_Fixme, // #82 +PF_Fixme, // #83 +PF_Fixme, // #84 +PF_Fixme, // #85 +PF_Fixme, // #86 +PF_Fixme, // #87 +PF_Fixme, // #88 +PF_Fixme, // #89 + +PF_tracebox, // #90 LordHavoc builtin range (9x) +PF_randomvec, // #91 +PF_GetLight, // #92 +PF_registercvar, // #93 +PF_min, // #94 +PF_max, // #95 +PF_bound, // #96 +PF_pow, // #97 +PF_FindFloat, // #98 +PF_checkextension, // #99 #define a PF_Fixme, PF_Fixme, PF_Fixme, PF_Fixme, PF_Fixme, PF_Fixme, PF_Fixme, PF_Fixme, PF_Fixme, PF_Fixme, #define aa a a a a a a a a a a aa // #200 aa // #300 aa // #400 -PF_copyentity, // #400 LordHavoc: builtin range (4xx) -PF_setcolor, // #401 +PF_copyentity, // #400 LordHavoc: builtin range (4xx) +PF_setcolor, // #401 +PF_findchain, // #402 +PF_findchainfloat, // #403 +PF_effect, // #404 +PF_te_blood, // #405 +PF_te_bloodshower, // #406 +PF_te_explosionrgb, // #407 +PF_te_particlecube, // #408 +PF_te_particlerain, // #409 +PF_te_particlesnow, // #410 +PF_te_spark, // #411 +PF_te_gunshotquad, // #412 +PF_te_spikequad, // #413 +PF_te_superspikequad, // #414 +PF_te_explosionquad, // #415 +PF_te_smallflash, // #416 +PF_te_customflash, // #417 +PF_te_gunshot, // #418 +PF_te_spike, // #419 +PF_te_superspike, // #420 +PF_te_explosion, // #421 +PF_te_tarexplosion, // #422 +PF_te_wizspike, // #423 +PF_te_knightspike, // #424 +PF_te_lavasplash, // #425 +PF_te_teleport, // #426 +PF_te_explosion2, // #427 +PF_te_lightning1, // #428 +PF_te_lightning2, // #429 +PF_te_lightning3, // #430 +PF_te_beam, // #431 +PF_vectorvectors, // #432 }; builtin_t *pr_builtins = pr_builtin; int pr_numbuiltins = sizeof(pr_builtin)/sizeof(pr_builtin[0]); - diff --git a/pr_edict.c b/pr_edict.c index 0488c176..1ef5b19a 100644 --- a/pr_edict.c +++ b/pr_edict.c @@ -39,6 +39,7 @@ int type_size[8] = {1,sizeof(string_t)/4,1,3,1,1,sizeof(func_t)/4,sizeof(void * ddef_t *ED_FieldAtOfs (int ofs); qboolean ED_ParseEpair (void *base, ddef_t *key, char *s); +cvar_t pr_checkextension = {"pr_checkextension", "1"}; cvar_t nomonsters = {"nomonsters", "0"}; cvar_t gamecfg = {"gamecfg", "0"}; cvar_t scratch1 = {"scratch1", "0"}; @@ -111,6 +112,7 @@ int eval_colormod; int eval_ping; int eval_movement; int eval_pmodel; +int eval_punchvector; dfunction_t *SV_PlayerPhysicsQC; dfunction_t *EndFrameQC; @@ -158,6 +160,7 @@ void FindEdictFieldOffsets() eval_ping = FindFieldOffset("ping"); eval_movement = FindFieldOffset("movement"); eval_pmodel = FindFieldOffset("pmodel"); + eval_punchvector = FindFieldOffset("punchvector"); // LordHavoc: allowing QuakeC to override the player movement code SV_PlayerPhysicsQC = ED_FindFunction ("SV_PlayerPhysics"); @@ -1288,6 +1291,7 @@ void PR_Init (void) Cmd_AddCommand ("edicts", ED_PrintEdicts); Cmd_AddCommand ("edictcount", ED_Count); Cmd_AddCommand ("profile", PR_Profile_f); + Cvar_RegisterVariable (&pr_checkextension); Cvar_RegisterVariable (&nomonsters); Cvar_RegisterVariable (&gamecfg); Cvar_RegisterVariable (&scratch1); diff --git a/progs.h b/progs.h index 278447b2..4d4ce0ad 100644 --- a/progs.h +++ b/progs.h @@ -89,6 +89,7 @@ extern int eval_colormod; extern int eval_ping; extern int eval_movement; extern int eval_pmodel; +extern int eval_punchvector; #define GETEDICTFIELDVALUE(ed, fieldoffset) (fieldoffset ? (eval_t*)((char*)&ed->v + fieldoffset) : NULL) diff --git a/protocol.h b/protocol.h index 6de7bcb7..edad508f 100644 --- a/protocol.h +++ b/protocol.h @@ -44,6 +44,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // effects/model (can be used as model flags or entity effects) #define EF_REFLECTIVE 256 // LordHavoc: shiny metal objects :) #define EF_FULLBRIGHT 512 // LordHavoc: fullbright +#define EF_FLAME 1024 // LordHavoc: on fire // if the high bit of the servercmd is set, the low bits are fast update flags: #define U_MOREBITS (1<<0) @@ -81,7 +82,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define U_GLOWTRAIL (1<<24) // leaves a trail of particles (of color .glowcolor, or black if it is a negative glowsize) #define U_VIEWMODEL (1<<25) // attachs the model to the view (origin and angles become relative to it), only shown to owner, a more powerful alternative to .weaponmodel and such #define U_FRAME2 (1<<26) // 1 byte, this is .frame & 0xFF00 (second byte) -#define U_UNUSED27 (1<<27) // future expansion +#define U_MODEL2 (1<<27) // 1 byte, this is .modelindex & 0xFF00 (second byte) #define U_UNUSED28 (1<<28) // future expansion #define U_UNUSED29 (1<<29) // future expansion #define U_UNUSED30 (1<<30) // future expansion @@ -102,6 +103,25 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define SU_WEAPONFRAME (1<<12) #define SU_ARMOR (1<<13) #define SU_WEAPON (1<<14) +#define SU_EXTEND1 (1<<15) +// first extend byte +#define SU_PUNCHVEC1 (1<<16) +#define SU_PUNCHVEC2 (1<<17) +#define SU_PUNCHVEC3 (1<<18) +#define SU_UNUSED19 (1<<19) +#define SU_UNUSED20 (1<<20) +#define SU_UNUSED21 (1<<21) +#define SU_UNUSED22 (1<<22) +#define SU_EXTEND2 (1<<23) // another byte to follow, future expansion +// second extend byte +#define SU_UNUSED24 (1<<24) +#define SU_UNUSED25 (1<<25) +#define SU_UNUSED26 (1<<26) +#define SU_UNUSED27 (1<<27) +#define SU_UNUSED28 (1<<28) +#define SU_UNUSED29 (1<<29) +#define SU_UNUSED30 (1<<30) +#define SU_EXTEND3 (1<<31) // another byte to follow, future expansion // a sound with no channel is a local only sound #define SND_VOLUME (1<<0) // a byte @@ -176,13 +196,16 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define svc_cutscene 34 -#define svc_showlmp 35 // [string] slotname [string] lmpfilename [coord] x [coord] y +#define svc_showlmp 35 // [string] slotname [string] lmpfilename [short] x [short] y #define svc_hidelmp 36 // [string] slotname -#define svc_skybox 37 // [string] skyname -#define svc_farclip 50 // [coord] size (default is 6144) -#define svc_fog 51 // [byte] enable [short] density*4096 [byte] red [byte] green [byte] blue -//#define svc_playerposition 52 // only used in dpprotocol mode +#define svc_unused1 +#define svc_fog 51 // unfinished +#define svc_effect 52 // [vector] org [byte] modelindex [byte] startframe [byte] framecount [byte] framerate +#define svc_effect2 53 // [vector] org [short] modelindex [byte] startframe [byte] framecount [byte] framerate +#define svc_sound2 54 // short soundindex instead of byte +#define svc_spawnbaseline2 55 // short modelindex instead of byte +#define svc_spawnstatic2 56 // short modelindex instead of byte // // client to server @@ -232,4 +255,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define TE_SUPERSPIKEQUAD 59 // [vector] origin // LordHavoc: block2 - 70-80 #define TE_EXPLOSIONQUAD 70 // [vector] origin -#define TE_BLOOD2 71 // [vector] origin \ No newline at end of file +#define TE_BLOOD2 71 // [vector] origin +#define TE_SMALLFLASH 72 // [vector] origin +#define TE_CUSTOMFLASH 73 // [vector] origin [byte] radius / 8 - 1 [byte] lifetime / 256 - 1 [byte] red [byte] green [byte] blue +#define TE_FLAMEJET 74 // [vector] origin [vector] velocity [byte] count diff --git a/quakedef.h b/quakedef.h index 3aee5075..0232c8f3 100644 --- a/quakedef.h +++ b/quakedef.h @@ -64,8 +64,8 @@ extern int buildnumber; #define ROLL 2 -#define MAX_QPATH 64 // max length of a quake game pathname -#define MAX_OSPATH 128 // max length of a filesystem pathname +#define MAX_QPATH 128 // max length of a quake game pathname +#define MAX_OSPATH 1024 // max length of a filesystem pathname #define ON_EPSILON 0.1 // point on plane side epsilon @@ -79,8 +79,9 @@ extern int buildnumber; // LordHavoc: increased entity limit to 2048 from 600 #define MAX_EDICTS 2048 // FIXME: ouch! ouch! ouch! #define MAX_LIGHTSTYLES 64 -#define MAX_MODELS 256 // these are sent over the net as bytes -#define MAX_SOUNDS 256 // so they cannot be blindly increased +// LordHavoc: increased model and sound limits from 256 and 256 to 1024 and 1024 (and added protocol extensions accordingly) +#define MAX_MODELS 1024 // these are sent over the net as bytes +#define MAX_SOUNDS 1024 // so they cannot be blindly increased #define SAVEGAME_COMMENT_LENGTH 39 @@ -204,6 +205,8 @@ typedef struct } entity_state_t; +#include "r_textures.h" + #include "wad.h" #include "draw.h" #include "cvar.h" @@ -271,8 +274,6 @@ extern int host_framecount; // incremented every frame, never reset extern double realtime; // not bounded in any way, changed at // start of every frame, never reset -extern double sv_frametime; - void Host_ClearMemory (void); void Host_ServerFrame (void); void Host_InitCommands (void); diff --git a/r_crosshairs.c b/r_crosshairs.c index 5416a693..c6a2b81c 100644 --- a/r_crosshairs.c +++ b/r_crosshairs.c @@ -7,7 +7,7 @@ cvar_t crosshair_flashrange = {"crosshair_flashrange", "0.1", true}; #define NUMCROSSHAIRS 5 -int crosshairtex[NUMCROSSHAIRS]; +rtexture_t *crosshairtex[NUMCROSSHAIRS]; byte *crosshairtexdata[NUMCROSSHAIRS] = { @@ -106,7 +106,7 @@ void crosshairload(int num, byte *in) data[i][0] = data[i][1] = data[i][2] = 255; data[i][3] = (in[i] - '0') * 255 / 7; } - crosshairtex[num] = GL_LoadTexture(va("crosshair%02d", num), 16, 16, &data[0][0], false, true, 4); + crosshairtex[num] = R_LoadTexture(va("crosshair%02d", num), 16, 16, &data[0][0], TEXF_ALPHA | TEXF_RGBA | TEXF_PRECACHE); } void r_crosshairs_start() diff --git a/r_explosion.c b/r_explosion.c index bff9f5cf..a69d4fe2 100644 --- a/r_explosion.c +++ b/r_explosion.c @@ -23,12 +23,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. float TraceLine (vec3_t start, vec3_t end, vec3_t impact, vec3_t normal); #define MAX_EXPLOSIONS 64 -#define EXPLOSIONBANDS 16 -#define EXPLOSIONSEGMENTS 16 -#define EXPLOSIONVERTS ((EXPLOSIONBANDS+1)*(EXPLOSIONSEGMENTS+1)) +#define EXPLOSIONGRID 16 +#define EXPLOSIONVERTS ((EXPLOSIONGRID+1)*(EXPLOSIONGRID+1)) #define EXPLOSIONTRIS (EXPLOSIONVERTS*2) #define EXPLOSIONSTARTRADIUS (0.0f) -#define EXPLOSIONSTARTVELOCITY (400.0f) +#define EXPLOSIONSTARTVELOCITY (500.0f) #define EXPLOSIONFADESTART (1.5f) #define EXPLOSIONFADERATE (6.0f) @@ -36,10 +35,12 @@ vec3_t explosionspherevert[EXPLOSIONVERTS]; vec3_t explosionspherevertvel[EXPLOSIONVERTS]; float explosiontexcoords[EXPLOSIONVERTS][2]; int explosiontris[EXPLOSIONTRIS][3]; +int explosionnoiseindex[EXPLOSIONVERTS]; vec3_t explosionpoint[EXPLOSIONVERTS]; typedef struct explosion_s { + float starttime; float alpha; vec3_t vert[EXPLOSIONVERTS]; vec3_t vertvel[EXPLOSIONVERTS]; @@ -48,8 +49,8 @@ explosion_t; explosion_t explosion[128]; -int explosiontexture; -int explosiontexturefog; +rtexture_t *explosiontexture; +rtexture_t *explosiontexturefog; cvar_t r_explosionclip = {"r_explosionclip", "0"}; @@ -57,15 +58,16 @@ int R_ExplosionVert(int column, int row) { int i; float a, b, c; - i = row * (EXPLOSIONSEGMENTS + 1) + column; - a = row * M_PI * 2 / EXPLOSIONBANDS; - b = column * M_PI * 2 / EXPLOSIONSEGMENTS; + i = row * (EXPLOSIONGRID + 1) + column; + a = row * M_PI * 2 / EXPLOSIONGRID; + b = column * M_PI * 2 / EXPLOSIONGRID; c = cos(b); explosionpoint[i][0] = cos(a) * c; explosionpoint[i][1] = sin(a) * c; explosionpoint[i][2] = -sin(b); - explosiontexcoords[i][0] = (float) column / (float) EXPLOSIONSEGMENTS; - explosiontexcoords[i][1] = (float) row / (float) EXPLOSIONBANDS; + explosionnoiseindex[i] = (row & (EXPLOSIONGRID - 1)) * EXPLOSIONGRID + (column & (EXPLOSIONGRID - 1)); + explosiontexcoords[i][0] = (float) column / (float) EXPLOSIONGRID; + explosiontexcoords[i][1] = (float) row / (float) EXPLOSIONGRID; return i; } @@ -73,8 +75,8 @@ void r_explosion_start() { int x, y; byte noise1[128][128], noise2[128][128], data[128][128][4]; - fractalnoise(&noise1[0][0], 128, 8); - fractalnoise(&noise2[0][0], 128, 8); + fractalnoise(&noise1[0][0], 128, 2); + fractalnoise(&noise2[0][0], 128, 2); for (y = 0;y < 128;y++) { for (x = 0;x < 128;x++) @@ -91,11 +93,11 @@ void r_explosion_start() data[y][x][3] = bound(0, a, 255); } } - explosiontexture = GL_LoadTexture ("explosiontexture", 128, 128, &data[0][0][0], true, true, 4); + explosiontexture = R_LoadTexture ("explosiontexture", 128, 128, &data[0][0][0], TEXF_MIPMAP | TEXF_ALPHA | TEXF_RGBA | TEXF_PRECACHE); for (y = 0;y < 128;y++) for (x = 0;x < 128;x++) data[y][x][0] = data[y][x][1] = data[y][x][2] = 255; - explosiontexturefog = GL_LoadTexture ("explosiontexturefog", 128, 128, &data[0][0][0], true, true, 4); + explosiontexturefog = R_LoadTexture ("explosiontexturefog", 128, 128, &data[0][0][0], TEXF_MIPMAP | TEXF_ALPHA | TEXF_RGBA | TEXF_PRECACHE); } void r_explosion_shutdown() @@ -106,9 +108,9 @@ void R_Explosion_Init() { int i, x, y; i = 0; - for (y = 0;y < EXPLOSIONBANDS;y++) + for (y = 0;y < EXPLOSIONGRID;y++) { - for (x = 0;x < EXPLOSIONSEGMENTS;x++) + for (x = 0;x < EXPLOSIONGRID;x++) { explosiontris[i][0] = R_ExplosionVert(x , y ); explosiontris[i][1] = R_ExplosionVert(x + 1, y ); @@ -138,6 +140,9 @@ void R_Explosion_Init() void R_NewExplosion(vec3_t org) { int i, j; + float dist; + byte noise[EXPLOSIONGRID*EXPLOSIONGRID]; + fractalnoise(noise, EXPLOSIONGRID, 2); for (i = 0;i < MAX_EXPLOSIONS;i++) { if (explosion[i].alpha <= 0.0f) @@ -145,12 +150,13 @@ void R_NewExplosion(vec3_t org) explosion[i].alpha = EXPLOSIONFADESTART; for (j = 0;j < EXPLOSIONVERTS;j++) { - explosion[i].vert[j][0] = explosionspherevert[j][0] + org[0]; - explosion[i].vert[j][1] = explosionspherevert[j][1] + org[1]; - explosion[i].vert[j][2] = explosionspherevert[j][2] + org[2]; - explosion[i].vertvel[j][0] = explosionspherevertvel[j][0]; - explosion[i].vertvel[j][1] = explosionspherevertvel[j][1]; - explosion[i].vertvel[j][2] = explosionspherevertvel[j][2]; + 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; } break; } @@ -159,40 +165,32 @@ void R_NewExplosion(vec3_t org) void R_DrawExplosion(explosion_t *e) { - int i, index, *indexlist = &explosiontris[0][0], alpha = bound(0, e->alpha * 255.0f, 255); - float s = cl.time * 1, t = cl.time * 0.75; - s -= (int) s; - t -= (int) t; + int i, index, *indexlist = &explosiontris[0][0], alpha = bound(0, e->alpha * 128.0f, 128), texnum, fogtexnum; + float s, t; +// s = cl.time * 1; +// t = cl.time * 0.75; +// s -= (int) s; +// t -= (int) t; + s = 0; + t = 0; /* glColor4f(1,1,1,e->alpha); glDisable(GL_TEXTURE_2D); // glBindTexture(GL_TEXTURE_2D, explosiontexture); - if (gl_vertexarrays.value) - { - qglVertexPointer(3, GL_FLOAT, 0, (float *) &e->vert[0][0]); -// qglTexCoordPointer(2, GL_FLOAT, 0, (float *) &explosiontexcoords[0][0]); - glEnableClientState(GL_VERTEX_ARRAY); -// glEnableClientState(GL_TEXTURE_COORD_ARRAY); - qglDrawElements(GL_TRIANGLES, EXPLOSIONTRIS, GL_UNSIGNED_INT, indexlist); -// glDisableClientState(GL_TEXTURE_COORD_ARRAY); - glDisableClientState(GL_VERTEX_ARRAY); - } - else - { - glBegin(GL_TRIANGLES); - for (i = 0;i < EXPLOSIONTRIS * 3;i++) - { - index = *indexlist++; -// glTexCoord2fv(explosiontexcoords[index]); - glVertex3fv(e->vert[index]); - } - glEnd(); - } + glVertexPointer(3, GL_FLOAT, 0, (float *) &e->vert[0][0]); +// glTexCoordPointer(2, GL_FLOAT, 0, (float *) &explosiontexcoords[0][0]); + glEnableClientState(GL_VERTEX_ARRAY); +// glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glDrawElements(GL_TRIANGLES, EXPLOSIONTRIS, GL_UNSIGNED_INT, indexlist); +// glDisableClientState(GL_TEXTURE_COORD_ARRAY); + glDisableClientState(GL_VERTEX_ARRAY); glEnable(GL_TEXTURE_2D); */ + texnum = R_GetTexture(explosiontexture); + fogtexnum = R_GetTexture(explosiontexturefog); for (i = 0;i < EXPLOSIONTRIS;i++) { - transpolybegin(explosiontexture, 0, explosiontexturefog, TPOLYTYPE_ALPHA); + transpolybegin(texnum, 0, fogtexnum, TPOLYTYPE_ALPHA); index = *indexlist++;transpolyvert(e->vert[index][0], e->vert[index][1], e->vert[index][2], explosiontexcoords[index][0] + s, explosiontexcoords[index][1] + t, 255, 255, 255, alpha); index = *indexlist++;transpolyvert(e->vert[index][0], e->vert[index][1], e->vert[index][2], explosiontexcoords[index][0] + s, explosiontexcoords[index][1] + t, 255, 255, 255, alpha); index = *indexlist++;transpolyvert(e->vert[index][0], e->vert[index][1], e->vert[index][2], explosiontexcoords[index][0] + s, explosiontexcoords[index][1] + t, 255, 255, 255, alpha); @@ -244,6 +242,11 @@ void R_MoveExplosions() { if (explosion[i].alpha > 0.0f) { + if (explosion[i].starttime > cl.time) + { + explosion[i].alpha = 0; + continue; + } R_MoveExplosion(&explosion[i], frametime); } } diff --git a/r_lerpanim.c b/r_lerpanim.c new file mode 100644 index 00000000..7ac1c62e --- /dev/null +++ b/r_lerpanim.c @@ -0,0 +1,183 @@ + +#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) +{ + int sub1, sub2, numframes, f, i, data; + double sublerp, lerp, l; + animscene_t *scene, *scenes; + + 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; + + if ((frame1 >= numframes)) + { + Con_Printf ("R_LerpAnimation: no such frame %d\n", frame1); + frame1 = 0; + } + + if ((frame2 >= numframes)) + { + Con_Printf ("R_LerpAnimation: no such frame %d\n", frame2); + frame2 = 0; + } + + if (frame1 < 0) + Host_Error ("R_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; + + 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) + { + scene = scenes + frame1; + lerp = 1 - 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; + } + 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 = sub2; + l = sublerp * lerp; + } + else + { + f = scene->firstframe; + l = 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; + } + } + } + } + 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; + } + 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 = sub2; + l = sublerp * lerp; + } + else + { + f = scene->firstframe; + l = 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; + } + } + } + } +} diff --git a/r_lerpanim.h b/r_lerpanim.h new file mode 100644 index 00000000..83eec6f7 --- /dev/null +++ b/r_lerpanim.h @@ -0,0 +1,9 @@ + +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); diff --git a/r_light.c b/r_light.c index b71ce66a..39cde86d 100644 --- a/r_light.c +++ b/r_light.c @@ -22,7 +22,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "quakedef.h" cvar_t r_lightmodels = {"r_lightmodels", "1"}; -cvar_t r_modelsdonttransformnormals = {"r_modelsdonttransformnormals", "0"}; + +extern cvar_t gl_transform; void r_light_start() { @@ -35,7 +36,6 @@ void r_light_shutdown() void R_Light_Init() { Cvar_RegisterVariable(&r_lightmodels); - Cvar_RegisterVariable(&r_modelsdonttransformnormals); R_RegisterModule("R_Light", r_light_start, r_light_shutdown); } @@ -91,7 +91,7 @@ void R_OldMarkLights (vec3_t lightorigin, dlight_t *light, int bit, int bitindex return; // for comparisons to minimum acceptable light - maxdist = light->radius * light->radius * LIGHTSCALE; + maxdist = light->radius * light->radius; // clamp radius to avoid exceeding 32768 entry division table if (maxdist > 4194304) @@ -139,7 +139,7 @@ loc0: if (surf->flags & SURF_PLANEBACK) dist = -dist; - if (dist < -0.25f) + if (dist < -0.25f && !(surf->flags & SURF_LIGHTBOTHSIDES)) continue; dist2 = dist * dist; @@ -256,7 +256,9 @@ void R_VisMarkLights (vec3_t lightorigin, dlight_t *light, int bit, int bitindex int row = (model->numleafs+7)>>3; float low[3], high[3], radius, dist, maxdist; - radius = light->radius * LIGHTSCALE1; + lightframe++; + + radius = light->radius * 2; // clamp radius to avoid exceeding 32768 entry division table if (radius > 2048) @@ -268,7 +270,6 @@ void R_VisMarkLights (vec3_t lightorigin, dlight_t *light, int bit, int bitindex // for comparisons to minimum acceptable light maxdist = radius*radius; - lightframe++; k = 0; while (k < row) { @@ -312,7 +313,7 @@ void R_VisMarkLights (vec3_t lightorigin, dlight_t *light, int bit, int bitindex if (surf->flags & SURF_PLANEBACK) dist = -dist; // LordHavoc: make sure it is infront of the surface and not too far away - if (dist >= -0.25f && dist < radius) + if ((dist >= -0.25f || (surf->flags & SURF_LIGHTBOTHSIDES)) && dist < radius) { int d; float dist2, impact[3]; @@ -666,19 +667,6 @@ loc0: } } -void R_LightPoint (vec3_t color, vec3_t p) -{ - if (r_fullbright.value || !cl.worldmodel->lightdata) - { - color[0] = color[1] = color[2] = 255; - 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); -} - -// LordHavoc: R_DynamicLightPoint - acumulates the dynamic lighting void R_DynamicLightPoint(vec3_t color, vec3_t org, int *dlightbits) { int i, j, k; @@ -694,15 +682,17 @@ void R_DynamicLightPoint(vec3_t color, vec3_t org, int *dlightbits) { for (i=0 ; i<32 ; i++) { - if ((!((1 << (i&31)) & dlightbits[i>>5])) || cl_dlights[i].die < cl.time || !cl_dlights[i].radius) + if (!((1 << i) & dlightbits[j])) continue; k = (j<<5)+i; + if (cl_dlights[k].die < cl.time || !cl_dlights[k].radius) + continue; VectorSubtract (org, cl_dlights[k].origin, dist); f = DotProduct(dist, dist) + LIGHTOFFSET; - r = cl_dlights[k].radius*cl_dlights[k].radius*LIGHTSCALE; + r = cl_dlights[k].radius*cl_dlights[k].radius; if (f < r) { - brightness = r * (256.0f / LIGHTSCALE2) / f; + brightness = r * 128.0f / f; color[0] += brightness * cl_dlights[k].color[0]; color[1] += brightness * cl_dlights[k].color[1]; color[2] += brightness * cl_dlights[k].color[2]; @@ -712,7 +702,65 @@ void R_DynamicLightPoint(vec3_t color, vec3_t org, int *dlightbits) } } -// same as above but no bitmask to check +void R_CompleteLightPoint (vec3_t color, vec3_t p) +{ + mleaf_t *leaf; + leaf = Mod_PointInLeaf(p, cl.worldmodel); + if (leaf->contents == CONTENTS_SOLID) + { + color[0] = color[1] = color[2] = 0; + return; + } + + if (r_fullbright.value || !cl.worldmodel->lightdata) + { + color[0] = color[1] = color[2] = 255; + 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); + + R_DynamicLightPoint(color, p, leaf->dlightbits); +} + +void R_ModelLightPoint (vec3_t color, vec3_t p, int *dlightbits) +{ + mleaf_t *leaf; + leaf = Mod_PointInLeaf(p, cl.worldmodel); + if (leaf->contents == CONTENTS_SOLID) + { + color[0] = color[1] = color[2] = 0; + dlightbits[0] = dlightbits[1] = dlightbits[2] = dlightbits[3] = dlightbits[4] = dlightbits[5] = dlightbits[6] = dlightbits[7] = 0; + return; + } + + if (r_fullbright.value || !cl.worldmodel->lightdata) + { + color[0] = color[1] = color[2] = 255; + 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); + + if (leaf->dlightframe == r_dlightframecount) + { + dlightbits[0] = leaf->dlightbits[0]; + dlightbits[1] = leaf->dlightbits[1]; + dlightbits[2] = leaf->dlightbits[2]; + dlightbits[3] = leaf->dlightbits[3]; + dlightbits[4] = leaf->dlightbits[4]; + dlightbits[5] = leaf->dlightbits[5]; + dlightbits[6] = leaf->dlightbits[6]; + dlightbits[7] = leaf->dlightbits[7]; + } + else + dlightbits[0] = dlightbits[1] = dlightbits[2] = dlightbits[3] = dlightbits[4] = dlightbits[5] = dlightbits[6] = dlightbits[7] = 0; +} + +/* // not currently used void R_DynamicLightPointNoMask(vec3_t color, vec3_t org) { int i; @@ -728,10 +776,10 @@ void R_DynamicLightPointNoMask(vec3_t color, vec3_t org) continue; VectorSubtract (org, cl_dlights[i].origin, dist); f = DotProduct(dist, dist) + LIGHTOFFSET; - r = cl_dlights[i].radius*cl_dlights[i].radius*LIGHTSCALE; + r = cl_dlights[i].radius*cl_dlights[i].radius; if (f < r) { - brightness = r * (256.0f / LIGHTSCALE2) / f; + brightness = r * 256.0f / f; if (cl_dlights[i].dark) brightness = -brightness; color[0] += brightness * cl_dlights[i].color[0]; @@ -740,19 +788,12 @@ void R_DynamicLightPointNoMask(vec3_t color, vec3_t org) } } } - -void R_CompleteLightPoint (vec3_t color, vec3_t p) -{ - R_LightPoint(color, p); - R_DynamicLightPointNoMask(color, p); -} +*/ extern float *aliasvert; -extern float *modelaliasvert; extern float *aliasvertnorm; extern byte *aliasvertcolor; extern float modelalpha; -extern int modeldlightbits[8]; void R_LightModel(int numverts, vec3_t center, vec3_t basecolor) { // LordHavoc: warning: reliance on int being 4 bytes here (of course the d_8to24table relies on that too...) @@ -765,31 +806,10 @@ void R_LightModel(int numverts, vec3_t center, vec3_t basecolor) vec3_t color; vec3_t origin; } nearlight[MAX_DLIGHTS]; + int modeldlightbits[8]; avc = aliasvertcolor; avn = aliasvertnorm; a = (byte) bound((int) 0, (int) (modelalpha * 255.0f), (int) 255); - if (currententity->effects & EF_FULLBRIGHT) - { - if (lighthalf) - { - ((byte *)&color)[0] = (byte) ((float) (128.0f * currententity->colormod[0])); - ((byte *)&color)[1] = (byte) ((float) (128.0f * currententity->colormod[1])); - ((byte *)&color)[2] = (byte) ((float) (128.0f * currententity->colormod[2])); - } - else - { - ((byte *)&color)[0] = (byte) ((float) (255.0f * currententity->colormod[0])); - ((byte *)&color)[1] = (byte) ((float) (255.0f * currententity->colormod[1])); - ((byte *)&color)[2] = (byte) ((float) (255.0f * currententity->colormod[2])); - } - ((byte *)&color)[3] = a; - for (i = 0;i < numverts;i++) - { - *((int *)avc) = color; - avc += 4; - } - return; - } if (lighthalf) { mod[0] = currententity->colormod[0] * 0.5f; @@ -802,37 +822,11 @@ void R_LightModel(int numverts, vec3_t center, vec3_t basecolor) mod[1] = currententity->colormod[1]; mod[2] = currententity->colormod[2]; } - basecolor[0] *= mod[0]; - basecolor[1] *= mod[1]; - basecolor[2] *= mod[2]; - if (!r_lightmodels.value) + if (currententity->effects & EF_FULLBRIGHT) { - for (i = 0;i < MAX_DLIGHTS;i++) - { - if (!modeldlightbits[i >> 5]) - { - i |= 31; - continue; - } - if (!(modeldlightbits[i >> 5] & (1 << (i & 31)))) - continue; - VectorSubtract (center, cl_dlights[i].origin, dist); - t1 = cl_dlights[i].radius*cl_dlights[i].radius*LIGHTSCALE; - t2 = DotProduct(dist,dist) * (1.0f / LIGHTSCALE) + LIGHTOFFSET; - if (t2 < t1) - { - dist[0] = cl_dlights[i].color[0] * t1 * mod[0]; - dist[1] = cl_dlights[i].color[1] * t1 * mod[1]; - dist[2] = cl_dlights[i].color[2] * t1 * mod[2]; - t1 = (224.0f / LIGHTSCALE / LIGHTSCALE) / t2; - basecolor[0] += dist[0] * t1; - basecolor[1] += dist[1] * t1; - basecolor[2] += dist[2] * t1; - } - } - ((byte *)&color)[0] = bound(0, basecolor[0], 255); - ((byte *)&color)[1] = bound(0, basecolor[1], 255); - ((byte *)&color)[2] = bound(0, basecolor[2], 255); + ((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++) { @@ -841,36 +835,43 @@ void R_LightModel(int numverts, vec3_t center, vec3_t basecolor) } return; } - else + R_ModelLightPoint(basecolor, center, modeldlightbits); + + basecolor[0] *= mod[0]; + basecolor[1] *= mod[1]; + basecolor[2] *= mod[2]; + for (i = 0;i < MAX_DLIGHTS;i++) { - for (i = 0;i < MAX_DLIGHTS;i++) + if (!modeldlightbits[i >> 5]) { - if (!modeldlightbits[i >> 5]) + i |= 31; + continue; + } + if (!(modeldlightbits[i >> 5] & (1 << (i & 31)))) + continue; + VectorSubtract (center, cl_dlights[i].origin, dist); + t2 = DotProduct(dist,dist) + LIGHTOFFSET; + 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 { - i |= 31; - continue; + VectorCopy(cl_dlights[i].origin, nearlight[nearlights].origin); } - if (!(modeldlightbits[i >> 5] & (1 << (i & 31)))) - continue; - VectorSubtract (center, cl_dlights[i].origin, dist); - t1 = cl_dlights[i].radius*cl_dlights[i].radius*LIGHTSCALE; - t2 = DotProduct(dist,dist) * (1.0f / LIGHTSCALE) + LIGHTOFFSET; - if (t2 < t1) - { - if (r_modelsdonttransformnormals.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]; -// t1 = (128.0f / LIGHTSCALE2) / t2; -// basecolor[0] += nearlight[nearlights].color[0] * t1; -// basecolor[1] += nearlight[nearlights].color[1] * t1; -// basecolor[2] += nearlight[nearlights].color[2] * t1; + 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) nearlights++; + else + { + 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; } } } @@ -886,10 +887,7 @@ void R_LightModel(int numverts, vec3_t center, vec3_t basecolor) int temp; vec3_t v; float *av; - if (r_modelsdonttransformnormals.value) - av = modelaliasvert; - else - av = aliasvert; + av = aliasvert; if (nearlights == 1) { for (i = 0;i < numverts;i++) @@ -898,10 +896,13 @@ void R_LightModel(int numverts, vec3_t center, vec3_t basecolor) t = DotProduct(avn,v); if (t > 0) { - t /= DotProduct(v,v); - temp = (int) ((float) (basecolor[0] + nearlight[0].color[0] * t));if (temp < 0) temp = 0;else if (temp > 255) temp = 255;avc[0] = temp; - temp = (int) ((float) (basecolor[1] + nearlight[0].color[1] * t));if (temp < 0) temp = 0;else if (temp > 255) temp = 255;avc[1] = temp; - temp = (int) ((float) (basecolor[2] + nearlight[0].color[2] * t));if (temp < 0) temp = 0;else if (temp > 255) temp = 255;avc[2] = temp; + 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; } else @@ -913,31 +914,35 @@ void R_LightModel(int numverts, vec3_t center, vec3_t basecolor) } else { - int i1, i2, i3, k; for (i = 0;i < numverts;i++) { + int lit; t1 = basecolor[0]; t2 = basecolor[1]; t3 = basecolor[2]; - k = false; + 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); + t /= (DotProduct(v,v) + LIGHTOFFSET); t1 += nearlight[j].color[0] * t; t2 += nearlight[j].color[1] * t; t3 += nearlight[j].color[2] * t; - k = true; + lit = true; } } - if (k) + if (lit) { - i1 = t1;if (i1 < 0) i1 = 0;else if (i1 > 255) i1 = 255;avc[0] = i1; - i2 = t2;if (i2 < 0) i2 = 0;else if (i2 > 255) i2 = 255;avc[1] = i2; - i3 = t3;if (i3 < 0) i3 = 0;else if (i3 > 255) i3 = 255;avc[2] = i3; + 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 diff --git a/r_light.h b/r_light.h index 509fe644..4d7bcb55 100644 --- a/r_light.h +++ b/r_light.h @@ -13,9 +13,9 @@ typedef struct } dlight_t; // LordHavoc: this affects the lighting scale of the whole game -//#define LIGHTOFFSET 16384.0f -//#define LIGHTSCALE1 2.0f #define LIGHTOFFSET 4096.0f -#define LIGHTSCALE1 1.0f -#define LIGHTSCALE (LIGHTSCALE1*LIGHTSCALE1) -#define LIGHTSCALE2 LIGHTSCALE + +extern void R_CompleteLightPoint (vec3_t color, vec3_t p); +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); diff --git a/r_part.c b/r_part.c index 59d875ee..fa183696 100644 --- a/r_part.c +++ b/r_part.c @@ -20,13 +20,13 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "quakedef.h" -#define MAX_PARTICLES 4096 // default max # of particles at one time +#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_blob, pt_blob2, pt_smoke, pt_snow, pt_rain, pt_bloodcloud, pt_fallfadespark, pt_bubble, pt_fade, pt_smokecloud, pt_splash, pt_flame, pt_flamingdebris, pt_smokingdebris, pt_flamefall + pt_static, pt_grav, pt_slowgrav, pt_blob, pt_blob2, pt_bulletsmoke, pt_smoke, pt_snow, pt_rain, pt_bloodcloud, pt_fallfadespark, pt_bubble, pt_fade, pt_smokecloud, pt_splash, pt_flame, pt_flamingdebris, pt_smokingdebris, pt_flamefall, pt_glow, pt_decal, pt_blood, pt_bloodsplatter } ptype_t; @@ -38,12 +38,17 @@ typedef struct particle_s float die; ptype_t type; float scale; - short texnum; - short dynlight; // if set the particle will be dynamically lit (if r_dynamicparticles is on), used for smoke and blood + 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 pad1; + byte pad2; float alpha; // 0-255 float time2; // used for various things (snow fluttering, for example) + 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 of bouncing particles) vec3_t oldorg; vec3_t vel2; // used for snow fluttering (base velocity, wind for instance) + vec3_t direction; // used by decals } particle_t; @@ -53,12 +58,10 @@ 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}; -int particletexture; -int smokeparticletexture[8]; -int rainparticletexture; -int bubbleparticletexture; -int explosiontexture; -int explosiontexturefog; +rtexture_t *particletexture; +rtexture_t *smokeparticletexture[8]; +rtexture_t *rainparticletexture; +rtexture_t *bubbleparticletexture; particle_t *particles; int r_numparticles; @@ -68,12 +71,6 @@ vec3_t r_pright, r_pup, r_ppn; int numparticles; particle_t **freeparticles; // list used only in compacting particles array -// LordHavoc: reduced duplicate code, and allow particle allocation system independence -#define ALLOCPARTICLE(part) \ - if (numparticles >= r_numparticles)\ - return;\ - (part) = &particles[numparticles++]; - cvar_t r_particles = {"r_particles", "1"}; cvar_t r_drawparticles = {"r_drawparticles", "1"}; cvar_t r_dynamicparticles = {"r_dynamicparticles", "1", true}; @@ -115,7 +112,7 @@ void R_InitParticleTexture (void) { int x,y,d,i,m; float dx, dy; - byte data[32][32][4], noise1[128][128], noise2[128][128]; + byte data[32][32][4], noise1[64][64], noise2[64][64]; vec3_t light; for (y = 0;y < 32;y++) @@ -130,14 +127,14 @@ void R_InitParticleTexture (void) data[y][x][3] = (byte) d; } } - particletexture = GL_LoadTexture ("particletexture", 32, 32, &data[0][0][0], true, true, 4); + particletexture = R_LoadTexture ("particletexture", 32, 32, &data[0][0][0], TEXF_MIPMAP | TEXF_ALPHA | TEXF_RGBA | TEXF_PRECACHE); for (i = 0;i < 8;i++) { do { - fractalnoise(&noise1[0][0], 128, 8); - fractalnoise(&noise2[0][0], 128, 16); + fractalnoise(&noise1[0][0], 64, 4); + fractalnoise(&noise2[0][0], 64, 8); m = 0; for (y = 0;y < 32;y++) { @@ -168,7 +165,7 @@ void R_InitParticleTexture (void) } while (m < 192); - smokeparticletexture[i] = GL_LoadTexture (va("smokeparticletexture%d", i), 32, 32, &data[0][0][0], true, true, 4); + smokeparticletexture[i] = R_LoadTexture (va("smokeparticletexture%d", i), 32, 32, &data[0][0][0], TEXF_MIPMAP | TEXF_ALPHA | TEXF_RGBA | TEXF_PRECACHE); } light[0] = 1;light[1] = 1;light[2] = 1; @@ -181,7 +178,7 @@ 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 = GL_LoadTexture ("rainparticletexture", 32, 32, &data[0][0][0], true, true, 4); + 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); @@ -193,7 +190,7 @@ void R_InitParticleTexture (void) data[y][x][3] = shadebubble((x - 16) * (1.0 / 16.0), (y - 16) * (1.0 / 16.0), light); } } - bubbleparticletexture = GL_LoadTexture ("bubbleparticletexture", 32, 32, &data[0][0][0], true, true, 4); + bubbleparticletexture = R_LoadTexture ("bubbleparticletexture", 32, 32, &data[0][0][0], TEXF_MIPMAP | TEXF_ALPHA | TEXF_RGBA | TEXF_PRECACHE); } void r_part_start() @@ -243,59 +240,104 @@ void R_Particles_Init (void) R_RegisterModule("R_Particles", r_part_start, r_part_shutdown); } -#define particle(ptype, pcolor, ptex, plight, pscale, palpha, ptime, px, py, pz, pvx, pvy, pvz)\ +//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)\ {\ particle_t *part;\ - ALLOCPARTICLE(part)\ + if (numparticles >= r_numparticles)\ + return;\ + part = &particles[numparticles++];\ part->type = (ptype);\ part->color = (pcolor);\ - part->texnum = (ptex);\ + 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, plight, pscale, palpha, ptime, pbase, poscale, pvscale)\ +#define particle2(ptype, pcolor, ptex, prendermode, plight, pscale, palpha, ptime, pbounce, pbase, poscale, pvscale)\ {\ particle_t *part;\ - ALLOCPARTICLE(part)\ + if (numparticles >= r_numparticles)\ + return;\ + part = &particles[numparticles++];\ part->type = (ptype);\ part->color = (pcolor);\ - part->texnum = (ptex);\ + 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, plight, pscale, palpha, ptime, pbase, pscalex, pscaley, pscalez, pvscalex, pvscaley, pvscalez)\ +#define particle3(ptype, pcolor, ptex, prendermode, plight, pscale, palpha, ptime, pbounce, pbase, pscalex, pscaley, pscalez, pvscalex, pvscaley, pvscalez)\ {\ particle_t *part;\ - ALLOCPARTICLE(part)\ + if (numparticles >= r_numparticles)\ + return;\ + part = &particles[numparticles++];\ part->type = (ptype);\ part->color = (pcolor);\ - part->texnum = (ptex);\ + 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);\ + 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 = (ptime2);\ + part->vel2[0] = (pvx2);\ + part->vel2[1] = (pvy2);\ + part->vel2[2] = (pvz2);\ } /* @@ -303,27 +345,19 @@ void R_Particles_Init (void) R_EntityParticles =============== */ - -#define NUMVERTEXNORMALS 162 -extern float r_avertexnormals[NUMVERTEXNORMALS][3]; -vec3_t avelocities[NUMVERTEXNORMALS]; -float beamlength = 16; -vec3_t avelocity = {23, 7, 3}; -float partstep = 0.01; -float timescale = 0.01; - void R_EntityParticles (entity_t *ent) { - int count; int i; float angle; float sp, sy, cp, cy; vec3_t forward; float dist; + float beamlength; + static vec3_t avelocities[NUMVERTEXNORMALS]; if (!r_particles.value) return; // LordHavoc: particles are optional dist = 64; - count = 50; + beamlength = 16; if (!avelocities[0][0]) for (i=0 ; iorigin[0] + r_avertexnormals[i][0]*dist + forward[0]*beamlength, ent->origin[1] + r_avertexnormals[i][1]*dist + forward[1]*beamlength, ent->origin[2] + r_avertexnormals[i][2]*dist + forward[2]*beamlength, 0, 0, 0); + particle(pt_static, 0x6f, particletexture, TPOLYTYPE_ALPHA, false, 2, 255, 0, 0, ent->origin[0] + m_bytenormals[i][0]*dist + forward[0]*beamlength, ent->origin[1] + m_bytenormals[i][1]*dist + forward[1]*beamlength, ent->origin[2] + m_bytenormals[i][2]*dist + forward[2]*beamlength, 0, 0, 0); } } @@ -397,7 +431,7 @@ void R_ReadPointFile_f (void) Con_Printf ("Not enough free particles\n"); break; } - particle(pt_static, (-c)&15, particletexture, false, 2, 255, 99999, org[0], org[1], org[2], 0, 0, 0); + particle(pt_static, (-c)&15, particletexture, TPOLYTYPE_ALPHA, false, 2, 255, 99999, 0, org[0], org[1], org[2], 0, 0, 0); } fclose (f); @@ -442,13 +476,13 @@ 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], true, 30, 255, 2, org[0], org[1], org[2], 0, 0, 0); +// particle(pt_smoke, (rand()&7) + 8, smokeparticletexture[rand()&7], TPOLYTYPE_ALPHA, true, 30, 255, 2, org[0], org[1], org[2], 0, 0, 0); i = Mod_PointInLeaf(org, cl.worldmodel)->contents; if (i == CONTENTS_SLIME || i == CONTENTS_WATER) { for (i=0 ; i<128 ; i++) - particle2(pt_bubble, (rand()&3) + 12, bubbleparticletexture, false, lhrandom(1, 2), 255, 2, org, 16, 96); + particle2(pt_bubble, (rand()&3) + 12, bubbleparticletexture, TPOLYTYPE_ADD, false, lhrandom(1, 2), 255, 2, 1.5, org, 16, 96); } else R_NewExplosion(org); @@ -459,15 +493,15 @@ void R_ParticleExplosion (vec3_t org, int smoke) // int color; float f, forg[3], fvel[3], fvel2[3]; // for (i = 0;i < 256;i++) -// particle(pt_fallfadespark, ramp3[rand()%6], particletexture, false, 1.5, lhrandom(128, 255), 5, lhrandom(-16, 16) + org[0], lhrandom(-16, 16) + org[1], lhrandom(-16, 16) + org[2], lhrandom(-192, 192), lhrandom(-192, 192), lhrandom(-192, 192) + 192); +// particle(pt_fallfadespark, ramp3[rand()%6], particletexture, TPOLYTYPE_ALPHA, false, 1.5, lhrandom(128, 255), 5, lhrandom(-16, 16) + org[0], lhrandom(-16, 16) + org[1], lhrandom(-16, 16) + org[2], lhrandom(-192, 192), lhrandom(-192, 192), lhrandom(-192, 192) + 192); // for (i = 0;i < 256;i++) -// particle2(pt_fallfadespark, ramp3[rand()%6], particletexture, false, 1.5, lhrandom(128, 255), 5, org, 15, 150); +// particle2(pt_fallfadespark, ramp3[rand()%6], particletexture, TPOLYTYPE_ALPHA, false, 1.5, lhrandom(128, 255), 5, org, 15, 150); for (i = 0;i < 32;i++) { fvel[0] = lhrandom(-150, 150); fvel[1] = lhrandom(-150, 150); fvel[2] = lhrandom(-150, 150) + 80; -// particle(pt_flamefall, 106 + (rand()%6), particletexture, 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]); +// 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++) { forg[0] = lhrandom(-20, 20) + org[0]; @@ -480,15 +514,15 @@ void R_ParticleExplosion (vec3_t org, int smoke) fvel2[0] *= f; fvel2[1] *= f; fvel2[2] *= f; - particle(pt_flamefall, 106 + (rand()%6), particletexture, false, 5, lhrandom(96, 192), 5, forg[0], forg[1], forg[2], fvel2[0], fvel2[1], fvel2[2]); + 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 (i = 0;i < 16;i++) -// particle2(pt_smoke, 12+(rand()&3), smokeparticletexture[rand()&7], true, 20, 192, 99, org, 20, 0); +// particle2(pt_smoke, 12+(rand()&3), smokeparticletexture[rand()&7], TPOLYTYPE_ALPHA, true, 20, 192, 99, org, 20, 0); // for (i = 0;i < 50;i++) -// particle2(pt_flamingdebris, ramp3[rand()%6], particletexture, false, 3, 255, 99, org, 10, 200); +// particle2(pt_flamingdebris, ramp3[rand()%6], particletexture, TPOLYTYPE_ALPHA, false, 3, 255, 99, org, 10, 200); // for (i = 0;i < 30;i++) -// particle2(pt_smokingdebris, 10 + (rand()%6), particletexture, false, 2, 255, 99, org, 10, 100); +// particle2(pt_smokingdebris, 10 + (rand()%6), particletexture, TPOLYTYPE_ALPHA, false, 2, 255, 99, org, 10, 100); } */ } @@ -505,7 +539,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++) - particle2(pt_fade, colorStart + (i % colorLength), particletexture, false, 1.5, 255, 0.3, org, 8, 192); + particle2(pt_fade, colorStart + (i % colorLength), particletexture, TPOLYTYPE_ALPHA, false, 1.5, 255, 0.3, 0, org, 8, 192); } /* @@ -520,9 +554,9 @@ void R_BlobExplosion (vec3_t org) if (!r_particles.value) return; // LordHavoc: particles are optional for (i=0 ; i<512 ; i++) - particle3(pt_blob, 66+(rand()%6), particletexture, false, 2, 255, lhrandom(1, 1.4), org, 16, 16, 16, 4, 4, 128); + particle3(pt_blob, 66+(rand()%6), particletexture, TPOLYTYPE_ALPHA, false, 2, 255, lhrandom(1, 1.4), 0, org, 16, 16, 16, 4, 4, 128); for (i=0 ; i<512 ; i++) - particle3(pt_blob2, 150+(rand()%6), particletexture, false, 2, 255, lhrandom(1, 1.4), org, 16, 16, 16, 4, 4, 128); + particle3(pt_blob2, 150+(rand()%6), particletexture, TPOLYTYPE_ALPHA, false, 2, 255, lhrandom(1, 1.4), 0, org, 16, 16, 16, 4, 4, 128); } /* @@ -540,15 +574,8 @@ void R_RunParticleEffect (vec3_t org, vec3_t dir, int color, int count) R_ParticleExplosion(org, false); return; } - color &= ~7; - if (count & 7) - { - particle2(pt_fade, color + (rand()&7), particletexture, false, 6, (count & 7) * 16 + (rand()&15), 1, org, 8, 15); - count &= ~7; - } - count >>= 3; while (count--) - particle2(pt_fade, color + (rand()&7), particletexture, false, 6, 128, 1, org, 8, 15); + particle2(pt_fade, color + (rand()&7), particletexture, TPOLYTYPE_ALPHA, false, 1, 128, 1, 0, org, 8, 15); } // LordHavoc: added this for spawning sparks/dust (which have strong gravity) @@ -562,26 +589,27 @@ void R_SparkShower (vec3_t org, vec3_t dir, int count) if (!r_particles.value) return; // LordHavoc: particles are optional // smoke puff - particle(pt_smoke, 12+(rand()&3), smokeparticletexture[rand()&7], true, 8, 160, 99, org[0], org[1], org[2], 0, 0, 0); + particle(pt_bulletsmoke, 12+(rand()&3), smokeparticletexture[rand()&7], TPOLYTYPE_ALPHA, true, 1, 160, 99, 0, org[0], org[1], org[2], lhrandom(-4, 4), lhrandom(-4, 4), 16); // sparks while(count--) -// particle2(pt_fallfadespark, ramp3[rand()%6], particletexture, false, 1, lhrandom(0, 255), 5, org, 4, 96); - particle(pt_fallfadespark, ramp3[rand()%6], particletexture, false, 1, lhrandom(0, 255), 5, lhrandom(-4, 4) + org[0], lhrandom(-4, 4) + org[1], lhrandom(-4, 4) + org[2], lhrandom(-64, 64), lhrandom(-64, 64), lhrandom(-64, 64) + 64); + particle(pt_fallfadespark, ramp3[rand()%6], particletexture, TPOLYTYPE_ADD, false, 1, lhrandom(0, 255), 1.5, 1.5, org[0], org[1], org[2], lhrandom(-64, 64), lhrandom(-64, 64), lhrandom(-64, 64) + 128); } -void R_BloodPuff (vec3_t org) +void R_BloodPuff (vec3_t org, vec3_t vel, int count) { if (!r_particles.value) return; // LordHavoc: particles are optional - particle(pt_bloodcloud, 251 /*68+(rand()&3)*/, smokeparticletexture[rand()&7], true, 12, 128, 99, org[0], org[1], org[2], 0, 0, 0); - particle(pt_bloodcloud, 251 /*68+(rand()&3)*/, smokeparticletexture[rand()&7], true, 10, 128, 99, org[0] + lhrandom(-4, 4), org[1] + lhrandom(-4, 4), org[2] + lhrandom(-4, 4), 0, 0, 0); - particle(pt_bloodcloud, 251 /*68+(rand()&3)*/, smokeparticletexture[rand()&7], true, 8, 128, 99, org[0] + lhrandom(-4, 4), org[1] + lhrandom(-4, 4), org[2] + lhrandom(-4, 4), 0, 0, 0); + if (count > 100) + count = 100; + while(count > 0) + { + particle(pt_bloodsplatter, 68+(rand()&3), smokeparticletexture[rand()&7], TPOLYTYPE_ALPHA, true, lhrandom(10, 20), min(count, 10) * 25 + 5, 99, -1, org[0], org[1], org[2], vel[0] + lhrandom(-64, 64), vel[1] + lhrandom(-64, 64), vel[2] + lhrandom(-64, 64)); + count -= 10; + } } void R_BloodShower (vec3_t mins, vec3_t maxs, float velspeed, int count) { - int j; - particle_t *p; vec3_t diff; vec3_t center; vec3_t velscale; @@ -592,73 +620,37 @@ void R_BloodShower (vec3_t mins, vec3_t maxs, float velspeed, int count) center[1] = (mins[1] + maxs[1]) * 0.5; center[2] = (mins[2] + maxs[2]) * 0.5; // FIXME: change velspeed back to 2.0x after fixing mod - velscale[0] = velspeed * 0.5 / diff[0]; - velscale[1] = velspeed * 0.5 / diff[1]; - velscale[2] = velspeed * 0.5 / diff[2]; + velscale[0] = velspeed * 2.0 / diff[0]; + velscale[1] = velspeed * 2.0 / diff[1]; + velscale[2] = velspeed * 2.0 / diff[2]; while (count--) { - ALLOCPARTICLE(p) - - p->texnum = smokeparticletexture[rand()&7]; - p->dynlight = true; - p->scale = lhrandom(4, 6); - p->alpha = 96 + (rand()&63); - p->die = cl.time + 2; - p->type = pt_bloodcloud; - p->color = 251; //(rand()&3)+68; - for (j=0 ; j<3 ; j++) - { - p->org[j] = diff[j] * (float) (rand()%1024) * (1.0 / 1024.0) + mins[j]; - p->vel[j] = (p->org[j] - center[j]) * velscale[j]; - } + vec3_t org, vel; + org[0] = lhrandom(mins[0], maxs[0]); + org[1] = lhrandom(mins[1], maxs[1]); + org[2] = lhrandom(mins[2], maxs[2]); + 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_bloodsplatter, 68+(rand()&3), smokeparticletexture[rand()&7], TPOLYTYPE_ALPHA, true, lhrandom(10, 25), 255, 99, -1, org[0], org[1], org[2], vel[0], vel[1], vel[2]); } } void R_ParticleCube (vec3_t mins, vec3_t maxs, vec3_t dir, int count, int colorbase, int gravity, int randomvel) { - int j; - particle_t *p; - vec3_t diff; float t; if (!r_particles.value) return; // LordHavoc: particles are optional if (maxs[0] <= mins[0]) {t = mins[0];mins[0] = maxs[0];maxs[0] = t;} if (maxs[1] <= mins[1]) {t = mins[1];mins[1] = maxs[1];maxs[1] = t;} if (maxs[2] <= mins[2]) {t = mins[2];mins[2] = maxs[2];maxs[2] = t;} - VectorSubtract(maxs, mins, diff); - while (count--) - { - ALLOCPARTICLE(p) - - p->texnum = particletexture; - p->dynlight = false; - p->scale = 6; - p->alpha = 255; - p->die = cl.time + 1 + (rand()&15)*0.0625; - if (gravity) - p->type = pt_grav; - else - p->type = pt_static; - p->color = colorbase + (rand()&3); - for (j=0 ; j<3 ; j++) - { - p->org[j] = diff[j] * (float) (rand()&1023) * (1.0 / 1024.0) + mins[j]; - if (randomvel) - p->vel[j] = dir[j] + (rand()%randomvel)-(randomvel*0.5); - else - p->vel[j] = 0; - } - } + 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)); } void R_ParticleRain (vec3_t mins, vec3_t maxs, vec3_t dir, int count, int colorbase, int type) { - int i; - particle_t *p; - vec3_t diff; - vec3_t org; vec3_t vel; float t, z; if (!r_particles.value) return; // LordHavoc: particles are optional @@ -677,44 +669,53 @@ void R_ParticleRain (vec3_t mins, vec3_t maxs, vec3_t dir, int count, int colorb } if (t < 0 || t > 2) // sanity check t = 2; - t += cl.time; - VectorSubtract(maxs, mins, diff); - - for (i=0 ; ialpha = 255; - p->die = t; - if (type == 1) + case 0: + while(count--) { - p->scale = 2; - p->texnum = particletexture; - p->dynlight = false; - p->type = pt_snow; + 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]); } - else // 0 + break; + case 1: + while(count--) { - p->scale = 3; - p->texnum = rainparticletexture; - p->dynlight = true; - p->type = pt_rain; + 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]); } - p->color = colorbase + (rand()&3); - VectorCopy(org, p->org); - VectorCopy(vel, p->vel); - VectorCopy(vel, p->vel2); + break; + default: + Host_Error("R_ParticleRain: unknown type %i (0 = rain, 1 = snow)\n", type); } } +void R_FlameCube (vec3_t mins, vec3_t maxs, int count) +{ + float t; + if (!r_particles.value) return; // LordHavoc: particles are optional + if (maxs[0] <= mins[0]) {t = mins[0];mins[0] = maxs[0];maxs[0] = t;} + if (maxs[1] <= mins[1]) {t = mins[1];mins[1] = maxs[1];maxs[1] = t;} + 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, 1, lhrandom(64, 255), 5, 0, lhrandom(mins[0], maxs[0]), lhrandom(mins[1], maxs[1]), lhrandom(mins[2], maxs[2]), lhrandom(-16, 16), lhrandom(-16, 16), lhrandom(-16, 48)); +} + +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, 1, lhrandom(64, 255), 5, 1.5, org[0], org[1], org[2], vel[0] + lhrandom(-16, 16), vel[1] + lhrandom(-16, 16), vel[2] + lhrandom(-16, 16)); +} + + /* =============== @@ -722,39 +723,28 @@ R_LavaSplash =============== */ -void R_LavaSplash (vec3_t org) +void R_LavaSplash (vec3_t origin) { int i, j; - particle_t *p; float vel; - vec3_t dir; + vec3_t dir, org; if (!r_particles.value) return; // LordHavoc: particles are optional - for (i=-128 ; i<128 ; i+=16) - for (j=-128 ; j<128 ; j+=16) + for (i=-128 ; i<128 ; i+=8) + { + for (j=-128 ; j<128 ; j+=8) { - ALLOCPARTICLE(p) - - p->texnum = particletexture; - p->dynlight = false; - p->scale = 10; - p->alpha = 128; - p->die = cl.time + 2 + (rand()&31) * 0.02; - p->color = 224 + (rand()&7); - p->type = pt_grav; - - dir[0] = j + (rand()&7); - dir[1] = i + (rand()&7); + dir[0] = j + lhrandom(0, 8); + dir[1] = i + lhrandom(0, 8); dir[2] = 256; - - p->org[0] = org[0] + dir[0]; - p->org[1] = org[1] + dir[1]; - p->org[2] = org[2] + (rand()&63); - - VectorNormalize (dir); - vel = 50 + (rand()&63); - VectorScale (dir, vel, p->vel); + org[0] = origin[0] + dir[0]; + org[1] = origin[1] + dir[1]; + org[2] = origin[2] + lhrandom(0, 64); + vel = lhrandom(50, 120) / VectorLength(dir); // normalize and scale + particle(pt_slowgrav, 224 + (rand()&7), particletexture, TPOLYTYPE_ALPHA, false, 3, 128, lhrandom(2, 2.5), 0, org[0], org[1], org[2], dir[0] * vel, dir[1] * vel, dir[2] * vel); +// particle(pt_slowgrav, 224 + (rand()&7), particletexture, TPOLYTYPE_ALPHA, false, 3, 128, lhrandom(2, 2.5), 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)); } + } } /* @@ -766,194 +756,143 @@ R_TeleportSplash void R_TeleportSplash (vec3_t org) { int i, j, k; - particle_t *p; if (!r_particles.value) return; // LordHavoc: particles are optional for (i=-16 ; i<16 ; i+=8) for (j=-16 ; j<16 ; j+=8) for (k=-24 ; k<32 ; k+=8) - { - ALLOCPARTICLE(p) - - p->texnum = particletexture; - p->dynlight = false; - p->scale = 1; - p->alpha = lhrandom(32,128); - p->die = cl.time + 5; - p->color = 254; - p->type = pt_fade; - - p->org[0] = org[0] + i + (rand()&7); - p->org[1] = org[1] + j + (rand()&7); - p->org[2] = org[2] + k + (rand()&7); - - p->vel[0] = i*2 + (rand()%25) - 12; - p->vel[1] = j*2 + (rand()%25) - 12; - p->vel[2] = k*2 + (rand()%25) - 12 + 40; - } + particle(pt_fade, 254, particletexture, TPOLYTYPE_ADD, false, 1, lhrandom(64, 128), 5, 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)); } void R_RocketTrail (vec3_t start, vec3_t end, int type, entity_t *ent) { - vec3_t vec; - float len, dec = 0, t, nt, speed; - int j, contents, bubbles; - particle_t *p; + vec3_t vec, dir, vel; + float len, dec = 0, speed; + int contents, bubbles, polytype; + double t; if (!r_particles.value) return; // LordHavoc: particles are optional - t = cl.oldtime; - nt = cl.time; - if (ent->trail_leftover < 0) - ent->trail_leftover = 0; - t += ent->trail_leftover; - ent->trail_leftover -= (cl.time - cl.oldtime); + VectorSubtract(end, start, dir); + VectorNormalize(dir); + + /* + if (type == 0) // rocket glow + particle(pt_glow, 254, particletexture, TPOLYTYPE_ADD, false, 10, 160, 999, 0, start[0] - 12 * dir[0], start[1] - 12 * dir[1], start[2] - 12 * dir[2], 0, 0, 0); + */ + + t = ent->trail_time; if (t >= cl.time) - return; + return; // no particles to spawn this frame (sparse trail) - contents = Mod_PointInLeaf(start, cl.worldmodel)->contents; - if (contents == CONTENTS_SKY || contents == CONTENTS_LAVA) - return; + if (t < cl.oldtime) + t = cl.oldtime; VectorSubtract (end, start, vec); len = VectorNormalizeLength (vec); if (len <= 0.01f) + { + // advance the trail time + ent->trail_time = cl.time; return; - speed = len / (nt - t); + } + speed = len / (cl.time - cl.oldtime); + VectorScale(vec, speed, vel); - bubbles = (contents == CONTENTS_WATER || contents == CONTENTS_SLIME); + // advance into this frame to reach the first puff location + dec = t - cl.oldtime; + dec *= speed; + VectorMA(start, dec, vec, start); - while (t < nt) + contents = Mod_PointInLeaf(start, cl.worldmodel)->contents; + if (contents == CONTENTS_SKY || contents == CONTENTS_LAVA) { - ALLOCPARTICLE(p) - - p->vel[0] = p->vel[1] = p->vel[2] = 0; - p->die = cl.time + 2; + // advance the trail time + ent->trail_time = cl.time; + return; + } + bubbles = (contents == CONTENTS_WATER || contents == CONTENTS_SLIME); + + polytype = TPOLYTYPE_ALPHA; + if (ent->effects & EF_ADDITIVE) + polytype = TPOLYTYPE_ADD; + + while (t < cl.time) + { switch (type) { case 0: // rocket trail - case 1: // grenade trail if (bubbles) { - dec = type == 0 ? 0.01f : 0.02f; - p->texnum = bubbleparticletexture; - p->dynlight = false; - p->scale = lhrandom(1,2); - p->alpha = 255; - p->color = 254; - p->type = pt_bubble; - p->die = cl.time + 2; - for (j=0 ; j<3 ; j++) - { - p->vel[j] = (rand()&31)-16; - p->org[j] = start[j] + ((rand()&3)-2); - } + dec = 0.01f; + particle(pt_bubble, 254, bubbleparticletexture, polytype, false, lhrandom(1, 2), 255, 2, 1.5, start[0], start[1], start[2], lhrandom(-16, 16), lhrandom(-16, 16), lhrandom(-16, 16)); } else { - dec = type == 0 ? 0.02f : 0.04f; - p->texnum = smokeparticletexture[rand()&7]; - p->dynlight = true; - p->scale = lhrandom(4, 8); - p->alpha = 160; //128 + (rand()&63); - p->color = 254; - p->type = pt_smoke; - p->die = cl.time + 10000; - VectorCopy(start, p->org); - /* + dec = 0.01f; + particle(pt_smoke, 254, smokeparticletexture[rand()&7], polytype, true, 2, 160, 9999, 0, start[0], start[1], start[2], 0, 0, 16); if (type == 0) { - particle(pt_fallfadespark, 0x68 + (rand() & 7), particletexture, false, 1, lhrandom(64, 128), 5, start[0], start[1], start[2], lhrandom(-64, 64), lhrandom(-64, 64), lhrandom(-64, 64)); - particle(pt_fallfadespark, 0x68 + (rand() & 7), particletexture, false, 1, lhrandom(64, 128), 5, start[0], start[1], start[2], lhrandom(-64, 64), lhrandom(-64, 64), lhrandom(-64, 64)); - particle(pt_fallfadespark, 0x68 + (rand() & 7), particletexture, false, 1, lhrandom(64, 128), 5, start[0], start[1], start[2], lhrandom(-64, 64), lhrandom(-64, 64), lhrandom(-64, 64)); - particle(pt_fallfadespark, 0x68 + (rand() & 7), particletexture, false, 1, lhrandom(64, 128), 5, start[0], start[1], start[2], lhrandom(-64, 64), lhrandom(-64, 64), lhrandom(-64, 64)); + particle(pt_fallfadespark, 0x68 + (rand() & 7), particletexture, TPOLYTYPE_ADD, false, 1, lhrandom(128, 255), 5, 0, 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_fallfadespark, 0x68 + (rand() & 7), particletexture, TPOLYTYPE_ADD, false, 1, lhrandom(128, 255), 5, 0, 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_fallfadespark, 0x68 + (rand() & 7), particletexture, TPOLYTYPE_ADD, false, 1, lhrandom(128, 255), 5, 0, 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_fallfadespark, 0x68 + (rand() & 7), particletexture, TPOLYTYPE_ADD, false, 1, lhrandom(128, 255), 5, 0, 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); } - */ } break; - /* - case 1: // smoke smoke - dec = 0.016f; - p->texnum = smokeparticletexture; - p->dynlight = true; - p->scale = lhrandom(6,9); - p->alpha = 64; - if (r_smokecolor.value) - p->color = r_smokecolor.value; + case 1: // grenade trail + // FIXME: make it gradually stop smoking + if (bubbles) + { + dec = 0.02f; + particle(pt_bubble, 254, bubbleparticletexture, polytype, false, lhrandom(1, 2), 255, 2, 1.5, start[0], start[1], start[2], lhrandom(-16, 16), lhrandom(-16, 16), lhrandom(-16, 16)); + } else - p->color = (rand()&3)+12; - p->type = pt_smoke; - p->die = cl.time + 1; - VectorCopy(start, p->org); + { + dec = 0.02f; + particle(pt_smoke, 6, smokeparticletexture[rand()&7], polytype, true, 2, 160, 9999, 0, start[0], start[1], start[2], 0, 0, 16); + } break; - */ + case 2: // blood + dec = 0.025f; + particle(pt_bloodsplatter, 67+(rand()&3), smokeparticletexture[rand()&7], polytype, true, lhrandom(5, 20), 255, 9999, -1, start[0], start[1], start[2], vel[0] + lhrandom(-64, 64), vel[1] + lhrandom(-64, 64), vel[2] + lhrandom(-64, 64)); + break; + case 4: // slight blood dec = 0.025f; - p->texnum = smokeparticletexture[rand()&7]; - p->dynlight = true; - p->scale = lhrandom(4, 6); - p->alpha = type == 4 ? 192 : 255; - p->color = 247; //(rand()&3)+68; - p->type = pt_bloodcloud; - p->die = cl.time + 9999; - for (j=0 ; j<3 ; j++) - { - p->vel[j] = (rand()&15)-8; - p->org[j] = start[j] + ((rand()&3)-2); - } + particle(pt_bloodsplatter, 67+(rand()&3), smokeparticletexture[rand()&7], polytype, true, lhrandom(5, 20), 192, 9999, -1, start[0], start[1], start[2], vel[0] + lhrandom(-64, 64), vel[1] + lhrandom(-64, 64), vel[2] + lhrandom(-64, 64)); break; - case 3: - case 5: // tracer + case 3: // green tracer dec = 0.02f; - p->texnum = smokeparticletexture[rand()&7]; - p->dynlight = false; - p->scale = 4; - p->alpha = 64 + (rand()&31); - p->color = type == 3 ? 56 : 234; - p->type = pt_fade; - p->die = cl.time + 10000; - VectorCopy(start, p->org); + particle(pt_fade, 56, smokeparticletexture[rand()&7], polytype, false, 4, 255, 9999, 0, start[0], start[1], start[2], 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); break; case 6: // voor trail dec = 0.05f; // sparse trail - p->texnum = smokeparticletexture[rand()&7]; - p->dynlight = false; - p->scale = lhrandom(3, 5); - p->alpha = 255; - p->color = 9*16 + 8 + (rand()&3); - p->type = pt_fade; - p->die = cl.time + 2; - for (j=0 ; j<3 ; j++) - { - p->vel[j] = (rand()&15)-8; - p->org[j] = start[j] + ((rand()&3)-2); - } + particle(pt_fade, 152 + (rand()&3), smokeparticletexture[rand()&7], polytype, false, 4, 255, 9999, 0, start[0], start[1], start[2], 0, 0, 0); break; case 7: // Nehahra smoke tracer dec = 0.14f; - p->texnum = smokeparticletexture[rand()&7]; - p->dynlight = true; - p->scale = lhrandom(8, 12); - p->alpha = 64; - p->color = (rand()&3)+12; - p->type = pt_smoke; - p->die = cl.time + 10000; - for (j=0 ; j<3 ; j++) - p->org[j] = start[j] + ((rand()&3)-2); + particle(pt_smoke, 12, smokeparticletexture[rand()&7], polytype, true, 10, 64, 9999, 0, start[0], start[1], start[2], 0, 0, 0); break; } + // advance to next time and position t += dec; dec *= speed; VectorMA (start, dec, vec, start); } - ent->trail_leftover = t - cl.time; + ent->trail_time = t; } void R_RocketTrail2 (vec3_t start, vec3_t end, int color, entity_t *ent) @@ -967,7 +906,7 @@ void R_RocketTrail2 (vec3_t start, vec3_t end, int color, entity_t *ent) VectorScale(vec, 3, vec); while (len--) { - particle(pt_smoke, color, particletexture, false, 8, 192, 99, start[0], start[1], start[2], 0, 0, 0); + particle(pt_smoke, color, particletexture, TPOLYTYPE_ALPHA, false, 8, 192, 99, 0, start[0], start[1], start[2], 0, 0, 0); VectorAdd (start, vec, start); } } @@ -1010,6 +949,35 @@ void R_MoveParticles (void) p->org[0] += p->vel[0]*frametime; p->org[1] += p->vel[1]*frametime; p->org[2] += p->vel[2]*frametime; + if (p->bounce) + { + vec3_t normal; + float dist; + if (TraceLine(p->oldorg, p->org, v, normal) < 1) + { + VectorCopy(v, p->org); + if (p->bounce < 0) + { + VectorClear(p->vel); + p->type = pt_decal; + // have to negate the direction (why?) + VectorNegate(normal, p->direction); + p->bounce = 0; + p->time2 = cl.time + 30; + } + else + { + dist = DotProduct(p->vel, normal) * -p->bounce; + VectorMAQuick(p->vel, dist, normal, p->vel); + if (DotProduct(p->vel, p->vel) < 0.03) + { + VectorClear(p->vel); + // hack - world is static, therefore there won't be any moving or disappearing surfaces to worry about + //p->bounce = 0; + } + } + } + } switch (p->type) { @@ -1027,6 +995,9 @@ void R_MoveParticles (void) case pt_grav: p->vel[2] -= gravity; break; + case pt_slowgrav: + p->vel[2] -= gravity * 0.05; + break; case pt_snow: if (cl.time > p->time2) { @@ -1035,28 +1006,92 @@ void R_MoveParticles (void) p->vel[1] = (rand()&63)-32 + p->vel2[1]; p->vel[2] = (rand()&63)-32 + p->vel2[2]; } + a = Mod_PointInLeaf(p->org, cl.worldmodel)->contents; + if (a != CONTENTS_EMPTY && a != CONTENTS_SKY) + { + 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) + { + case CONTENTS_LAVA: + case CONTENTS_SLIME: + p->tex = smokeparticletexture[rand()&7]; + p->type = pt_smokecloud; + p->alpha = 96; + p->scale = 5; + p->vel[2] = 96; + break; + case CONTENTS_WATER: + 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); + VectorCopy(v, p->org); + p->tex = smokeparticletexture[rand()&7]; + p->type = pt_fade; + VectorClear(p->vel); + break; + } + } break; case pt_bloodcloud: // if (Mod_PointInLeaf(p->org, cl.worldmodel)->contents != CONTENTS_EMPTY) // { // p->die = -1; // break; +// } + p->scale += frametime * 16; + p->alpha -= frametime * 256; + p->vel[2] -= gravity * 0.25; + if (p->alpha < 1) + p->die = -1; + break; + case pt_blood: +// if (Mod_PointInLeaf(p->org, cl.worldmodel)->contents != CONTENTS_EMPTY) +// { +// p->die = -1; +// break; // } p->scale += frametime * 16; p->alpha -= frametime * 512; + p->vel[2] -= gravity * 0.25; + if (p->alpha < 1) + p->die = -1; + break; + case pt_bloodsplatter: +// if (Mod_PointInLeaf(p->org, cl.worldmodel)->contents != CONTENTS_EMPTY) +// { +// p->die = -1; +// break; +// } + p->alpha -= frametime * 128; + if (p->alpha < 1) + p->die = -1; + p->vel[2] -= gravity * 0.5; break; case pt_fallfadespark: p->alpha -= frametime * 256; p->vel[2] -= gravity; + if (p->alpha < 1) + p->die = -1; break; case pt_fade: p->alpha -= frametime * 512; + if (p->alpha < 1) + p->die = -1; break; case pt_bubble: a = Mod_PointInLeaf(p->org, cl.worldmodel)->contents; if (a != CONTENTS_WATER && a != CONTENTS_SLIME) { - p->texnum = smokeparticletexture[rand()&7]; + p->tex = smokeparticletexture[rand()&7]; p->type = pt_splash; p->alpha = 96; p->scale = 5; @@ -1076,19 +1111,38 @@ void R_MoveParticles (void) p->vel[2] += lhrandom(-32,32); } p->alpha -= frametime * 64; + if (p->alpha < 1) + p->die = -1; + if (p->alpha < 1) + p->die = -1; break; // LordHavoc: for smoke trails + case pt_bulletsmoke: + p->scale += frametime * 60; + p->alpha -= frametime * 512; + p->vel[2] += gravity * 0.05; + if (p->alpha < 1) + p->die = -1; + break; case pt_smoke: - p->scale += frametime * 16; + p->scale += frametime * 20; p->alpha -= frametime * 256; + p->vel[2] += gravity * 0.05; + if (p->alpha < 1) + p->die = -1; break; case pt_smokecloud: p->scale += frametime * 64; p->alpha -= frametime * 256; + p->vel[2] += gravity * 0.05; + if (p->alpha < 1) + p->die = -1; break; case pt_splash: p->scale += frametime * 24; p->alpha -= frametime * 512; + if (p->alpha < 1) + p->die = -1; break; case pt_rain: a = Mod_PointInLeaf(p->org, cl.worldmodel)->contents; @@ -1098,73 +1152,95 @@ void R_MoveParticles (void) 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) { case CONTENTS_LAVA: case CONTENTS_SLIME: - p->texnum = smokeparticletexture[rand()&7]; + p->tex = smokeparticletexture[rand()&7]; p->type = pt_smokecloud; - p->alpha = 64; + p->alpha = 96; + p->scale = 5; p->vel[2] = 96; break; case CONTENTS_WATER: - p->texnum = smokeparticletexture[rand()&7]; + p->tex = smokeparticletexture[rand()&7]; p->type = pt_splash; p->alpha = 96; p->scale = 5; - p->vel[0] = p->vel[1] = p->vel[2] = 0; -// p->texnum = bubbleparticletexture; -// p->type = pt_bubble; -// p->vel[2] *= 0.1; break; default: // CONTENTS_SOLID and any others TraceLine(p->oldorg, p->org, v, normal); VectorCopy(v, p->org); - p->texnum = smokeparticletexture[rand()&7]; + p->tex = smokeparticletexture[rand()&7]; p->type = pt_splash; p->alpha = 96; p->scale = 5; - p->vel[0] = p->vel[1] = p->vel[2] = 0; - p->die = cl.time + 1000; + particle(pt_fallfadespark, 245, particletexture, TPOLYTYPE_ADD, false, 1, 64, 1, 1.3, p->org[0], p->org[1], p->org[2] + 1, lhrandom(-32, 32), lhrandom(-32, 32), lhrandom(-32, 32) + 48); + particle(pt_fallfadespark, 245, particletexture, TPOLYTYPE_ADD, false, 1, 128, 1, 1.3, p->org[0], p->org[1], p->org[2] + 1, lhrandom(-32, 32), lhrandom(-32, 32), lhrandom(-32, 32) + 48); + particle(pt_fallfadespark, 245, particletexture, TPOLYTYPE_ADD, false, 1, 192, 1, 1.3, p->org[0], p->org[1], p->org[2] + 1, lhrandom(-32, 32), lhrandom(-32, 32), lhrandom(-32, 32) + 48); + particle(pt_fallfadespark, 245, particletexture, TPOLYTYPE_ADD, false, 1, 255, 1, 1.3, p->org[0], p->org[1], p->org[2] + 1, lhrandom(-32, 32), lhrandom(-32, 32), lhrandom(-32, 32) + 48); break; } } break; case pt_flame: p->alpha -= frametime * 512; + p->vel[2] += gravity * 0.2; + if (p->alpha < 1) + p->die = -1; break; + /* case pt_flamingdebris: if (cl.time >= p->time2) { p->time2 = cl.time + 0.01; - particle2(pt_flame, p->color, particletexture, false, 4, p->alpha, 999, p->org, 0, 50); + particle2(pt_flame, p->color, particletexture, TPOLYTYPE_ADD, false, 4, p->alpha, 999, 0, p->org, 0, 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], false, 4, p->alpha, 999, p->org, 0, 50); + particle2(pt_flame, 15, smokeparticletexture[rand()&7], TPOLYTYPE_ALPHA, false, 4, p->alpha, 999, 0, p->org, 0, 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_flamefall: p->alpha -= frametime * 512; p->vel[2] -= gravity * 0.5f; + if (p->alpha < 1) + p->die = -1; + break; + */ + case pt_glow: + if (p->time2) + p->die = -1; + p->time2 = 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->die = -1; break; } - // LordHavoc: most particles did this check anyway, consistency... - if (p->alpha < 1) - p->die = -1; - // LordHavoc: immediate removal of unnecessary particles (must be done to ensure compactor below operates properly in all cases) if (p->die < cl.time) freeparticles[j++] = p; @@ -1185,15 +1261,13 @@ void R_MoveParticles (void) numparticles = activeparticles; } -void R_CompleteLightPoint (vec3_t color, vec3_t p); - void R_DrawParticles (void) { particle_t *p; int i, r,g,b,a, dynlight; float scale, scale2, minparticledist; byte *color24; - vec3_t up, right, uprightangles, forward2, up2, right2, tempcolor; + vec3_t up, right, uprightangles, up2, right2, tempcolor, corner, decalright, decalup, v; // LordHavoc: early out condition if ((!numparticles) || (!r_drawparticles.value)) @@ -1210,7 +1284,7 @@ void R_DrawParticles (void) uprightangles[0] = 0; uprightangles[1] = r_refdef.viewangles[1]; uprightangles[2] = 0; - AngleVectors (uprightangles, forward2, right2, up2); + AngleVectors (uprightangles, NULL, right2, up2); minparticledist = DotProduct(r_refdef.vieworg, vpn) + 16.0f; @@ -1220,6 +1294,13 @@ void R_DrawParticles (void) // if (p->die < cl.time) // continue; + if (p->type == pt_decal) + { + VectorSubtract(p->org, r_refdef.vieworg, v); + if (DotProduct(p->direction, v) < 0) + continue; + } + // LordHavoc: only render if not too close if (DotProduct(p->org, vpn) < minparticledist) continue; @@ -1236,21 +1317,38 @@ void R_DrawParticles (void) g = (g * (int) tempcolor[1]) >> 7; b = (b * (int) tempcolor[2]) >> 7; } - transpolybegin(p->texnum, 0, p->texnum, TPOLYTYPE_ALPHA); - scale = p->scale * -0.5;scale2 = p->scale * 0.5; - if (p->texnum == rainparticletexture) // rain streak + 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) + { + VectorVectors(p->direction, decalright, decalup); + corner[0] = p->org[0] + decalup[0]*scale + decalright[0]*scale; + corner[1] = p->org[1] + decalup[1]*scale + decalright[1]*scale; + corner[2] = p->org[2] + decalup[2]*scale + decalright[2]*scale; + transpolyvert(corner[0] , corner[1] , corner[2] , 0,1,r,g,b,a); + transpolyvert(corner[0] + decalup[0]*scale2 , corner[1] + decalup[1]*scale2 , corner[2] + decalup[2]*scale2 , 0,0,r,g,b,a); + transpolyvert(corner[0] + decalup[0]*scale2 + decalright[0]*scale2, corner[1] + decalup[1]*scale2 + decalright[1]*scale2, corner[2] + decalup[2]*scale2 + decalright[2]*scale2, 1,0,r,g,b,a); + transpolyvert(corner[0] + decalright[0]*scale2, corner[1] + decalright[1]*scale2, corner[2] + decalright[2]*scale2, 1,1,r,g,b,a); + } + else if (p->tex == rainparticletexture) // rain streak { - transpolyvert(p->org[0] + up2[0]*scale + right2[0]*scale , p->org[1] + up2[1]*scale + right2[1]*scale , p->org[2] + up2[2]*scale + right2[2]*scale , 0,1,r,g,b,a); - transpolyvert(p->org[0] + up2[0]*scale2 + right2[0]*scale , p->org[1] + up2[1]*scale2 + right2[1]*scale , p->org[2] + up2[2]*scale2 + right2[2]*scale , 0,0,r,g,b,a); - transpolyvert(p->org[0] + up2[0]*scale2 + right2[0]*scale2, p->org[1] + up2[1]*scale2 + right2[1]*scale2, p->org[2] + up2[2]*scale2 + right2[2]*scale2, 1,0,r,g,b,a); - transpolyvert(p->org[0] + up2[0]*scale + right2[0]*scale2, p->org[1] + up2[1]*scale + right2[1]*scale2, p->org[2] + up2[2]*scale + right2[2]*scale2, 1,1,r,g,b,a); + 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; + transpolyvert(corner[0] , corner[1] , corner[2] , 0,1,r,g,b,a); + transpolyvert(corner[0] + up2[0]*scale2 , corner[1] + up2[1]*scale2 , corner[2] + up2[2]*scale2 , 0,0,r,g,b,a); + transpolyvert(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,r,g,b,a); + transpolyvert(corner[0] + right2[0]*scale2, corner[1] + right2[1]*scale2, corner[2] + right2[2]*scale2, 1,1,r,g,b,a); } else { - transpolyvert(p->org[0] + up[0]*scale + right[0]*scale , p->org[1] + up[1]*scale + right[1]*scale , p->org[2] + up[2]*scale + right[2]*scale , 0,1,r,g,b,a); - transpolyvert(p->org[0] + up[0]*scale2 + right[0]*scale , p->org[1] + up[1]*scale2 + right[1]*scale , p->org[2] + up[2]*scale2 + right[2]*scale , 0,0,r,g,b,a); - transpolyvert(p->org[0] + up[0]*scale2 + right[0]*scale2, p->org[1] + up[1]*scale2 + right[1]*scale2, p->org[2] + up[2]*scale2 + right[2]*scale2, 1,0,r,g,b,a); - transpolyvert(p->org[0] + up[0]*scale + right[0]*scale2, p->org[1] + up[1]*scale + right[1]*scale2, p->org[2] + up[2]*scale + right[2]*scale2, 1,1,r,g,b,a); + corner[0] = p->org[0] + up[0]*scale + right[0]*scale; + corner[1] = p->org[1] + up[1]*scale + right[1]*scale; + corner[2] = p->org[2] + up[2]*scale + right[2]*scale; + transpolyvert(corner[0] , corner[1] , corner[2] , 0,1,r,g,b,a); + transpolyvert(corner[0] + up[0]*scale2 , corner[1] + up[1]*scale2 , corner[2] + up[2]*scale2 , 0,0,r,g,b,a); + transpolyvert(corner[0] + up[0]*scale2 + right[0]*scale2, corner[1] + up[1]*scale2 + right[1]*scale2, corner[2] + up[2]*scale2 + right[2]*scale2, 1,0,r,g,b,a); + transpolyvert(corner[0] + right[0]*scale2, corner[1] + right[1]*scale2, corner[2] + right[2]*scale2, 1,1,r,g,b,a); } transpolyend(); } diff --git a/r_sprites.c b/r_sprites.c index ef054901..13db9a00 100644 --- a/r_sprites.c +++ b/r_sprites.c @@ -1,87 +1,14 @@ #include "quakedef.h" -/* -================ -R_GetSpriteFrame -================ -*/ -void R_GetSpriteFrame (entity_t *currententity, mspriteframe_t **oldframe, mspriteframe_t **newframe, float *framelerp) -{ - msprite_t *psprite; - mspritegroup_t *pspritegroup; - int i, j, numframes, frame; - float *pintervals, fullinterval, targettime, time, jtime, jinterval; - - psprite = currententity->model->cache.data; - frame = currententity->frame; - - if ((frame >= psprite->numframes) || (frame < 0)) - { - Con_Printf ("R_DrawSprite: no such frame %d\n", frame); - frame = 0; - } - - if (psprite->frames[frame].type == SPR_SINGLE) - { - if (currententity->draw_lastmodel == currententity->model && currententity->draw_lerpstart < cl.time) - { - if (frame != currententity->draw_pose) - { - currententity->draw_lastpose = currententity->draw_pose; - currententity->draw_pose = frame; - currententity->draw_lerpstart = cl.time; - *framelerp = 0; - } - else - *framelerp = (cl.time - currententity->draw_lerpstart) * 10.0; - } - else // uninitialized - { - currententity->draw_lastmodel = currententity->model; - currententity->draw_lastpose = currententity->draw_pose = frame; - currententity->draw_lerpstart = cl.time; - *framelerp = 0; - } - *oldframe = psprite->frames[currententity->draw_lastpose].frameptr; - *newframe = psprite->frames[frame].frameptr; - } - else - { - pspritegroup = (mspritegroup_t *)psprite->frames[frame].frameptr; - pintervals = pspritegroup->intervals; - numframes = pspritegroup->numframes; - fullinterval = pintervals[numframes-1]; - - time = cl.time + currententity->syncbase; - - // when loading in Mod_LoadSpriteGroup, we guaranteed all interval values - // are positive, so we don't have to worry about division by 0 - targettime = time - ((int)(time / fullinterval)) * fullinterval; - - // LordHavoc: since I can't measure the time properly when it loops from numframes-1 to 0, - // I instead measure the time of the first frame, hoping it is consistent - j = numframes-1;jtime = 0;jinterval = pintervals[1] - pintervals[0]; - for (i=0 ; i<(numframes-1) ; i++) - { - if (pintervals[i] > targettime) - break; - j = i;jinterval = pintervals[i] - jtime;jtime = pintervals[i]; - } - *framelerp = (targettime - jtime) / jinterval; - - *oldframe = pspritegroup->frames[j]; - *newframe = pspritegroup->frames[i]; - } -} - -void GL_DrawSpriteImage (mspriteframe_t *frame, vec3_t origin, vec3_t up, vec3_t right, int red, int green, int blue, int alpha) +void GL_DrawSpriteImage (mspriteframe_t *frame, vec3_t origin, vec3_t up, vec3_t right, byte red, byte green, byte blue, int alpha) { - // LordHavoc: rewrote this to use the transparent poly system - transpolybegin(frame->gl_texturenum, 0, frame->gl_fogtexturenum, currententity->effects & EF_ADDITIVE ? TPOLYTYPE_ADD : TPOLYTYPE_ALPHA); - transpolyvert(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, alpha); - transpolyvert(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, alpha); - transpolyvert(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, alpha); - transpolyvert(origin[0] + frame->down * up[0] + frame->right * right[0], origin[1] + frame->down * up[1] + frame->right * right[1], origin[2] + frame->down * up[2] + frame->right * right[2], 1, 1, red, green, blue, alpha); + byte alphaub; + alphaub = bound(0, alpha, 255); + transpolybegin(R_GetTexture(frame->texture), 0, R_GetTexture(frame->fogtexture), currententity->effects & EF_ADDITIVE ? TPOLYTYPE_ADD : TPOLYTYPE_ALPHA); + transpolyvertub(origin[0] + frame->down * up[0] + frame->left * right[0], origin[1] + frame->down * up[1] + frame->left * right[1], origin[2] + frame->down * up[2] + frame->left * right[2], 0, 1, red, green, blue, alphaub); + transpolyvertub(origin[0] + frame->up * up[0] + frame->left * right[0], origin[1] + frame->up * up[1] + frame->left * right[1], origin[2] + frame->up * up[2] + frame->left * right[2], 0, 0, red, green, blue, alphaub); + transpolyvertub(origin[0] + frame->up * up[0] + frame->right * right[0], origin[1] + frame->up * up[1] + frame->right * right[1], origin[2] + frame->up * up[2] + frame->right * right[2], 1, 0, red, green, blue, alphaub); + transpolyvertub(origin[0] + frame->down * up[0] + frame->right * right[0], origin[1] + frame->down * up[1] + frame->right * right[1], origin[2] + frame->down * up[2] + frame->right * right[2], 1, 1, red, green, blue, alphaub); transpolyend(); } @@ -91,29 +18,23 @@ R_DrawSpriteModel ================= */ -void R_DrawSpriteModel (entity_t *e) +void R_DrawSpriteModel (entity_t *e, frameblend_t *blend) { - mspriteframe_t *oldframe, *newframe; - float lerp, ilerp; - vec3_t forward, right, up, org, color; + vec3_t right, up, org, color; + byte colorub[4]; msprite_t *psprite; // don't even bother culling, because it's just a single // polygon without a surface cache c_sprites++; - - R_GetSpriteFrame (e, &oldframe, &newframe, &lerp); - if (lerp < 0) lerp = 0; - if (lerp > 1) lerp = 1; - if (isRagePro) // LordHavoc: no alpha scaling supported on per pixel alpha images on ATI Rage Pro... ACK! - lerp = 1; - ilerp = 1.0 - lerp; - psprite = e->model->cache.data; + + psprite = Mod_Extradata(e->model); + //psprite = e->model->cache.data; if (psprite->type == SPR_ORIENTED) { // bullet marks on walls - AngleVectors (e->angles, forward, right, up); + AngleVectors (e->angles, NULL, right, up); VectorSubtract(e->origin, vpn, org); } else @@ -135,15 +56,20 @@ void R_DrawSpriteModel (entity_t *e) color[2] = e->colormod[2] * 255; } else - { - R_LightPoint (color, e->origin); - R_DynamicLightPointNoMask(color, e->origin); - } + R_CompleteLightPoint(color, e->origin); + + 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 (ilerp != 0) - GL_DrawSpriteImage(oldframe, org, up, right, color[0],color[1],color[2],e->alpha*255*ilerp); - if (lerp != 0) - GL_DrawSpriteImage(newframe, org, up, right, color[0],color[1],color[2],e->alpha*255*lerp); + 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->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->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->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->alpha*255*blend[3].lerp); } diff --git a/r_textures.h b/r_textures.h new file mode 100644 index 00000000..9657fadf --- /dev/null +++ b/r_textures.h @@ -0,0 +1,19 @@ + +#define TEXF_ALPHA 1 // transparent +#define TEXF_MIPMAP 2 // mipmapped +#define TEXF_RGBA 4 // 32bit RGBA, as opposed to 8bit paletted +#define TEXF_PRECACHE 8 // upload immediately, otherwise defer loading until it is used (r_textureprecache can override this) + +// contents of this structure are private to gl_textures.c +typedef struct rtexture_s +{ + int useless; +} +rtexture_t; + +// uploads a texture +extern rtexture_t *R_LoadTexture (char *identifier, int width, int height, byte *data, int flags); +// returns the renderer dependent texture slot number (call this before each use, as a texture might not have been precached) +extern int R_GetTexture (rtexture_t *rt); +// returns a GL texture slot (only used for lightmaps) +extern int R_GetTextureSlots(int count); diff --git a/render.h b/render.h index 669b7b37..5cf362e6 100644 --- a/render.h +++ b/render.h @@ -55,10 +55,7 @@ typedef struct entity_s float alpha; // opacity (alpha) of the model float colormod[3]; // color tint for model float scale; // size the model is shown - int draw_lastpose, draw_pose; // for interpolation - float draw_lerpstart; // for interpolation - struct model_s *draw_lastmodel; // for interpolation - float trail_leftover; + float trail_time; float glowsize; // how big the glow is byte glowcolor; // color of glow and particle trail (paletted) byte glowtrail; // leaves a trail of particles @@ -66,10 +63,17 @@ typedef struct entity_s struct model_s *model; // NULL = no model struct efrag_s *efrag; // linked list of efrags - int frame; + int frame; // current desired frame (usually identical to frame2, but frame2 is not always used) + struct model_s *lerp_model; // lerp resets when model changes + float lerp_starttime; // start of this transition + 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 lerp_starttime + double frame1start; // time frame1 began playing (for framegroup animations) + double frame2start; // time frame2 began playing (for framegroup animations) float syncbase; // for client-side animations int colormap; - int effects; // light, particals, etc + int effects; // light, particles, etc int skinnum; // for Alias models int visframe; // last frame this entity was // found in an active leaf @@ -89,6 +93,7 @@ typedef struct { vrect_t vrect; // subwindow in video for refresh // FIXME: not need vrect next field here? + /* vrect_t aliasvrect; // scaled Alias version int vrectright, vrectbottom; // right & bottom screen coords int aliasvrectright, aliasvrectbottom; // scaled Alias versions @@ -104,15 +109,16 @@ typedef struct float fvrectbottom; // bottommost edge, for Alias clamping float horizontalFieldOfView; // at Z = 1.0, this many X is visible // 2.0 = 90 degrees - float xOrigin; // should probably allways be 0.5 + float xOrigin; // should probably always be 0.5 float yOrigin; // between be around 0.3 to 0.5 + */ vec3_t vieworg; vec3_t viewangles; float fov_x, fov_y; - int ambientlight; +// int ambientlight; } refdef_t; @@ -126,46 +132,44 @@ extern vec3_t r_origin, vpn, vright, vup; extern struct texture_s *r_notexture_mip; -extern void R_Init (void); -extern void R_InitTextures (void); -extern void R_InitEfrags (void); -extern void R_RenderView (void); // must set r_refdef first -extern void R_ViewChanged (vrect_t *pvrect, int lineadj, float aspect); +void R_Init (void); +void R_InitTextures (void); +void R_InitEfrags (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 -extern void R_InitSky (byte *src, int bytesperpixel); // called at level load -//extern void R_InitSky (struct texture_s *mt); // called at level load - -extern void R_AddEfrags (entity_t *ent); -extern void R_RemoveEfrags (entity_t *ent); - -extern void R_NewMap (void); - - -extern void R_ParseParticleEffect (void); -extern void R_RunParticleEffect (vec3_t org, vec3_t dir, int color, int count); -extern void R_RocketTrail (vec3_t start, vec3_t end, int type, entity_t *ent); -extern void R_RocketTrail2 (vec3_t start, vec3_t end, int type, entity_t *ent); -extern void R_SparkShower (vec3_t org, vec3_t dir, int count); -extern void R_BloodPuff (vec3_t org); - -extern void R_EntityParticles (entity_t *ent); -extern void R_BlobExplosion (vec3_t org); -extern void R_ParticleExplosion (vec3_t org, int smoke); -extern void R_ParticleExplosion2 (vec3_t org, int colorStart, int colorLength); -extern void R_LavaSplash (vec3_t org); -extern void R_TeleportSplash (vec3_t org); - -extern void R_NewExplosion(vec3_t org); - -extern void R_PushDlights (void); -extern void R_DrawWorld (void); -//extern void R_RenderDlights (void); -extern void R_DrawParticles (void); -extern void R_MoveParticles (void); -extern void R_DrawExplosions (void); -extern void R_MoveExplosions (void); - -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); +void R_InitSky (byte *src, int bytesperpixel); // called at level load +//void R_InitSky (struct texture_s *mt); // called at level load + +void R_AddEfrags (entity_t *ent); +void R_RemoveEfrags (entity_t *ent); + +void R_NewMap (void); + + +void R_ParseParticleEffect (void); +void R_RunParticleEffect (vec3_t org, vec3_t dir, int color, int count); +void R_RocketTrail (vec3_t start, vec3_t end, int type, entity_t *ent); +void R_RocketTrail2 (vec3_t start, vec3_t end, int type, entity_t *ent); +void R_SparkShower (vec3_t org, vec3_t dir, int count); +void R_BloodPuff (vec3_t org, vec3_t vel, int count); +void R_FlameCube (vec3_t mins, vec3_t maxs, int count); +void R_Flames (vec3_t org, vec3_t vel, int count); + +void R_EntityParticles (entity_t *ent); +void R_BlobExplosion (vec3_t org); +void R_ParticleExplosion (vec3_t org, int smoke); +void R_ParticleExplosion2 (vec3_t org, int colorStart, int colorLength); +void R_LavaSplash (vec3_t org); +void R_TeleportSplash (vec3_t org); + +void R_NewExplosion(vec3_t org); + +void R_PushDlights (void); +void R_DrawWorld (void); +//void R_RenderDlights (void); +void R_DrawParticles (void); +void R_MoveParticles (void); +void R_DrawExplosions (void); +void R_MoveExplosions (void); diff --git a/server.h b/server.h index c377acdc..4eada814 100644 --- a/server.h +++ b/server.h @@ -40,6 +40,8 @@ typedef struct qboolean loadgame; // handle connections specially double time; + + double frametime; int lastcheck; // used by PF_checkclient double lastchecktime; @@ -204,8 +206,8 @@ extern edict_t *sv_player; void SV_Init (void); void SV_StartParticle (vec3_t org, vec3_t dir, int color, int count); -void SV_StartSound (edict_t *entity, int channel, char *sample, int volume, - float attenuation); +void SV_StartEffect (vec3_t org, int modelindex, int startframe, int framecount, int framerate); +void SV_StartSound (edict_t *entity, int channel, char *sample, int volume, float attenuation); void SV_DropClient (qboolean crash); diff --git a/snd_dma.c b/snd_dma.c index a66e329a..4f760acc 100644 --- a/snd_dma.c +++ b/snd_dma.c @@ -64,9 +64,6 @@ int num_sfx; sfx_t *ambient_sfx[NUM_AMBIENTS]; -int desired_speed = 44100; //11025; // LordHavoc: 44.1khz sound -int desired_bits = 16; - int sound_started=0; cvar_t bgmvolume = {"bgmvolume", "1", true}; @@ -376,7 +373,7 @@ channel_t *SND_PickChannel(int entnum, int entchannel) if (entchannel != 0 // channel 0 never overrides && channels[ch_idx].entnum == entnum && (channels[ch_idx].entchannel == entchannel || entchannel == -1) ) - { // allways override sound from same entity + { // always override sound from same entity first_to_die = ch_idx; break; } @@ -414,7 +411,7 @@ void SND_Spatialize(channel_t *ch) vec3_t source_vec; sfx_t *snd; -// anything coming from the view entity will allways be full volume +// anything coming from the view entity will always be full volume // LordHavoc: make sounds with ATTN_NONE have no spatialization if (ch->entnum == cl.viewentity || ch->dist_mult == 0) { @@ -517,9 +514,12 @@ void S_StartSound(int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float f continue; if (check->sfx == sfx && !check->pos) { - skip = rand () % (int)(0.1*shm->speed); - if (skip >= target_chan->end) - skip = target_chan->end - 1; + // LordHavoc: fixed skip calculations + skip = 0.1 * shm->speed; + if (skip > sc->length) + skip = sc->length; + if (skip > 0) + skip = rand() % skip; target_chan->pos += skip; target_chan->end -= skip; break; @@ -707,13 +707,13 @@ void S_UpdateAmbientSounds (void) // don't adjust volume too fast if (chan->master_vol < vol) { - chan->master_vol += host_frametime * ambient_fade.value; + chan->master_vol += host_realframetime * ambient_fade.value; if (chan->master_vol > vol) chan->master_vol = vol; } else if (chan->master_vol > vol) { - chan->master_vol -= host_frametime * ambient_fade.value; + chan->master_vol -= host_realframetime * ambient_fade.value; if (chan->master_vol < vol) chan->master_vol = vol; } @@ -763,7 +763,7 @@ void S_Update(vec3_t origin, vec3_t forward, vec3_t right, vec3_t up) // try to combine static sounds with a previous channel of the same // sound effect so we don't mix five torches every frame - if (i >= MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS) + if (i > MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS) { // see if it can just use the last one if (combine && combine->sfx == ch->sfx) diff --git a/snd_mem.c b/snd_mem.c index f573c370..09758a63 100644 --- a/snd_mem.c +++ b/snd_mem.c @@ -30,10 +30,10 @@ byte *S_Alloc (int size); ResampleSfx ================ */ -void ResampleSfx (sfx_t *sfx, int inrate, byte *data) +void ResampleSfx (sfx_t *sfx, int inrate, byte *data, char *name) { int outcount; - int srcsample; + int srcsample, srclength; float stepscale; int i; int samplefrac, fracstep; @@ -45,6 +45,8 @@ void ResampleSfx (sfx_t *sfx, int inrate, byte *data) stepscale = (float)inrate / shm->speed; // this is usually 0.5, 1, or 2 + srclength = sc->length << sc->stereo; + outcount = sc->length / stepscale; sc->length = outcount; if (sc->loopstart != -1) @@ -62,6 +64,7 @@ void ResampleSfx (sfx_t *sfx, int inrate, byte *data) if (stepscale == 1/* && inwidth == 1*/ && sc->width == 1) { // fast special case + /* // LordHavoc: I do not serve the readability gods... int *indata, *outdata; int count4, count1; @@ -75,27 +78,18 @@ void ResampleSfx (sfx_t *sfx, int inrate, byte *data) ((short*)outdata)[0] = ((short*)indata)[0] ^ 0x8080; if (count1 & 1) ((char*)outdata)[2] = ((char*)indata)[2] ^ 0x80; - /* - if (sc->stereo) // LordHavoc: stereo sound support - { - for (i=0 ; i<(outcount<<1) ; i++) - ((signed char *)sc->data)[i] = (int)( (unsigned char)(data[i]) - 128); - } - else - { - for (i=0 ; idata)[i] = (int)( (unsigned char)(data[i]) - 128); - } */ + if (sc->stereo) // LordHavoc: stereo sound support + outcount *= 2; + for (i=0 ; idata)[i] = ((unsigned char *)data)[i] - 128; } else if (stepscale == 1/* && inwidth == 2*/ && sc->width == 2) // LordHavoc: quick case for 16bit { if (sc->stereo) // LordHavoc: stereo sound support - for (i=0 ; idata)[i] = LittleShort (((short *)data)[i]); - else - for (i=0 ; idata)[i] = LittleShort (((short *)data)[i]); + outcount *= 2; + for (i=0 ; idata)[i] = LittleShort (((short *)data)[i]); } else { @@ -113,10 +107,10 @@ void ResampleSfx (sfx_t *sfx, int inrate, byte *data) if (sc->stereo) // LordHavoc: stereo sound support { fracstep <<= 1; - for (i=0 ; idata, *in = (void *)data; + signed char *out = (void *)sc->data; + unsigned char *in = (void *)data; if (sc->stereo) // LordHavoc: stereo sound support { fracstep <<= 1; - for (i=0 ; iwidth == 2) { short *out = (void *)sc->data, *in = (void *)data; if (sc->stereo) // LordHavoc: stereo sound support { - for (i=0 ; i> 7) & ~1; - samplefrac += fracstep; - sample = (LittleShort (in[srcsample ]) * (256 - (samplefrac & 255)) + LittleShort (in[srcsample+2]) * (samplefrac & 255)) >> 8; + srcsample = (samplefrac >> 8) << 1; + a = in[srcsample ]; + if (srcsample+2 >= srclength) + b = 0; + else + b = in[srcsample+2]; + sample = (((b - a) * (samplefrac & 255)) >> 8) + a; *out++ = (short) sample; - sample = (LittleShort (in[srcsample+1]) * (256 - (samplefrac & 255)) + LittleShort (in[srcsample+3]) * (samplefrac & 255)) >> 8; + a = in[srcsample+1]; + if (srcsample+2 >= srclength) + b = 0; + else + b = in[srcsample+3]; + sample = (((b - a) * (samplefrac & 255)) >> 8) + a; *out++ = (short) sample; + samplefrac += fracstep; } } else @@ -175,25 +181,41 @@ void ResampleSfx (sfx_t *sfx, int inrate, byte *data) for (i=0 ; i> 8; - samplefrac += fracstep; - sample = (LittleShort (in[srcsample ]) * (256 - (samplefrac & 255)) + LittleShort (in[srcsample+1]) * (samplefrac & 255)) >> 8; + a = in[srcsample ]; + if (srcsample+1 >= srclength) + b = 0; + else + b = in[srcsample+1]; + sample = (((b - a) * (samplefrac & 255)) >> 8) + a; *out++ = (short) sample; + samplefrac += fracstep; } } } else { - signed char *out = (void *)sc->data, *in = (void *)data; + signed char *out = (void *)sc->data; + unsigned char *in = (void *)data; if (sc->stereo) // LordHavoc: stereo sound support { - for (i=0 ; i> 7) & ~1; - samplefrac += fracstep; - sample = ((((unsigned char) in[srcsample ] - 128) * (256 - (samplefrac & 255))) + (((unsigned char) in[srcsample+2] - 128) * (samplefrac & 255))) >> 8; + srcsample = (samplefrac >> 8) << 1; + a = (int) in[srcsample ] - 128; + if (srcsample+2 >= srclength) + b = 0; + else + b = (int) in[srcsample+2] - 128; + sample = (((b - a) * (samplefrac & 255)) >> 8) + a; *out++ = (signed char) sample; - sample = ((((unsigned char) in[srcsample+1] - 128) * (256 - (samplefrac & 255))) + (((unsigned char) in[srcsample+3] - 128) * (samplefrac & 255))) >> 8; + a = (int) in[srcsample+1] - 128; + if (srcsample+2 >= srclength) + b = 0; + else + b = (int) in[srcsample+3] - 128; + sample = (((b - a) * (samplefrac & 255)) >> 8) + a; *out++ = (signed char) sample; + samplefrac += fracstep; } } else @@ -201,14 +223,24 @@ void ResampleSfx (sfx_t *sfx, int inrate, byte *data) for (i=0 ; i> 8; - samplefrac += fracstep; - sample = ((((unsigned char) in[srcsample ] - 128) * (256 - (samplefrac & 255))) + (((unsigned char) in[srcsample+1] - 128) * (samplefrac & 255))) >> 8; + a = (int) in[srcsample ] - 128; + if (srcsample+1 >= srclength) + b = 0; + else + b = (int) in[srcsample+1] - 128; + sample = (((b - a) * (samplefrac & 255)) >> 8) + a; *out++ = (signed char) sample; + samplefrac += fracstep; } } } } } + + // LordHavoc: use this for testing if it ever becomes useful again +#if 0 + COM_WriteFile (va("sound/%s.pcm", name), sc->data, (sc->length << sc->stereo) * sc->width); +#endif } //============================================================================= @@ -281,7 +313,7 @@ sfxcache_t *S_LoadSound (sfx_t *s) sc->width = info.width; sc->stereo = info.channels == 2; - ResampleSfx (s, sc->speed, data + info.dataofs); + ResampleSfx (s, sc->speed, data + info.dataofs, s->name); qfree(data); return sc; diff --git a/snd_mix.c b/snd_mix.c index 1da0fcf6..7444857f 100644 --- a/snd_mix.c +++ b/snd_mix.c @@ -27,7 +27,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define DWORD unsigned long #endif -#define PAINTBUFFER_SIZE 512 +// LordHavoc: was 512, expanded to 2048 +#define PAINTBUFFER_SIZE 2048 portable_samplepair_t paintbuffer[PAINTBUFFER_SIZE]; int snd_scaletable[32][256]; int *snd_p, snd_linear_count, snd_vol; @@ -46,20 +47,9 @@ void Snd_WriteLinearBlastStereo16 (void) for (i=0 ; i>8; - if (val > 0x7fff) - snd_out[i] = 0x7fff; - else if (val < (short)0x8000) - snd_out[i] = (short)0x8000; - else - snd_out[i] = val; - - val = (snd_p[i]*snd_vol)>>8; - if (val > 0x7fff) - snd_out[i+1] = 0x7fff; - else if (val < (short)0x8000) - snd_out[i+1] = (short)0x8000; - else - snd_out[i+1] = val; + snd_out[i ] = bound(-32768, val, 32767); + val = (snd_p[i ]*snd_vol)>>8; + snd_out[i+1] = bound(-32768, val, 32767); } } else @@ -67,20 +57,9 @@ void Snd_WriteLinearBlastStereo16 (void) for (i=0 ; i>8; - if (val > 0x7fff) - snd_out[i] = 0x7fff; - else if (val < (short)0x8000) - snd_out[i] = (short)0x8000; - else - snd_out[i] = val; - + snd_out[i] = bound(-32768, val, 32767); val = (snd_p[i+1]*snd_vol)>>8; - if (val > 0x7fff) - snd_out[i+1] = 0x7fff; - else if (val < (short)0x8000) - snd_out[i+1] = (short)0x8000; - else - snd_out[i+1] = val; + snd_out[i+1] = bound(-32768, val, 32767); } } } @@ -107,8 +86,7 @@ void S_TransferStereo16 (int endtime) { reps = 0; - while ((hresult = pDSBuf->lpVtbl->Lock(pDSBuf, 0, gSndBufSize, &pbuf, &dwSize, - &pbuf2, &dwSize2, 0)) != DS_OK) + while ((hresult = pDSBuf->lpVtbl->Lock(pDSBuf, 0, gSndBufSize, &pbuf, &dwSize, &pbuf2, &dwSize2, 0)) != DS_OK) { if (hresult != DSERR_BUFFERLOST) { @@ -194,8 +172,7 @@ void S_TransferPaintBuffer(int endtime) { reps = 0; - while ((hresult = pDSBuf->lpVtbl->Lock(pDSBuf, 0, gSndBufSize, &pbuf, &dwSize, - &pbuf2,&dwSize2, 0)) != DS_OK) + while ((hresult = pDSBuf->lpVtbl->Lock(pDSBuf, 0, gSndBufSize, &pbuf, &dwSize, &pbuf2,&dwSize2, 0)) != DS_OK) { if (hresult != DSERR_BUFFERLOST) { @@ -226,12 +203,8 @@ void S_TransferPaintBuffer(int endtime) while (count--) { val = (*p * snd_vol) >> 8; + out[out_idx] = bound(-32768, val, 32767); p+= step; - if (val > 0x7fff) - val = 0x7fff; - else if (val < (short)0x8000) - val = (short)0x8000; - out[out_idx] = val; out_idx = (out_idx + 1) & out_mask; } } @@ -240,19 +213,16 @@ void S_TransferPaintBuffer(int endtime) unsigned char *out = (unsigned char *) pbuf; while (count--) { - val = (*p * snd_vol) >> 8; + val = ((*p * snd_vol) >> 16) + 128; + out[out_idx] = bound(0, val, 255); p+= step; - if (val > 0x7fff) - val = 0x7fff; - else if (val < (short)0x8000) - val = (short)0x8000; - out[out_idx] = (val>>8) + 128; out_idx = (out_idx + 1) & out_mask; } } #ifdef _WIN32 - if (pDSBuf) { + if (pDSBuf) + { DWORD dwNewpos, dwWrite; int il = paintedtime; int ir = endtime - paintedtime; @@ -291,15 +261,15 @@ void S_PaintChannels(int endtime) while (paintedtime < endtime) { - // if paintbuffer is smaller than DMA buffer + // if paintbuffer is smaller than DMA buffer end = endtime; if (endtime - paintedtime > PAINTBUFFER_SIZE) end = paintedtime + PAINTBUFFER_SIZE; - // clear the paint buffer + // clear the paint buffer memset(paintbuffer, 0, (end - paintedtime) * sizeof(portable_samplepair_t)); - // paint in the channels. + // paint in the channels. ch = channels; for (i=0; iend < end) count = ch->end - ltime; else @@ -330,7 +301,7 @@ void S_PaintChannels(int endtime) ltime += count; } - // if at end of loop, restart + // if at end of loop, restart if (ltime >= ch->end) { if (sc->loopstart >= 0) @@ -339,7 +310,8 @@ void S_PaintChannels(int endtime) ch->end = ltime + sc->length - ch->pos; } else - { // channel just stopped + { + // channel just stopped ch->sfx = NULL; break; } @@ -348,7 +320,7 @@ void S_PaintChannels(int endtime) } - // transfer out according to DMA format + // transfer out according to DMA format S_TransferPaintBuffer(end); paintedtime = end; } @@ -375,11 +347,12 @@ void SND_PaintChannelFrom8 (channel_t *ch, sfxcache_t *sc, int count) ch->leftvol = 255; if (ch->rightvol > 255) ch->rightvol = 255; - + lscale = snd_scaletable[ch->leftvol >> 3]; rscale = snd_scaletable[ch->rightvol >> 3]; - if (sc->stereo) // LordHavoc: stereo sound support, and optimizations + if (sc->stereo) { + // LordHavoc: stereo sound support, and optimizations sfx = (unsigned char *)sc->data + ch->pos * 2; for (i=0 ; ileftvol; rightvol = ch->rightvol; - if (sc->stereo) // LordHavoc: stereo sound support, and optimizations + if (sc->stereo) { + // LordHavoc: stereo sound support, and optimizations sfx = (signed short *)sc->data + ch->pos * 2; for (i=0 ; i> 8); - paintbuffer[i].right += (short) ((int) (*sfx++ * rightvol) >> 8); + paintbuffer[i].left += (*sfx++ * leftvol) >> 8; + paintbuffer[i].right += (*sfx++ * rightvol) >> 8; } } else @@ -429,8 +403,8 @@ void SND_PaintChannelFrom16 (channel_t *ch, sfxcache_t *sc, int count) for (i=0 ; i> 8); - paintbuffer[i].right += (short) ((int) (*sfx++ * rightvol) >> 8); + paintbuffer[i].left += (*sfx * leftvol) >> 8; + paintbuffer[i].right += (*sfx++ * rightvol) >> 8; } } diff --git a/snd_win.c b/snd_win.c index d24b6f2d..1a725ebb 100644 --- a/snd_win.c +++ b/snd_win.c @@ -364,7 +364,7 @@ sndinitstat SNDDMA_InitDirect (void) if (snd_firsttime) Con_SafePrintf(" %d channel(s)\n" " %d bits/sample\n" - " %d bytes/sec\n", + " %d samples/sec\n", shm->channels, shm->samplebits, shm->speed); gSndBufSize = dsbcaps.dwBufferBytes; diff --git a/sv_main.c b/sv_main.c index 9a3c37ed..330a9ba7 100644 --- a/sv_main.c +++ b/sv_main.c @@ -102,6 +102,41 @@ void SV_StartParticle (vec3_t org, vec3_t dir, int color, int count) MSG_WriteByte (&sv.datagram, color); } +/* +================== +SV_StartEffect + +Make sure the event gets sent to all clients +================== +*/ +void SV_StartEffect (vec3_t org, int modelindex, int startframe, int framecount, int framerate) +{ + if (sv.datagram.cursize > MAX_DATAGRAM-18) + return; + if (modelindex >= 256) + { + MSG_WriteByte (&sv.datagram, svc_effect2); + MSG_WriteFloatCoord (&sv.datagram, org[0]); + MSG_WriteFloatCoord (&sv.datagram, org[1]); + MSG_WriteFloatCoord (&sv.datagram, org[2]); + MSG_WriteShort (&sv.datagram, modelindex); + MSG_WriteByte (&sv.datagram, startframe); + MSG_WriteByte (&sv.datagram, framecount); + MSG_WriteByte (&sv.datagram, framerate); + } + else + { + MSG_WriteByte (&sv.datagram, svc_effect); + MSG_WriteFloatCoord (&sv.datagram, org[0]); + MSG_WriteFloatCoord (&sv.datagram, org[1]); + MSG_WriteFloatCoord (&sv.datagram, org[2]); + MSG_WriteByte (&sv.datagram, modelindex); + MSG_WriteByte (&sv.datagram, startframe); + MSG_WriteByte (&sv.datagram, framecount); + MSG_WriteByte (&sv.datagram, framerate); + } +} + /* ================== SV_StartSound @@ -110,7 +145,7 @@ Each entity can have eight independant sound sources, like voice, weapon, feet, etc. Channel 0 is an auto-allocate channel, the others override anything -allready running on that entity/channel pair. +already running on that entity/channel pair. An attenuation of 0 will play full volume everywhere in the level. Larger attenuations will drop off. (max 4 attenuation) @@ -159,15 +194,21 @@ void SV_StartSound (edict_t *entity, int channel, char *sample, int volume, if (attenuation != DEFAULT_SOUND_PACKET_ATTENUATION) field_mask |= SND_ATTENUATION; -// directed messages go only to the entity the are targeted on - MSG_WriteByte (&sv.datagram, svc_sound); +// directed messages go only to the entity they are targeted on + if (sound_num >= 256) + MSG_WriteByte (&sv.datagram, svc_sound2); + else + MSG_WriteByte (&sv.datagram, svc_sound); MSG_WriteByte (&sv.datagram, field_mask); if (field_mask & SND_VOLUME) MSG_WriteByte (&sv.datagram, volume); if (field_mask & SND_ATTENUATION) MSG_WriteByte (&sv.datagram, attenuation*64); MSG_WriteShort (&sv.datagram, channel); - MSG_WriteByte (&sv.datagram, sound_num); + if (sound_num >= 256) + MSG_WriteShort (&sv.datagram, sound_num); + else + MSG_WriteByte (&sv.datagram, sound_num); for (i=0 ; i<3 ; i++) MSG_WriteFloatCoord (&sv.datagram, entity->v.origin[i]+0.5*(entity->v.mins[i]+entity->v.maxs[i])); } @@ -547,7 +588,7 @@ void SV_WriteEntitiesToClient (client_t *client, edict_t *clent, sizebuf_t *msg) dodelta = false; if ((int)ent->v.effects & EF_DELTA) - dodelta = sv.time < client->nextfullupdate[e]; // every half second a full update is forced + dodelta = realtime < client->nextfullupdate[e]; // every half second a full update is forced if (dodelta) { @@ -556,7 +597,7 @@ void SV_WriteEntitiesToClient (client_t *client, edict_t *clent, sizebuf_t *msg) } else { - client->nextfullupdate[e] = sv.time + 0.5; + client->nextfullupdate[e] = realtime + 0.5; baseline = &ent->baseline; } @@ -619,17 +660,20 @@ void SV_WriteEntitiesToClient (client_t *client, edict_t *clent, sizebuf_t *msg) } // LordHavoc: old stuff, but rewritten to have more exact tolerances - if ((int)(origin[0]*8.0) != (int)(baseline->origin[0]*8.0)) bits |= U_ORIGIN1; - if ((int)(origin[1]*8.0) != (int)(baseline->origin[1]*8.0)) bits |= U_ORIGIN2; - if ((int)(origin[2]*8.0) != (int)(baseline->origin[2]*8.0)) bits |= U_ORIGIN3; +// if ((int)(origin[0]*8.0) != (int)(baseline->origin[0]*8.0)) bits |= U_ORIGIN1; +// if ((int)(origin[1]*8.0) != (int)(baseline->origin[1]*8.0)) bits |= U_ORIGIN2; +// if ((int)(origin[2]*8.0) != (int)(baseline->origin[2]*8.0)) bits |= U_ORIGIN3; + if (origin[0] != baseline->origin[0]) bits |= U_ORIGIN1; + if (origin[1] != baseline->origin[1]) bits |= U_ORIGIN2; + if (origin[2] != baseline->origin[2]) bits |= U_ORIGIN3; if ((int)(angles[0]*(256.0/360.0)) != (int)(baseline->angles[0]*(256.0/360.0))) bits |= U_ANGLE1; if ((int)(angles[1]*(256.0/360.0)) != (int)(baseline->angles[1]*(256.0/360.0))) bits |= U_ANGLE2; if ((int)(angles[2]*(256.0/360.0)) != (int)(baseline->angles[2]*(256.0/360.0))) bits |= U_ANGLE3; - if (baseline->colormap != (int) ent->v.colormap) bits |= U_COLORMAP; - if (baseline->skin != (int) ent->v.skin) bits |= U_SKIN; + if (baseline->colormap != (byte) ent->v.colormap) bits |= U_COLORMAP; + if (baseline->skin != (byte) ent->v.skin) bits |= U_SKIN; if ((baseline->frame & 0x00FF) != ((int) ent->v.frame & 0x00FF)) bits |= U_FRAME; if ((baseline->effects & 0x00FF) != ((int) ent->v.effects & 0x00FF)) bits |= U_EFFECTS; - if (baseline->modelindex != (int) ent->v.modelindex) bits |= U_MODEL; + if (baseline->modelindex != (byte) ent->v.modelindex) bits |= U_MODEL; // LordHavoc: new stuff if (baseline->alpha != alpha) bits |= U_ALPHA; @@ -639,6 +683,7 @@ void SV_WriteEntitiesToClient (client_t *client, edict_t *clent, sizebuf_t *msg) if (baseline->glowcolor != glowcolor) bits |= U_GLOWCOLOR; if (baseline->colormod != colormod) bits |= U_COLORMOD; if (((int) baseline->frame & 0xFF00) != ((int) ent->v.frame & 0xFF00)) bits |= U_FRAME2; + if (((int) baseline->frame & 0xFF00) != ((int) ent->v.modelindex & 0xFF00)) bits |= U_MODEL2; // update delta baseline VectorCopy(ent->v.origin, ent->deltabaseline.origin); @@ -697,6 +742,7 @@ void SV_WriteEntitiesToClient (client_t *client, edict_t *clent, sizebuf_t *msg) if (bits & U_GLOWCOLOR) MSG_WriteByte(msg, glowcolor); if (bits & U_COLORMOD) MSG_WriteByte(msg, colormod); if (bits & U_FRAME2) MSG_WriteByte(msg, (int)ent->v.frame >> 8); + if (bits & U_MODEL2) MSG_WriteByte(msg, (int)ent->v.modelindex >> 8); } } @@ -732,6 +778,7 @@ void SV_WriteClientdataToMessage (edict_t *ent, sizebuf_t *msg) edict_t *other; int items; eval_t *val; + vec3_t punchvector; // // send a damage message @@ -788,10 +835,17 @@ void SV_WriteClientdataToMessage (edict_t *ent, sizebuf_t *msg) if ( ent->v.waterlevel >= 2) bits |= SU_INWATER; + // dpprotocol + VectorClear(punchvector); + if ((val = GETEDICTFIELDVALUE(ent, eval_punchvector))) + VectorCopy(val->vector, punchvector); + for (i=0 ; i<3 ; i++) { if (ent->v.punchangle[i]) bits |= (SU_PUNCH1<v.velocity[i]) bits |= (SU_VELOCITY1<v.weapon) bits |= SU_WEAPON; + if (bits >= 65536) + bits |= SU_EXTEND1; + if (bits >= 16777216) + bits |= SU_EXTEND2; + // send the data MSG_WriteByte (msg, svc_clientdata); MSG_WriteShort (msg, bits); + if (bits & SU_EXTEND1) + MSG_WriteByte(msg, bits >> 16); + if (bits & SU_EXTEND2) + MSG_WriteByte(msg, bits >> 24); if (bits & SU_VIEWHEIGHT) MSG_WriteChar (msg, ent->v.view_ofs[2]); @@ -819,7 +882,9 @@ void SV_WriteClientdataToMessage (edict_t *ent, sizebuf_t *msg) for (i=0 ; i<3 ; i++) { if (bits & (SU_PUNCH1<v.punchangle[i]); + MSG_WritePreciseAngle(msg, ent->v.punchangle[i]); // dpprotocol + if (bits & (SU_PUNCHVEC1<v.velocity[i]/16); } @@ -1324,7 +1389,7 @@ void SV_SpawnServer (char *server) sv.state = ss_active; // run two frames to allow everything to settle - host_frametime = 0.1; + sv.frametime = pr_global_struct->frametime = host_frametime = 0.1; SV_Physics (); SV_Physics (); diff --git a/sv_phys.c b/sv_phys.c index afe020c9..7c41965a 100644 --- a/sv_phys.c +++ b/sv_phys.c @@ -137,7 +137,7 @@ qboolean SV_RunThink (edict_t *ent) float thinktime; thinktime = ent->v.nextthink; - if (thinktime <= 0 || thinktime > sv.time + host_frametime) + if (thinktime <= 0 || thinktime > sv.time + sv.frametime) return true; if (thinktime < sv.time) @@ -392,7 +392,7 @@ void SV_AddGravity (edict_t *ent) ent_gravity = val->_float; else ent_gravity = 1.0; - ent->v.velocity[2] -= ent_gravity * sv_gravity.value * host_frametime; + ent->v.velocity[2] -= ent_gravity * sv_gravity.value * sv.frametime; } @@ -754,14 +754,14 @@ void SV_Physics_Pusher (edict_t *ent) oldltime = ent->v.ltime; thinktime = ent->v.nextthink; - if (thinktime < ent->v.ltime + host_frametime) + if (thinktime < ent->v.ltime + sv.frametime) { movetime = thinktime - ent->v.ltime; if (movetime < 0) movetime = 0; } else - movetime = host_frametime; + movetime = sv.frametime; if (movetime) { @@ -886,11 +886,11 @@ SV_WallFriction */ void SV_WallFriction (edict_t *ent, trace_t *trace) { - vec3_t forward, right, up; + vec3_t forward; float d, i; vec3_t into, side; - AngleVectors (ent->v.v_angle, forward, right, up); + AngleVectors (ent->v.v_angle, forward, NULL, NULL); d = DotProduct (trace->plane.normal, forward); d += 0.5; @@ -993,7 +993,7 @@ void SV_WalkMove (edict_t *ent) VectorCopy (ent->v.origin, oldorg); VectorCopy (ent->v.velocity, oldvel); - clip = SV_FlyMove (ent, host_frametime, &steptrace); + clip = SV_FlyMove (ent, sv.frametime, &steptrace); if ( !(clip & 2) ) return; // move didn't block on a step @@ -1021,7 +1021,7 @@ void SV_WalkMove (edict_t *ent) VectorClear (upmove); VectorClear (downmove); upmove[2] = STEPSIZE; - downmove[2] = -STEPSIZE + oldvel[2]*host_frametime; + downmove[2] = -STEPSIZE + oldvel[2]*sv.frametime; // move up SV_PushEntity (ent, upmove); // FIXME: don't link? @@ -1030,7 +1030,7 @@ void SV_WalkMove (edict_t *ent) ent->v.velocity[0] = oldvel[0]; ent->v. velocity[1] = oldvel[1]; ent->v. velocity[2] = 0; - clip = SV_FlyMove (ent, host_frametime, &steptrace); + clip = SV_FlyMove (ent, sv.frametime, &steptrace); // check for stuckness, possibly due to the limited precision of floats // in the clipping hulls @@ -1121,14 +1121,14 @@ void SV_Physics_Client (edict_t *ent, int num) if (!SV_RunThink (ent)) return; SV_CheckWater (ent); - SV_FlyMove (ent, host_frametime, NULL); + SV_FlyMove (ent, sv.frametime, NULL); break; case MOVETYPE_NOCLIP: if (!SV_RunThink (ent)) return; SV_CheckWater (ent); - VectorMA (ent->v.origin, host_frametime, ent->v.velocity, ent->v.origin); + VectorMA (ent->v.origin, sv.frametime, ent->v.velocity, ent->v.origin); break; default: @@ -1221,8 +1221,8 @@ void SV_Physics_Noclip (edict_t *ent) if (!SV_RunThink (ent)) return; - VectorMA (ent->v.angles, host_frametime, ent->v.avelocity, ent->v.angles); - VectorMA (ent->v.origin, host_frametime, ent->v.velocity, ent->v.origin); + VectorMA (ent->v.angles, sv.frametime, ent->v.avelocity, ent->v.angles); + VectorMA (ent->v.origin, sv.frametime, ent->v.velocity, ent->v.origin); SV_LinkEdict (ent, false); } @@ -1301,10 +1301,10 @@ void SV_Physics_Toss (edict_t *ent) SV_AddGravity (ent); // move angles - VectorMA (ent->v.angles, host_frametime, ent->v.avelocity, ent->v.angles); + VectorMA (ent->v.angles, sv.frametime, ent->v.avelocity, ent->v.angles); // move origin - VectorScale (ent->v.velocity, host_frametime, move); + VectorScale (ent->v.velocity, sv.frametime, move); trace = SV_PushEntity (ent, move); if (trace.fraction == 1) return; @@ -1369,7 +1369,7 @@ void SV_Physics_Step (edict_t *ent) SV_AddGravity (ent); SV_CheckVelocity (ent); - SV_FlyMove (ent, host_frametime, NULL); + SV_FlyMove (ent, sv.frametime, NULL); SV_LinkEdict (ent, true); if ( (int)ent->v.flags & FL_ONGROUND ) // just hit ground @@ -1477,7 +1477,7 @@ void SV_Physics (void) PR_ExecuteProgram ((func_t)(EndFrameQC - pr_functions), ""); } - sv.time += host_frametime; + sv.time += sv.frametime; } @@ -1488,10 +1488,6 @@ trace_t SV_Trace_Toss (edict_t *ent, edict_t *ignore) trace_t trace; vec3_t move; vec3_t end; - double save_frametime; - - save_frametime = host_frametime; - host_frametime = 0.05; memcpy(&tempent, ent, sizeof(edict_t)); tent = &tempent; @@ -1500,8 +1496,8 @@ trace_t SV_Trace_Toss (edict_t *ent, edict_t *ignore) { SV_CheckVelocity (tent); SV_AddGravity (tent); - VectorMA (tent->v.angles, host_frametime, tent->v.avelocity, tent->v.angles); - VectorScale (tent->v.velocity, host_frametime, move); + VectorMA (tent->v.angles, 0.05, tent->v.avelocity, tent->v.angles); + VectorScale (tent->v.velocity, 0.05, move); VectorAdd (tent->v.origin, move, end); trace = SV_Move (tent->v.origin, tent->v.mins, tent->v.maxs, end, MOVE_NORMAL, tent); VectorCopy (trace.endpos, tent->v.origin); @@ -1510,6 +1506,6 @@ trace_t SV_Trace_Toss (edict_t *ent, edict_t *ignore) if (trace.ent != ignore) break; } - host_frametime = save_frametime; + trace.fraction = 0; // not relevant return trace; } diff --git a/sv_user.c b/sv_user.c index e76f78f9..496d0c02 100644 --- a/sv_user.c +++ b/sv_user.c @@ -149,7 +149,7 @@ void SV_UserFriction (void) // apply friction control = speed < sv_stopspeed.value ? sv_stopspeed.value : speed; - newspeed = speed - host_frametime*control*friction; + newspeed = speed - sv.frametime*control*friction; if (newspeed < 0) newspeed = 0; @@ -181,7 +181,7 @@ void SV_Accelerate (vec3_t wishvel) VectorSubtract (wishvel, velocity, pushvec); addspeed = VectorNormalize (pushvec); - accelspeed = sv_accelerate.value*host_frametime*addspeed; + accelspeed = sv_accelerate.value*sv.frametime*addspeed; if (accelspeed > addspeed) accelspeed = addspeed; @@ -198,7 +198,7 @@ void SV_Accelerate (void) addspeed = wishspeed - currentspeed; if (addspeed <= 0) return; - accelspeed = sv_accelerate.value*host_frametime*wishspeed; + accelspeed = sv_accelerate.value*sv.frametime*wishspeed; if (accelspeed > addspeed) accelspeed = addspeed; @@ -218,8 +218,8 @@ void SV_AirAccelerate (vec3_t wishveloc) addspeed = wishspd - currentspeed; if (addspeed <= 0) return; -// accelspeed = sv_accelerate.value * host_frametime; - accelspeed = sv_accelerate.value*wishspeed * host_frametime; +// accelspeed = sv_accelerate.value * sv.frametime; + accelspeed = sv_accelerate.value*wishspeed * sv.frametime; if (accelspeed > addspeed) accelspeed = addspeed; @@ -231,13 +231,24 @@ void SV_AirAccelerate (vec3_t wishveloc) void DropPunchAngle (void) { float len; + eval_t *val; len = VectorNormalizeLength (sv_player->v.punchangle); - len -= 10*host_frametime; + len -= 10*sv.frametime; if (len < 0) len = 0; VectorScale (sv_player->v.punchangle, len, sv_player->v.punchangle); + + if ((val = GETEDICTFIELDVALUE(sv_player, eval_punchvector))) + { + len = VectorNormalizeLength (val->vector); + + len -= 20*sv.frametime; + if (len < 0) + len = 0; + VectorScale (val->vector, len, val->vector); + } } /* @@ -279,7 +290,7 @@ void SV_WaterMove (void) speed = Length (velocity); if (speed) { - newspeed = speed - host_frametime * speed * sv_friction.value; + newspeed = speed - sv.frametime * speed * sv_friction.value; if (newspeed < 0) newspeed = 0; VectorScale (velocity, newspeed/speed, velocity); @@ -298,7 +309,7 @@ void SV_WaterMove (void) return; VectorNormalize (wishvel); - accelspeed = sv_accelerate.value * wishspeed * host_frametime; + accelspeed = sv_accelerate.value * wishspeed * sv.frametime; if (accelspeed > addspeed) accelspeed = addspeed; @@ -429,8 +440,7 @@ void SV_ClientThink (void) // // walk // - if ( (sv_player->v.waterlevel >= 2) - && (sv_player->v.movetype != MOVETYPE_NOCLIP) ) + if ( (sv_player->v.waterlevel >= 2) && (sv_player->v.movetype != MOVETYPE_NOCLIP) ) { SV_WaterMove (); return; diff --git a/sys_win.c b/sys_win.c index 8c8a595c..90b04ed8 100644 --- a/sys_win.c +++ b/sys_win.c @@ -187,21 +187,15 @@ int Sys_FileWrite (int handle, void *data, int count) int Sys_FileTime (char *path) { FILE *f; - int retval; - + f = fopen(path, "rb"); - if (f) { fclose(f); - retval = 1; - } - else - { - retval = -1; + return 1; } - return retval; + return -1; } void Sys_mkdir (char *path) diff --git a/vid.h b/vid.h index b177ed8b..f0f49ab8 100644 --- a/vid.h +++ b/vid.h @@ -45,15 +45,10 @@ extern viddef_t vid; // global video state extern void (*vid_menudrawfn)(void); extern void (*vid_menukeyfn)(int key); -extern qboolean isG200; -extern qboolean isRagePro; -extern qboolean gl_mtexable; -extern qboolean gl_arrays; - void GL_Init (void); void VID_CheckMultitexture(); -void VID_CheckVertexArrays(); +void VID_CheckCVA(); void VID_Init (); // Called at startup diff --git a/vid_3dfxsvga.c b/vid_3dfxsvga.c index f326228b..601387c1 100644 --- a/vid_3dfxsvga.c +++ b/vid_3dfxsvga.c @@ -46,9 +46,6 @@ #include -unsigned d_8to24table[256]; -unsigned char d_15to8table[65536]; - cvar_t vid_mode = {"vid_mode","0",false}; viddef_t vid; // global video state @@ -62,8 +59,6 @@ int VID_options_items = 0; /*-----------------------------------------------------------------------*/ -int texture_extension_number = 1; - float gldepthmin, gldepthmax; const char *gl_vendor; @@ -71,17 +66,6 @@ const char *gl_renderer; const char *gl_version; const char *gl_extensions; -void (*qglMTexCoord2f) (GLenum, GLfloat, GLfloat); -void (*qglSelectTexture) (GLenum); - -int gl_mtex_enum = 0; - -// LordHavoc: in GLX these are never set, simply provided to make the rest of the code work -qboolean isG200 = false; -qboolean isRagePro = false; -qboolean gl_mtexable = false; -qboolean gl_arrays = false; - /*-----------------------------------------------------------------------*/ void D_BeginDirectRect (int x, int y, byte *pbitmap, int width, int height) { @@ -122,11 +106,6 @@ void InitSig(void) signal(SIGTERM, signal_handler); } -// LordHavoc: FIXME or something? -void VID_CheckVertexArrays() -{ -} - /* VID_CheckMultitexture @@ -165,7 +144,34 @@ void VID_CheckMultitexture() else Con_Printf ("none found\n"); dlclose(dlhand); - dlhand = NULL; + dlhand = NULL; +} + +void VID_CheckCVA(void) +{ + qglLockArraysEXT = NULL; + qglUnlockArraysEXT = NULL; + gl_supportslockarrays = false; + if (COM_CheckParm("-nocva")) + { + Con_Printf("...compiled vertex arrays disabled\n"); + return; + } + dlhand = dlopen (NULL, RTLD_LAZY); + if (dlhand == NULL) + { + Con_Printf("Unable to open symbol list for main program.\n"); + return; + } + if (strstr(gl_extensions, "GL_EXT_compiled_vertex_array")) + { + Con_Printf("...using compiled vertex arrays\n"); + qglLockArraysEXT = (void *) dlsym(dlhand, "glLockArraysEXT"); + qglUnlockArraysEXT = (void *) dlsym(dlhand, "glUnlockArraysEXT"); + gl_supportslockarrays = true; + } + dlclose(dlhand); + dlhand = NULL; } diff --git a/vid_glx.c b/vid_glx.c index c0af5028..cb0b1be4 100644 --- a/vid_glx.c +++ b/vid_glx.c @@ -49,9 +49,6 @@ static GLXContext ctx = NULL; #define X_MASK (KEY_MASK | MOUSE_MASK | VisibilityChangeMask | StructureNotifyMask ) -unsigned d_8to24table[256]; -unsigned char d_15to8table[65536]; - cvar_t vid_mode = {"vid_mode", "0", false}; cvar_t vid_fullscreen = {"vid_fullscreen", "1"}; @@ -83,8 +80,6 @@ static qboolean vidmode_active = false; /*-----------------------------------------------------------------------*/ -int texture_extension_number = 1; - float gldepthmin, gldepthmax; const char *gl_vendor; @@ -92,20 +87,11 @@ const char *gl_renderer; const char *gl_version; const char *gl_extensions; -void (*qglMTexCoord2f) (GLenum, GLfloat, GLfloat); -void (*qglSelectTexture) (GLenum); - //static float vid_gamma = 1.0; // LordHavoc: ARB multitexture support int gl_mtex_enum = 0; -// LordHavoc: in GLX these are never set, simply provided to make the rest of the code work -qboolean isG200 = false; -qboolean isRagePro = false; -qboolean gl_mtexable = false; -qboolean gl_arrays = false; - /*-----------------------------------------------------------------------*/ static int XLateKey(XKeyEvent *ev/*, qboolean modified*/) @@ -453,55 +439,6 @@ void InitSig(void) signal(SIGTERM, signal_handler); } -/* -void (*qglVertexPointer)(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr); -void (*qglColorPointer)(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr); -void (*qglTexCoordPointer)(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr); -void (*qglArrayElement)(GLint i); -void (*qglDrawElements)(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices); -void (*qglMTexCoord2f)(GLenum, GLfloat, GLfloat); -void (*qglSelectTexture)(GLenum); - -void VID_CheckVertexArrays (void) -{ - void *prjobj; - if (COM_CheckParm("-novertex")) - { - Con_Printf("...vertex array support disabled\n"); - return; - } - if ((prjobj = dlopen(NULL, RTLD_LAZY)) == NULL) - { - Con_Printf("Unable to open symbol list for main program.\n"); - return; - } - qglMTexCoord2fSGIS = (void *) dlsym(prjobj, "glMTexCoord2fSGIS"); - if ((qglArrayElement = (void *) dlsym(prjobj, "glArrayElement")) - && (qglColorPointer = (void *) dlsym(prjobj, "glColorPointer")) -// && (qglDrawArrays = (void *) dlsym(prjobj, "glDrawArrays")) - && (qglDrawElements = (void *) dlsym(prjobj, "glDrawElements")) -// && (qglInterleavedArrays = (void *) dlsym(prjobj, "glInterleavedArrays")) - && (qglTexCoordPointer = (void *) dlsym(prjobj, "glTexCoordPointer")) - && (qglVertexPointer = (void *) dlsym(prjobj, "glVertexPointer")) - ) - { - Con_Printf("...vertex array support detected\n"); - gl_arrays = true; - dlclose(prjobj); - return; - } - - Con_Printf("...vertex array support disabled (not detected - get a better driver)\n"); - dlclose(prjobj); -} -*/ - -// LordHavoc: require OpenGL 1.2.x -void VID_CheckVertexArrays (void) -{ - gl_arrays = true; -} - void VID_CheckMultitexture(void) { void *prjobj; @@ -535,11 +472,37 @@ void VID_CheckMultitexture(void) gl_mtexable = true; gl_mtex_enum = TEXTURE0_SGIS; } - if (!gl_mtexable) + else Con_Printf("...multitexture disabled (not detected)\n"); dlclose(prjobj); } +void VID_CheckCVA(void) +{ + void *prjobj; + qglLockArraysEXT = NULL; + qglUnlockArraysEXT = NULL; + gl_supportslockarrays = false; + if (COM_CheckParm("-nocva")) + { + Con_Printf("...compiled vertex arrays disabled\n"); + return; + } + if ((prjobj = dlopen(NULL, RTLD_LAZY)) == NULL) + { + Con_Printf("Unable to open symbol list for main program.\n"); + return; + } + if (strstr(gl_extensions, "GL_EXT_compiled_vertex_array")) + { + Con_Printf("...using compiled vertex arrays\n"); + qglLockArraysEXT = (void *) dlsym(prjobj, "glLockArraysEXT"); + qglUnlockArraysEXT = (void *) dlsym(prjobj, "glUnlockArraysEXT"); + gl_supportslockarrays = true; + } + dlclose(prjobj); +} + /* ================= GL_BeginRendering diff --git a/vid_shared.c b/vid_shared.c index 589c59dc..47ac0546 100644 --- a/vid_shared.c +++ b/vid_shared.c @@ -1,3 +1,17 @@ #include "quakedef.h" +// LordHavoc: these are only set in wgl +qboolean isG200 = false; // LordHavoc: the Matrox G200 can't do per pixel alpha, and it uses a D3D driver for GL... ugh... +qboolean isRagePro = false; // LordHavoc: the ATI Rage Pro has limitations with per pixel alpha (the color scaler does not apply to per pixel alpha images...), although not as bad as a G200. + +// LordHavoc: compiled vertex array support +qboolean gl_supportslockarrays = false; +// LordHavoc: ARB multitexture support +qboolean gl_mtexable = false; +int gl_mtex_enum = 0; + +void (GLAPIENTRY *qglMTexCoord2f) (GLenum, GLfloat, GLfloat); +void (GLAPIENTRY *qglSelectTexture) (GLenum); +void (GLAPIENTRY *qglLockArraysEXT) (GLint first, GLint count); +void (GLAPIENTRY *qglUnlockArraysEXT) (void); diff --git a/vid_wgl.c b/vid_wgl.c index 3ef91f20..fe9ec2cb 100644 --- a/vid_wgl.c +++ b/vid_wgl.c @@ -113,14 +113,6 @@ char *VID_GetModeDescription (int mode); void ClearAllStates (void); void VID_UpdateWindowStatus (void); -// LordHavoc: ARB multitexture support -int gl_mtex_enum = 0; - -qboolean isG200 = false; // LordHavoc: the Matrox G200 can't do per pixel alpha, and it uses a D3D driver for GL... ugh... -qboolean isRagePro = false; // LordHavoc: the ATI Rage Pro has limitations with per pixel alpha (the color scaler does not apply to per pixel alpha images...), although not as bad as a G200. -qboolean gl_mtexable = false; -qboolean gl_arrays = false; - //==================================== cvar_t vid_mode = {"vid_mode","0", false}; @@ -376,44 +368,11 @@ void VID_UpdateWindowStatus (void) //==================================== -void (GLAPIENTRY *qglVertexPointer)(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr); -void (GLAPIENTRY *qglColorPointer)(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr); -void (GLAPIENTRY *qglTexCoordPointer)(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr); -void (GLAPIENTRY *qglArrayElement)(GLint i); -void (GLAPIENTRY *qglDrawElements)(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices); -void (GLAPIENTRY *qglMTexCoord2f)(GLenum, GLfloat, GLfloat); -void (GLAPIENTRY *qglSelectTexture)(GLenum); - -void VID_CheckVertexArrays (void) -{ - if (COM_CheckParm("-novertex")) - { - Con_Printf("...vertex array support disabled\n"); - return; - } - if ((qglArrayElement = (void *) wglGetProcAddress("glArrayElement")) - && (qglColorPointer = (void *) wglGetProcAddress("glColorPointer")) -// && (qglDrawArrays = (void *) wglGetProcAddress("glDrawArrays")) - && (qglDrawElements = (void *) wglGetProcAddress("glDrawElements")) -// && (qglInterleavedArrays = (void *) wglGetProcAddress("glInterleavedArrays")) - && (qglTexCoordPointer = (void *) wglGetProcAddress("glTexCoordPointer")) - && (qglVertexPointer = (void *) wglGetProcAddress("glVertexPointer")) - ) - { - Con_Printf("...vertex array support detected\n"); - gl_arrays = true; - return; - } - - Con_Printf("...vertex array support disabled (not detected - get a better driver)\n"); -} - -int texture_extension_number = 1; - void VID_CheckMultitexture(void) { qglMTexCoord2f = NULL; qglSelectTexture = NULL; + gl_mtexable = false; // Check to see if multitexture is disabled if (COM_CheckParm("-nomtex")) { @@ -437,10 +396,29 @@ void VID_CheckMultitexture(void) gl_mtexable = true; gl_mtex_enum = TEXTURE0_SGIS; } - if (!gl_mtexable) + else Con_Printf("...multitexture disabled (not detected)\n"); } +void VID_CheckCVA(void) +{ + qglLockArraysEXT = NULL; + qglUnlockArraysEXT = NULL; + gl_supportslockarrays = false; + if (COM_CheckParm("-nocva")) + { + Con_Printf("...compiled vertex arrays disabled\n"); + return; + } + if (strstr(gl_extensions, "GL_EXT_compiled_vertex_array")) + { + Con_Printf("...using compiled vertex arrays\n"); + qglLockArraysEXT = (void *) wglGetProcAddress("glLockArraysEXT"); + qglUnlockArraysEXT = (void *) wglGetProcAddress("glUnlockArraysEXT"); + gl_supportslockarrays = true; + } +} + /* ================= GL_BeginRendering diff --git a/view.c b/view.c index bcff7fff..5eddbe63 100644 --- a/view.c +++ b/view.c @@ -41,6 +41,8 @@ cvar_t v_kicktime = {"v_kicktime", "0.5", false}; cvar_t v_kickroll = {"v_kickroll", "0.6", false}; cvar_t v_kickpitch = {"v_kickpitch", "0.6", false}; +cvar_t v_punch = {"v_punch", "1", false}; + cvar_t v_iyaw_cycle = {"v_iyaw_cycle", "2", false}; cvar_t v_iroll_cycle = {"v_iroll_cycle", "0.5", false}; cvar_t v_ipitch_cycle = {"v_ipitch_cycle", "1", false}; @@ -69,15 +71,14 @@ V_CalcRoll Used by view and sv_user =============== */ -vec3_t forward, right, up; - float V_CalcRoll (vec3_t angles, vec3_t velocity) { + vec3_t right; float sign; float side; float value; - AngleVectors (angles, forward, right, up); + AngleVectors (angles, NULL, right, NULL); side = DotProduct (velocity, right); sign = side < 0 ? -1 : 1; side = fabs(side); @@ -189,7 +190,7 @@ void V_DriftPitch (void) if ( fabs(cl.cmd.forwardmove) < cl_forwardspeed.value) cl.driftmove = 0; else - cl.driftmove += host_frametime; + cl.driftmove += cl.frametime; if ( cl.driftmove > v_centermove.value) { @@ -206,10 +207,10 @@ void V_DriftPitch (void) return; } - move = host_frametime * cl.pitchvel; - cl.pitchvel += host_frametime * v_centerspeed.value; + move = cl.frametime * cl.pitchvel; + cl.pitchvel += cl.frametime * v_centerspeed.value; -//Con_Printf ("move: %f (%f)\n", move, host_frametime); +//Con_Printf ("move: %f (%f)\n", move, cl.frametime); if (delta > 0) { @@ -262,7 +263,7 @@ void V_ParseDamage (void) int armor, blood; vec3_t from; int i; - vec3_t forward, right, up; + vec3_t forward, right; entity_t *ent; float side; float count; @@ -276,7 +277,7 @@ void V_ParseDamage (void) if (count < 10) count = 10; - cl.faceanimtime = cl.time + 0.2; // but sbar face into pain frame + cl.faceanimtime = cl.time + 0.2; // put sbar face into pain frame if (gl_polyblend.value) { @@ -314,7 +315,7 @@ void V_ParseDamage (void) VectorSubtract (from, ent->origin, from); VectorNormalize (from); - AngleVectors (ent->angles, forward, right, up); + AngleVectors (ent->angles, forward, right, NULL); side = DotProduct (from, right); v_dmg_roll = count*side*v_kickroll.value; @@ -567,6 +568,7 @@ CalcGunAngle */ void CalcGunAngle (void) { + /* float yaw, pitch, move; static float oldyaw = 0; static float oldpitch = 0; @@ -584,7 +586,7 @@ void CalcGunAngle (void) pitch = 10; if (pitch < -10) pitch = -10; - move = host_frametime*20; + move = cl.frametime*20; if (yaw > oldyaw) { if (oldyaw + move < yaw) @@ -612,6 +614,9 @@ void CalcGunAngle (void) cl.viewent.angles[YAW] = r_refdef.viewangles[YAW] + yaw; cl.viewent.angles[PITCH] = - (r_refdef.viewangles[PITCH] + pitch); + */ + cl.viewent.angles[YAW] = r_refdef.viewangles[YAW]; + cl.viewent.angles[PITCH] = -r_refdef.viewangles[PITCH]; cl.viewent.angles[ROLL] -= v_idlescale.value * sin(cl.time*v_iroll_cycle.value) * v_iroll_level.value; cl.viewent.angles[PITCH] -= v_idlescale.value * sin(cl.time*v_ipitch_cycle.value) * v_ipitch_level.value; @@ -679,7 +684,7 @@ void V_CalcViewRoll (void) { r_refdef.viewangles[ROLL] += v_dmg_time/v_kicktime.value*v_dmg_roll; r_refdef.viewangles[PITCH] += v_dmg_time/v_kicktime.value*v_dmg_pitch; - v_dmg_time -= host_frametime; + v_dmg_time -= cl.frametime; } if (cl.stats[STAT_HEALTH] <= 0) @@ -711,7 +716,7 @@ void V_CalcIntermissionRefdef (void) VectorCopy (ent->angles, r_refdef.viewangles); view->model = NULL; -// allways idle in intermission +// always idle in intermission old = v_idlescale.value; v_idlescale.value = 1; V_AddIdle (); @@ -729,7 +734,7 @@ void V_CalcRefdef (void) { entity_t *ent, *view; int i; - vec3_t forward, right, up; + vec3_t forward; vec3_t angles; float bob; static float oldz = 0; @@ -777,7 +782,7 @@ void V_CalcRefdef (void) angles[YAW] = ent->angles[YAW]; angles[ROLL] = ent->angles[ROLL]; - AngleVectors (angles, forward, right, up); + AngleVectors (angles, forward, NULL, NULL); V_BoundOffsets (); @@ -806,6 +811,7 @@ void V_CalcRefdef (void) // set up the refresh position if (!intimerefresh) + if (v_punch.value) { VectorAdd (r_refdef.viewangles, cl.punchangle, r_refdef.viewangles); } @@ -831,6 +837,9 @@ if (cl.onground && ent->origin[2] - oldz > 0) else oldz = ent->origin[2]; +// LordHavoc: origin view kick + VectorAdd(r_refdef.vieworg, cl.punchvector, r_refdef.vieworg); + if (chase_active.value) Chase_Update (); } @@ -900,6 +909,8 @@ void V_Init (void) Cvar_RegisterVariable (&v_kicktime); Cvar_RegisterVariable (&v_kickroll); Cvar_RegisterVariable (&v_kickpitch); + + Cvar_RegisterVariable (&v_punch); } diff --git a/world.c b/world.c index eea796c7..1c4b74bb 100644 --- a/world.c +++ b/world.c @@ -538,7 +538,19 @@ POINT TESTING IN HULLS =============================================================================== */ -// SV_HullPointContents moved to cpu_noasm.c +/* +================== +SV_HullPointContents + +================== +*/ +int SV_HullPointContents (hull_t *hull, int num, vec3_t p) +{ + while (num >= 0) + num = hull->clipnodes[num].children[(hull->planes[hull->clipnodes[num].planenum].type < 3 ? p[hull->planes[hull->clipnodes[num].planenum].type] : DotProduct (hull->planes[hull->clipnodes[num].planenum].normal, p)) < hull->planes[hull->clipnodes[num].planenum].dist]; + + return num; +} /* ============ diff --git a/zone.c b/zone.c index e4884467..556c7094 100644 --- a/zone.c +++ b/zone.c @@ -825,7 +825,7 @@ void *Cache_Alloc (cache_user_t *c, int size, char *name) cache_system_t *cs; if (c->data) - Sys_Error ("Cache_Alloc: allready allocated"); + Sys_Error ("Cache_Alloc: already allocated"); if (size <= 0) Sys_Error ("Cache_Alloc: size %i", size); -- 2.39.2