try to fix null framestates issue causing crashes from pmove/solid_bsp code.

some tweaks to try to make webgl more robust.
added r_max_gpu_bones cvar. defaults to 0 in webgl for now (64 otherwise).
fixed gles2+skeletal issue that was breaking webgl (note r_max_gpu_bones needs to be set to 32 or something for it to actually use glsl bones with webgl).
sound rates now internally use decimals instead of percents. because meh.
allow PEXT2_MAXPLAYERS and angle deltas in nq.

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5052 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2017-01-29 13:10:53 +00:00
parent ae644d60ef
commit 4fcd615308
39 changed files with 314 additions and 259 deletions

View file

@ -756,7 +756,7 @@ static qintptr_t CG_SystemCalls(void *offset, quintptr_t mask, qintptr_t fn, con
mins = vec3_origin;
if (!maxs)
maxs = vec3_origin;
mod->funcs.NativeTrace(mod, 0, 0, NULL, start, end, mins, maxs, fn==CG_CM_CAPSULETRACE, brushmask, &tr);
mod->funcs.NativeTrace(mod, 0, NULLFRAMESTATE, NULL, start, end, mins, maxs, fn==CG_CM_CAPSULETRACE, brushmask, &tr);
results->allsolid = tr.allsolid;
results->contents = tr.contents;
results->fraction = tr.fraction;

View file

@ -4521,21 +4521,21 @@ CL_ParseStartSoundPacket
*/
void CLQW_ParseStartSoundPacket(void)
{
vec3_t pos;
int channel, ent;
int sound_num;
int volume;
float attenuation;
int i;
vec3_t pos;
int channel, ent;
int sound_num;
int volume;
float attenuation;
int i;
channel = MSG_ReadShort();
channel = MSG_ReadShort();
if (channel & QWSND_VOLUME)
if (channel & QWSND_VOLUME)
volume = MSG_ReadByte ();
else
volume = DEFAULT_SOUND_PACKET_VOLUME;
if (channel & QWSND_ATTENUATION)
if (channel & QWSND_ATTENUATION)
attenuation = MSG_ReadByte () / 64.0;
else
attenuation = DEFAULT_SOUND_PACKET_ATTENUATION;
@ -4552,7 +4552,7 @@ void CLQW_ParseStartSoundPacket(void)
Host_EndGame ("CL_ParseStartSoundPacket: ent = %i", ent);
#ifdef PEXT_CSQC
if (!CSQC_StartSound(ent, channel, cl.sound_name[sound_num], pos, volume/255.0, attenuation, 100, 0, 0))
if (!CSQC_StartSound(ent, channel, cl.sound_name[sound_num], pos, volume/255.0, attenuation, 1, 0, 0))
#endif
{
if (!sound_num)
@ -4677,7 +4677,7 @@ void CLNQ_ParseStartSoundPacket(void)
int field_mask;
float attenuation;
int i;
int pitchadj;
float pitchadj;
float timeofs;
unsigned int flags;
@ -4697,9 +4697,9 @@ void CLNQ_ParseStartSoundPacket(void)
attenuation = DEFAULT_SOUND_PACKET_ATTENUATION;
if (field_mask & FTESND_PITCHADJ)
pitchadj = MSG_ReadByte();
pitchadj = MSG_ReadByte()/100.0;
else
pitchadj = 100;
pitchadj = 1;
if (field_mask & FTESND_TIMEOFS)
timeofs = MSG_ReadShort() / 1000.0;
@ -4715,6 +4715,9 @@ void CLNQ_ParseStartSoundPacket(void)
else
VectorClear(vel);
if (field_mask & DPSND_SPEEDUSHORT4000)
pitchadj = (unsigned short)MSG_ReadShort() / 4000.0;
flags = field_mask>>8;
flags &= CF_FORCELOOP | CF_NOREVERB | CF_FOLLOW;
@ -7850,6 +7853,12 @@ void CLNQ_ParseServerMessage (void)
CL_SetStatNumeric (destsplit, i, f, f);
}
break;
case svcfte_setangledelta:
for (i=0 ; i<3 ; i++)
cl.playerview[destsplit].viewangles[i] += MSG_ReadAngle16 ();
VectorCopy (cl.playerview[destsplit].viewangles, cl.playerview[destsplit].simangles);
VectorCopy (cl.playerview[destsplit].viewangles, cl.playerview[destsplit].intermissionangles);
break;
case svc_setangle:
{
inframe_t *inf = &cl.inframes[cls.netchan.incoming_sequence&UPDATE_MASK];

View file

@ -170,7 +170,7 @@ q2trace_t VARGS CLQ2_PMTrace (vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end
trace_t t;
// check against world
cl.worldmodel->funcs.NativeTrace(cl.worldmodel, 0, 0, NULL, start, end, mins, maxs, false, MASK_PLAYERSOLID, &t);
cl.worldmodel->funcs.NativeTrace(cl.worldmodel, 0, NULLFRAMESTATE, NULL, start, end, mins, maxs, false, MASK_PLAYERSOLID, &t);
if (t.fraction < 1.0)
t.ent = (struct edict_s *)1;

View file

@ -1317,7 +1317,7 @@ void SCR_CrosshairPosition(playerview_t *pview, float *x, float *y)
memset(&tr, 0, sizeof(tr));
tr.fraction = 1;
cl.worldmodel->funcs.NativeTrace(cl.worldmodel, 0, 0, NULL, start, end, vec3_origin, vec3_origin, false, MASK_WORLDSOLID, &tr);
cl.worldmodel->funcs.NativeTrace(cl.worldmodel, 0, NULLFRAMESTATE, NULL, start, end, vec3_origin, vec3_origin, false, MASK_WORLDSOLID, &tr);
start[2]-=16;
if (tr.fraction != 1)
{

View file

@ -1075,8 +1075,11 @@ void CL_ParseTEnt (void)
case TENQ_BEAM:
type = TEQW_BEAM;
break;
case TENQ_EXPLOSION_SPRITE:
type = TE_EXPLOSION;
break;
case TE_EXPLOSION:
type = TEQW_EXPLOSIONNOSPRITE;
type = TEQW_EXPLOSION_NOSPRITE;
break;
case TE_GUNSHOT:
type = TE_GUNSHOT_NQCOMPAT;
@ -1337,7 +1340,7 @@ void CL_ParseTEnt (void)
ex->endalpha = ex->startalpha; //don't fade out
}
break;
case TEQW_EXPLOSIONNOSPRITE: //nq-style, no sprite
case TEQW_EXPLOSION_NOSPRITE: //nq-style, no sprite
case TE_EXPLOSION: //qw-style, with (optional) sprite
// particles
pos[0] = MSG_ReadCoord ();

View file

@ -2315,7 +2315,7 @@ void CLQ2_AddEntities (void)
AngleVectors(r_refdef.viewangles, axis[0], axis[1], axis[2]);
VectorMA(r_refdef.vieworg, -chase_back.value, axis[0], camorg);
VectorMA(camorg, -chase_up.value, pv->gravitydir, camorg);
// if (cl.worldmodel && cl.worldmodel->funcs.NativeTrace(cl.worldmodel, 0, 0, NULL, r_refdef.vieworg, camorg, vec3_origin, vec3_origin, true, MASK_WORLDSOLID, &tr))
// if (cl.worldmodel && cl.worldmodel->funcs.NativeTrace(cl.worldmodel, 0, NULLFRAMESTATE, NULL, r_refdef.vieworg, camorg, vec3_origin, vec3_origin, true, MASK_WORLDSOLID, &tr))
VectorCopy(camorg, r_refdef.vieworg);
V_EditExternalModels(0, NULL, 0);

View file

@ -2481,7 +2481,7 @@ static qboolean Image_ReadDDSFile(texid_t tex, unsigned int flags, char *fname,
int encoding;
ddsheader fmtheader;
if (*(int*)filedata != *(int*)"DDS ")
if (*(int*)filedata != (('D'<<0)|('D'<<8)|('S'<<16)|(' '<<24)))
return false;
memcpy(&fmtheader, filedata+4, sizeof(fmtheader));
@ -2492,14 +2492,14 @@ static qboolean Image_ReadDDSFile(texid_t tex, unsigned int flags, char *fname,
if (nummips < 1)
nummips = 1;
if (*(int*)&fmtheader.ddpfPixelFormat.dwFourCC == *(int*)"DXT1")
if (*(int*)&fmtheader.ddpfPixelFormat.dwFourCC == (('D'<<0)|('X'<<8)|('T'<<16)|('1'<<24)))
{
encoding = PTI_S3RGBA1; //alpha or not? Assume yes, and let the drivers decide.
pad = 8;
divsize = 4;
blocksize = 8;
}
else if (*(int*)&fmtheader.ddpfPixelFormat.dwFourCC == *(int*)"DXT2") //dx3 with premultiplied alpha
else if (*(int*)&fmtheader.ddpfPixelFormat.dwFourCC == (('D'<<0)|('X'<<8)|('T'<<16)|('2'<<24))) //dx3 with premultiplied alpha
{
// if (!(tex->flags & IF_PREMULTIPLYALPHA))
return false;
@ -2508,7 +2508,7 @@ static qboolean Image_ReadDDSFile(texid_t tex, unsigned int flags, char *fname,
divsize = 4;
blocksize = 16;
}
else if (*(int*)&fmtheader.ddpfPixelFormat.dwFourCC == *(int*)"DXT3")
else if (*(int*)&fmtheader.ddpfPixelFormat.dwFourCC == (('D'<<0)|('X'<<8)|('T'<<16)|('3'<<24)))
{
if (tex->flags & IF_PREMULTIPLYALPHA)
return false;
@ -2517,7 +2517,7 @@ static qboolean Image_ReadDDSFile(texid_t tex, unsigned int flags, char *fname,
divsize = 4;
blocksize = 16;
}
else if (*(int*)&fmtheader.ddpfPixelFormat.dwFourCC == *(int*)"DXT4") //dx5 with premultiplied alpha
else if (*(int*)&fmtheader.ddpfPixelFormat.dwFourCC == (('D'<<0)|('X'<<8)|('T'<<16)|('4'<<24))) //dx5 with premultiplied alpha
{
// if (!(tex->flags & IF_PREMULTIPLYALPHA))
return false;
@ -2526,7 +2526,7 @@ static qboolean Image_ReadDDSFile(texid_t tex, unsigned int flags, char *fname,
divsize = 4;
blocksize = 16;
}
else if (*(int*)&fmtheader.ddpfPixelFormat.dwFourCC == *(int*)"DXT5")
else if (*(int*)&fmtheader.ddpfPixelFormat.dwFourCC == (('D'<<0)|('X'<<8)|('T'<<16)|('5'<<24)))
{
if (tex->flags & IF_PREMULTIPLYALPHA)
return false;
@ -4646,10 +4646,9 @@ static void Image_LoadHiResTextureWorker(void *ctx, void *data, size_t a, size_t
char fname[MAX_QPATH];
char *altname;
char *nextalt;
qboolean exactext = !!(tex->flags & IF_EXACTEXTENSION);
flocation_t loc;
unsigned int locflags;
unsigned int locflags = 0;
vfsfile_t *f;
size_t fsize;
@ -4720,7 +4719,7 @@ static void Image_LoadHiResTextureWorker(void *ctx, void *data, size_t a, size_t
//guess not, fall back to normalmaps
}
if (Image_LoadTextureFromMemory(tex, tex->flags, tex->ident, loc.rawname, buf, fsize))
if (Image_LoadTextureFromMemory(tex, tex->flags, tex->ident, fname, buf, fsize))
{
BZ_Free(tex->fallbackdata);
tex->fallbackdata = NULL;

View file

@ -69,6 +69,7 @@ typedef struct {
float bonecontrols[MAX_BONE_CONTROLLERS]; //hl special bone controllers
#endif
} framestate_t;
#define NULLFRAMESTATE (framestate_t*)NULL

View file

@ -1623,7 +1623,7 @@ parsefluid:
ptype->sounds[ptype->numsounds].vol = 1;
ptype->sounds[ptype->numsounds].atten = 1;
ptype->sounds[ptype->numsounds].pitch = 100;
ptype->sounds[ptype->numsounds].pitch = 1;
ptype->sounds[ptype->numsounds].delay = 0;
ptype->sounds[ptype->numsounds].weight = 0;
@ -1650,7 +1650,7 @@ parsefluid:
ptype->sounds[ptype->numsounds].atten = atof(e);
}
else if (!Q_strncasecmp(e, "pitch=", 6))
ptype->sounds[ptype->numsounds].pitch = atof(strchr(e, '=')+1);
ptype->sounds[ptype->numsounds].pitch = atof(strchr(e, '=')+1)*0.01;
else if (!Q_strncasecmp(e, "delay=", 6))
ptype->sounds[ptype->numsounds].delay = atof(strchr(e, '=')+1);
else if (!Q_strncasecmp(e, "weight=", 7))
@ -1667,9 +1667,9 @@ parsefluid:
ptype->sounds[ptype->numsounds].atten = atof(Cmd_Argv(3));
if (!ptype->sounds[ptype->numsounds].atten)
ptype->sounds[ptype->numsounds].atten = 1;
ptype->sounds[ptype->numsounds].pitch = atof(Cmd_Argv(4));
ptype->sounds[ptype->numsounds].pitch = atof(Cmd_Argv(4))*0.01;
if (!ptype->sounds[ptype->numsounds].pitch)
ptype->sounds[ptype->numsounds].pitch = 100;
ptype->sounds[ptype->numsounds].pitch = 1;
ptype->sounds[ptype->numsounds].delay = atof(Cmd_Argv(5));
if (!ptype->sounds[ptype->numsounds].delay)
ptype->sounds[ptype->numsounds].delay = 0;

View file

@ -3610,7 +3610,7 @@ void QCBUILTIN PF_soundupdate (pubprogfuncs_t *prinst, struct globalvars_s *pr_g
const char *sample = PR_GetStringOfs(prinst, OFS_PARM2);
float volume = G_FLOAT(OFS_PARM3);
float attenuation = G_FLOAT(OFS_PARM4);
float pitchpct = (prinst->callargc >= 6)?G_FLOAT(OFS_PARM5):0;
float pitchpct = (prinst->callargc >= 6)?G_FLOAT(OFS_PARM5)*0.01:0;
unsigned int flags = (prinst->callargc>=7)?G_FLOAT(OFS_PARM6):0;
float startoffset = (prinst->callargc>=8)?G_FLOAT(OFS_PARM7):0;
@ -3659,7 +3659,7 @@ static void QCBUILTIN PF_cs_sound(pubprogfuncs_t *prinst, struct globalvars_s *p
sample = PR_GetStringOfs(prinst, OFS_PARM2);
volume = G_FLOAT(OFS_PARM3);
attenuation = G_FLOAT(OFS_PARM4);
pitchpct = (prinst->callargc>=6)?G_FLOAT(OFS_PARM5):0;
pitchpct = (prinst->callargc>=6)?G_FLOAT(OFS_PARM5)*0.01:0;
flags = (prinst->callargc>=7)?G_FLOAT(OFS_PARM6):0;
startoffset = (prinst->callargc>=8)?G_FLOAT(OFS_PARM7):0;
@ -3691,7 +3691,7 @@ static void QCBUILTIN PF_cs_pointsound(pubprogfuncs_t *prinst, struct globalvars
volume = G_FLOAT(OFS_PARM2);
attenuation = G_FLOAT(OFS_PARM3);
if (prinst->callargc >= 5)
pitchpct = G_FLOAT(OFS_PARM4);
pitchpct = G_FLOAT(OFS_PARM4)*0.01;
else
pitchpct = 0;
@ -7883,7 +7883,7 @@ int CSQC_StartSound(int entnum, int channel, char *soundname, vec3_t pos, float
G_FLOAT(OFS_PARM3) = vol;
G_FLOAT(OFS_PARM4) = attenuation;
VectorCopy(pos, G_VECTOR(OFS_PARM5));
G_FLOAT(OFS_PARM6) = pitchmod;
G_FLOAT(OFS_PARM6) = pitchmod*100;
G_FLOAT(OFS_PARM7) = flags;
// G_FLOAT(OFS_PARM8) = timeofs;

View file

@ -911,10 +911,10 @@ float CL_TraceLine (vec3_t start, vec3_t end, vec3_t impact, vec3_t normal, int
{
AngleVectors(pe->angles, axis[0], axis[1], axis[2]);
VectorNegate(axis[1], axis[1]);
pe->model->funcs.NativeTrace(pe->model, 0, 0, axis, ts, te, vec3_origin, vec3_origin, false, MASK_WORLDSOLID, &trace);
pe->model->funcs.NativeTrace(pe->model, 0, PE_FRAMESTATE, axis, ts, te, vec3_origin, vec3_origin, false, MASK_WORLDSOLID, &trace);
}
else
pe->model->funcs.NativeTrace(pe->model, 0, 0, NULL, ts, te, vec3_origin, vec3_origin, false, MASK_WORLDSOLID, &trace);
pe->model->funcs.NativeTrace(pe->model, 0, PE_FRAMESTATE, NULL, ts, te, vec3_origin, vec3_origin, false, MASK_WORLDSOLID, &trace);
if (trace.fraction<1)
{
if (bestfrac > trace.fraction)

View file

@ -93,6 +93,7 @@ cvar_t r_bouncysparks = CVARFD ("r_bouncysparks", "1",
CVAR_ARCHIVE,
"Enables particle interaction with world surfaces, allowing for bouncy particles, stains, and decals.");
cvar_t r_drawentities = CVAR ("r_drawentities", "1");
cvar_t r_max_gpu_bones = CVARD ("r_max_gpu_bones", "", "Specifies the maximum number of bones that can be handled on the GPU. If empty, will guess.");
cvar_t r_drawflat = CVARAF ("r_drawflat", "0", "gl_textureless",
CVAR_ARCHIVE | CVAR_SEMICHEAT | CVAR_RENDERERCALLBACK | CVAR_SHADERSYSTEM);
cvar_t r_lightmap = CVARF ("r_lightmap", "0",
@ -877,6 +878,7 @@ void Renderer_Init(void)
Cvar_Register (&gl_texturemode2d, GLRENDEREROPTIONS);
Cvar_Register (&gl_mipcap, GLRENDEREROPTIONS);
Cvar_Register (&gl_texture_anisotropic_filtering, GLRENDEREROPTIONS);
Cvar_Register (&r_max_gpu_bones, GRAPHICALNICETIES);
Cvar_Register (&r_drawflat, GRAPHICALNICETIES);
Cvar_Register (&r_lightmap, GRAPHICALNICETIES);
Cvar_Register (&r_menutint, GRAPHICALNICETIES);

View file

@ -2553,7 +2553,7 @@ static void SND_Spatialize(soundcardinfo_t *sc, channel_t *ch)
// =======================================================================
// Start a sound effect
// =======================================================================
static void S_UpdateSoundCard(soundcardinfo_t *sc, qboolean updateonly, channel_t *target_chan, int entnum, int entchannel, sfx_t *sfx, vec3_t origin, vec3_t velocity, float fvol, float attenuation, float timeoffset, float pitchadj, unsigned int flags)
static void S_UpdateSoundCard(soundcardinfo_t *sc, qboolean updateonly, channel_t *target_chan, int entnum, int entchannel, sfx_t *sfx, vec3_t origin, vec3_t velocity, float fvol, float attenuation, float timeoffset, float ratemul, unsigned int flags)
{
channel_t *check;
int vol;
@ -2572,10 +2572,10 @@ static void S_UpdateSoundCard(soundcardinfo_t *sc, qboolean updateonly, channel_
if (!sfx)
sfx = target_chan->sfx;
if (pitchadj <= 0)
pitchadj = 100;
if (ratemul <= 0)
ratemul = 1;
pitchadj *= snd_playbackrate.value * (cls.state?cl.gamespeed:1) * (cls.demoplayback?cl_demospeed.value:1);
ratemul *= snd_playbackrate.value * (cls.state?cl.gamespeed:1) * (cls.demoplayback?cl_demospeed.value:1);
vol = fvol*255;
@ -2632,7 +2632,7 @@ static void S_UpdateSoundCard(soundcardinfo_t *sc, qboolean updateonly, channel_
absstartpos = 0;
}
target_chan->rate = ((1<<PITCHSHIFT) * pitchadj) / 100; /*pitchadj is a percentage*/
target_chan->rate = ((1<<PITCHSHIFT) * ratemul); //*sfx->rate/sc->sn.speed;
if (target_chan->rate < 1) /*make sure the rate won't crash us*/
target_chan->rate = 1;
target_chan->pos = absstartpos + (int)(timeoffset*sc->sn.speed*target_chan->rate);

View file

@ -23,7 +23,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define MAX_MAP_HULLSDQ1 4
#define MAX_MAP_HULLSDH2 8
#define MAX_MAP_HULLSM 16
#define MAX_MAP_HULLSM 8
//#define MAX_MAP_MODELS 256
//#define MAX_MAP_BRUSHES 0x8000

View file

@ -1578,7 +1578,7 @@ qboolean Alias_GAliasBuildMesh(mesh_t *mesh, vbo_t **vbop, galiasinfo_t *inf, in
usebones = false;
else if (inf->ofs_skel_xyz && !inf->ofs_skel_weight)
usebones = false;
else if (e->fatness || !inf->ofs_skel_idx || inf->numbones > MAX_GPU_BONES)
else if (e->fatness || !inf->ofs_skel_idx || inf->numbones > sh_config.max_gpu_bones)
#endif
usebones = false;
@ -2270,7 +2270,7 @@ qboolean Mod_Trace(model_t *model, int forcehullnum, framestate_t *framestate, v
#ifdef SKELETALMODELS
if (mod->numbones)
{
if (!mod->ofs_skel_idx)
if (!mod->ofs_skel_idx || !framestate)
posedata = mod->ofs_skel_xyz; //if there's no weights, don't try animating anything.
else if (mod->shares_verts != cursurfnum || !posedata)
{
@ -2292,12 +2292,14 @@ qboolean Mod_Trace(model_t *model, int forcehullnum, framestate_t *framestate, v
else
{
group = mod->ofsanimations;
group += framestate->g[FS_REG].frame[0] % mod->numanimations;
if (framestate)
group += framestate->g[FS_REG].frame[0] % mod->numanimations;
//FIXME: no support for frame blending.
if (!group->numposes)
continue;
pose = group->poseofs;
pose += (int)(framestate->g[FS_REG].frametime[0] * group->rate)%group->numposes;
if (framestate)
pose += (int)(framestate->g[FS_REG].frametime[0] * group->rate)%group->numposes;
posedata = pose->ofsverts;
}

View file

@ -216,7 +216,7 @@ unsigned int Net_PextMask(int maskset, qboolean fornq)
if (fornq)
{
//only ones that are tested
mask &= PEXT2_VOICECHAT | PEXT2_REPLACEMENTDELTAS | PEXT2_NEWSIZEENCODING | PEXT2_PREDINFO;
mask &= /*PEXT2_PRYDONCURSOR |*/ PEXT2_VOICECHAT | PEXT2_SETANGLEDELTA | PEXT2_REPLACEMENTDELTAS | PEXT2_MAXPLAYERS | PEXT2_PREDINFO | PEXT2_NEWSIZEENCODING;
}
// else
// mask &= ~PEXT2_PREDINFO;

View file

@ -975,7 +975,7 @@ void PM_CategorizePosition (void)
VectorMA (pmove.origin, 24, flatforward, fwd1);
pmove.physents[0].model->funcs.NativeTrace(pmove.physents[0].model, 0, 0, NULL, pmove.origin, fwd1, pmove.player_mins, pmove.player_maxs, pmove.capsule, MASK_PLAYERSOLID, &t);
pmove.physents[0].model->funcs.NativeTrace(pmove.physents[0].model, 0, PE_FRAMESTATE, NULL, pmove.origin, fwd1, pmove.player_mins, pmove.player_maxs, pmove.capsule, MASK_PLAYERSOLID, &t);
if (t.surface && t.surface->flags & Q3SURF_LADDER)
{
pmove.onladder = true;

View file

@ -48,6 +48,8 @@ typedef struct
qbyte notouch; //don't trigger touch events. FIXME: why are these entities even in the list?
qbyte isportal; //special portal traversion required
unsigned int forcecontentsmask;
// framestate_t framestate;
#define PE_FRAMESTATE NULLFRAMESTATE //remove this once we start wanting players to interact with ents in different frames.
} physent_t;
typedef struct

View file

@ -19,7 +19,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "quakedef.h"
static qboolean PM_TransformedHullCheck (model_t *model, vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, trace_t *trace, vec3_t origin, vec3_t angles);
static qboolean PM_TransformedHullCheck (model_t *model, framestate_t *framestate, vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, trace_t *trace, vec3_t origin, vec3_t angles);
int Q1BSP_HullPointContents(hull_t *hull, vec3_t p);
static hull_t box_hull;
static mclipnode_t box_clipnodes[6];
@ -182,7 +182,7 @@ int PM_ExtraBoxContents (vec3_t p)
{
if (pe->forcecontentsmask)
{
if (!PM_TransformedHullCheck(pm, p, p, pmove.player_mins, pmove.player_maxs, &tr, pe->origin, pe->angles))
if (!PM_TransformedHullCheck(pm, PE_FRAMESTATE, p, p, pmove.player_mins, pmove.player_maxs, &tr, pe->origin, pe->angles))
continue;
if (tr.startsolid || tr.inwater)
pc |= pe->forcecontentsmask;
@ -209,7 +209,7 @@ LINE TESTING IN HULLS
*/
/*returns if it actually did a trace*/
static qboolean PM_TransformedHullCheck (model_t *model, vec3_t start, vec3_t end, vec3_t player_mins, vec3_t player_maxs, trace_t *trace, vec3_t origin, vec3_t angles)
static qboolean PM_TransformedHullCheck (model_t *model, framestate_t *framestate, vec3_t start, vec3_t end, vec3_t player_mins, vec3_t player_maxs, trace_t *trace, vec3_t origin, vec3_t angles)
{
vec3_t start_l, end_l;
int i;
@ -226,7 +226,7 @@ static qboolean PM_TransformedHullCheck (model_t *model, vec3_t start, vec3_t en
{
AngleVectors (angles, axis[0], axis[1], axis[2]);
VectorNegate(axis[1], axis[1]);
model->funcs.NativeTrace(model, 0, 0, axis, start_l, end_l, player_mins, player_maxs, pmove.capsule, MASK_PLAYERSOLID, trace);
model->funcs.NativeTrace(model, 0, framestate, axis, start_l, end_l, player_mins, player_maxs, pmove.capsule, MASK_PLAYERSOLID, trace);
}
else
{
@ -237,7 +237,7 @@ static qboolean PM_TransformedHullCheck (model_t *model, vec3_t start, vec3_t en
if (start_l[i]+player_maxs[i] < model->mins[i] && end_l[i] + player_maxs[i] < model->mins[i])
return false;
}
model->funcs.NativeTrace(model, 0, 0, NULL, start_l, end_l, player_mins, player_maxs, pmove.capsule, MASK_PLAYERSOLID, trace);
model->funcs.NativeTrace(model, 0, framestate, NULL, start_l, end_l, player_mins, player_maxs, pmove.capsule, MASK_PLAYERSOLID, trace);
}
}
else
@ -388,7 +388,7 @@ qboolean PM_TestPlayerPosition (vec3_t pos, qboolean ignoreportals)
//if the trace ended up inside a portal region, then its not valid.
if (pe->model)
{
if (!PM_TransformedHullCheck (pe->model, pos, pos, vec3_origin, vec3_origin, &trace, pe->origin, pe->angles))
if (!PM_TransformedHullCheck (pe->model, PE_FRAMESTATE, pos, pos, vec3_origin, vec3_origin, &trace, pe->origin, pe->angles))
continue;
if (trace.allsolid)
return false;
@ -405,7 +405,7 @@ qboolean PM_TestPlayerPosition (vec3_t pos, qboolean ignoreportals)
{
if (pe->model)
{
if (!PM_TransformedHullCheck (pe->model, pos, pos, pmove.player_mins, pmove.player_maxs, &trace, pe->origin, pe->angles))
if (!PM_TransformedHullCheck (pe->model, PE_FRAMESTATE, pos, pos, pmove.player_mins, pmove.player_maxs, &trace, pe->origin, pe->angles))
continue;
if (trace.allsolid)
{
@ -480,7 +480,7 @@ trace_t PM_PlayerTrace (vec3_t start, vec3_t end, unsigned int solidmask)
PM_HullForBox (mins, maxs);
// trace a line through the apropriate clipping hull
if (!PM_TransformedHullCheck (NULL, start, end, pmove.player_mins, pmove.player_maxs, &trace, pe->origin, pe->angles))
if (!PM_TransformedHullCheck (NULL, NULL, start, end, pmove.player_mins, pmove.player_maxs, &trace, pe->origin, pe->angles))
continue;
}
else if (pe->isportal)
@ -489,13 +489,13 @@ trace_t PM_PlayerTrace (vec3_t start, vec3_t end, unsigned int solidmask)
PM_PortalCSG(pe, i, pmove.player_mins, pmove.player_maxs, start, end, &total);
// trace a line through the apropriate clipping hull
if (!PM_TransformedHullCheck (pe->model, start, end, vec3_origin, vec3_origin, &trace, pe->origin, pe->angles))
if (!PM_TransformedHullCheck (pe->model, PE_FRAMESTATE, start, end, vec3_origin, vec3_origin, &trace, pe->origin, pe->angles))
continue;
}
else
{
// trace a line through the apropriate clipping hull
if (!PM_TransformedHullCheck (pe->model, start, end, pmove.player_mins, pmove.player_maxs, &trace, pe->origin, pe->angles))
if (!PM_TransformedHullCheck (pe->model, PE_FRAMESTATE, start, end, pmove.player_mins, pmove.player_maxs, &trace, pe->origin, pe->angles))
continue;
if (trace.allsolid)

View file

@ -866,7 +866,7 @@ enum {
#define FTESND_MOREFLAGS (1<<2) // actually, chan flags
#define NQSND_LARGEENTITY (1<<3) //both dp+fitz
#define NQSND_LARGESOUND (1<<4) //both dp+fitz
//#define DPSND_SPEEDUSHORT4000 (1<<5) // ushort speed*4000 (speed is usually 1.0, a value of 0.0 is the same as 1.0)
#define DPSND_SPEEDUSHORT4000 (1<<5) // ushort speed*4000 (speed is usually 1.0, a value of 0.0 is the same as 1.0)
#define FTESND_TIMEOFS (1<<6) //signed short, in milliseconds.
#define FTESND_PITCHADJ (1<<7) //a byte (speed percent (0=100%))
//more flags are weird.
@ -923,7 +923,8 @@ enum {
TEQW_BEAM = 18, //use the builtin, luke.
TENEH_SMOKE = 18, //gah [vector] origin [byte] palette
TEQW_EXPLOSION2 = 19, //use the builtin, luke.
TEQW_EXPLOSIONNOSPRITE = 20,
TEQW_EXPLOSION_NOSPRITE = 20, //nq-style explosion over qw
TENQ_EXPLOSION_SPRITE = 20, //qw-style explosion over nq
TE_GUNSHOT_NQCOMPAT = 21, //nq has count byte, qw does not
// hexen 2

View file

@ -2123,7 +2123,7 @@ void Q1BSPX_Setup(model_t *mod, char *filebase, unsigned int filelen, lump_t *lu
i = LittleLong(h->numlumps);
/*verify the header*/
if (*(int*)h->id != *(int*)"BSPX" ||
if (*(int*)h->id != (('B'<<0)|('S'<<8)|('P'<<16)|('X'<<24)) ||
i < 0 ||
offs + sizeof(*h) + sizeof(h->lumps[0])*(i-1) > filelen)
return;

View file

@ -3137,12 +3137,10 @@ static void BE_Program_Set_Attributes(const program_t *prog, unsigned int perm,
break;
case SP_M_ENTBONES:
{
#ifdef GLESONLY
//cop out.
qglUniform4fvARB(ph, shaderstate.sourcevbo->numbones*3, shaderstate.sourcevbo->bones);
#else
qglUniformMatrix3x4fv(ph, shaderstate.sourcevbo->numbones, false, shaderstate.sourcevbo->bones);
#endif
if (sh_config.maxver>=120)
qglUniformMatrix3x4fv(ph, shaderstate.sourcevbo->numbones, false, shaderstate.sourcevbo->bones);
else
qglUniform4fvARB(ph, shaderstate.sourcevbo->numbones*3, shaderstate.sourcevbo->bones);
}
break;
case SP_M_INVVIEWPROJECTION:

View file

@ -570,7 +570,7 @@ void HL_SetupBones(hlmodel_t *model, int seqnum, int firstbone, int lastbone, fl
}
if (!model->animcache[sequence->seqindex])
model->animcache[sequence->seqindex] = FS_LoadMallocGroupFile(model->memgroup, sequencedata->name+32, &fz);
if (!model->animcache[sequence->seqindex] || model->animcache[sequence->seqindex]->magic != *(int*)"IDSQ" || model->animcache[sequence->seqindex]->version != 10)
if (!model->animcache[sequence->seqindex] || model->animcache[sequence->seqindex]->magic != (('I'<<0)|('D'<<8)|('S'<<16)|('Q'<<24)) || model->animcache[sequence->seqindex]->version != 10)
{
Sys_Error("Unable to load %s\n", sequencedata->name+32);
return;

View file

@ -53,11 +53,6 @@ typedef enum {
} shadersort_t;
#define MAX_BONES 256
#ifdef FTE_TARGET_WEB
#define MAX_GPU_BONES 32 //ATI drivers bug out and start to crash if you put this at 128. FIXME: make dynamic.
#else
#define MAX_GPU_BONES 64 //ATI drivers bug out and start to crash if you put this at 128. FIXME: make dynamic.
#endif
struct doll_s;
void rag_uninstanciateall(void);
void rag_flushdolls(qboolean force);

View file

@ -1124,6 +1124,7 @@ static qboolean Shader_LoadPermutations(char *name, program_t *prog, char *scrip
qboolean geom = false;
qboolean tess = false;
char maxgpubones[128];
cvar_t *cvarrefs[64];
char *cvarnames[64];
int cvartypes[64];
@ -1423,6 +1424,15 @@ static qboolean Shader_LoadPermutations(char *name, program_t *prog, char *scrip
}
blobadded = false;
if (!sh_config.max_gpu_bones)
{
Q_snprintfz(maxgpubones, sizeof(maxgpubones), "");
nopermutation |= PERMUTATION_SKELETAL;
}
else if (qrenderer == QR_OPENGL && sh_config.maxver < 120) //with old versions of glsl (including gles), mat3x4 is not supported, and we have to emulate it with 3*vec4. maybe we should just do that unconditionally, but whatever.
Q_snprintfz(maxgpubones, sizeof(maxgpubones), "#define MAX_GPU_BONES %i\n#define PACKEDBONES\n", sh_config.max_gpu_bones);
else
Q_snprintfz(maxgpubones, sizeof(maxgpubones), "#define MAX_GPU_BONES %i\n", sh_config.max_gpu_bones);
if (gl_specular.value)
{
if (nummodifiers < MAXMODIFIERS)
@ -1530,6 +1540,7 @@ static qboolean Shader_LoadPermutations(char *name, program_t *prog, char *scrip
prog->supportedpermutations = ~nopermutation;
for (p = 0; p < PERMUTATIONS; p++)
{
qboolean isprimary;
memset(&prog->permu[p].h, 0, sizeof(prog->permu[p].h));
if (nopermutation & p)
{
@ -1541,8 +1552,11 @@ static qboolean Shader_LoadPermutations(char *name, program_t *prog, char *scrip
if (p & (1u<<n))
permutationdefines[pn++] = permutationname[n];
}
isprimary = (pn-nummodifiers)==1;
if (p & PERMUTATION_UPPERLOWER)
permutationdefines[pn++] = "#define UPPER\n#define LOWER\n";
if (p & PERMUTATION_SKELETAL)
permutationdefines[pn++] = maxgpubones;
if (p & PERMUTATION_BUMPMAP)
{
if (r_glsl_offsetmapping.ival)
@ -1573,6 +1587,8 @@ static qboolean Shader_LoadPermutations(char *name, program_t *prog, char *scrip
#define SILENTPERMUTATIONS (developer.ival?0:PERMUTATION_SKELETAL)
if (!sh_config.pCreateProgram(prog, name, p, ver, permutationdefines, script, tess?script:NULL, tess?script:NULL, geom?script:NULL, script, (p & SILENTPERMUTATIONS)?true:onefailed, sh_config.pValidateProgram?NULL:blobfile))
{
if (isprimary)
prog->supportedpermutations &= ~p;
if (!(p & SILENTPERMUTATIONS))
onefailed = true; //don't flag it if skeletal failed.
if (!p) //give up if permutation 0 failed. that one failing is fatal.
@ -3483,6 +3499,23 @@ qboolean Shader_Init (void)
Hash_InitTable(&shader_active_hash, 1024, shader_active_hash_mem);
Shader_FlushGenerics();
if (!sh_config.progs_supported)
sh_config.max_gpu_bones = 0;
else
{
extern cvar_t r_max_gpu_bones;
if (!*r_max_gpu_bones.string)
{
#ifdef FTE_TARGET_WEB
sh_config.max_gpu_bones = 0; //webgl tends to crap out if this is too high, so 32 is a good enough value to play safe. some browsers have really shitty uniform performance too, so lets just default to pure-cpu transforms. in javascript. yes, its that bad.
#else
sh_config.max_gpu_bones = 64; //ATI drivers bug out and start to crash if you put this at 128.
#endif
}
else
sh_config.max_gpu_bones = bound(0, r_max_gpu_bones.ival, MAX_BONES);
}
}
memset(wibuf, 0xff, sizeof(wibuf));

View file

@ -1263,7 +1263,6 @@ static const char *glsl_hdrs[] =
"uniform sampler2D s_deluxmap3;\n"
#endif
#endif
"#ifdef USEUBOS\n"
"layout(std140) uniform u_lightinfo\n"
"{\n"
@ -1305,14 +1304,16 @@ static const char *glsl_hdrs[] =
"vec3 e_light_ambient;\n"
"float e_time;\n"
"};\n"
"layout(std140) unform u_bones\n"
"{\n"
#ifdef GLESONLY
"vec4 m_bones[3*"STRINGIFY(MAX_GPU_BONES)"];\n"
#else
"mat3x4 m_bones["STRINGIFY(MAX_GPU_BONES)"]\n"
#endif
"};\n"
"#ifdef SKELETAL\n"
"layout(std140) unform u_bones\n"
"{\n"
"#ifdef PACKEDBONES\n"
"vec4 m_bones[3*MAX_GPU_BONES];\n"
"#else\n"
"mat3x4 m_bones[MAX_GPU_BONES]\n"
"#endif\n"
"};\n"
"#endif\n"
"#else\n"
"uniform mat4 m_model;\n"
"uniform mat4 m_view;\n"
@ -1320,11 +1321,11 @@ static const char *glsl_hdrs[] =
"uniform mat4 m_projection;\n"
// "uniform mat4 m_modelviewprojection;\n"
"#ifdef SKELETAL\n" //skeletal permutation tends to require glsl 120
#ifdef GLESONLY
"uniform vec4 m_bones[3*"STRINGIFY(MAX_GPU_BONES)"];\n"
#else
"uniform mat3x4 m_bones["STRINGIFY(MAX_GPU_BONES)"];\n"
#endif
"#ifdef PACKEDBONES\n"
"uniform vec4 m_bones[3*MAX_GPU_BONES];\n"
"#else\n"
"uniform mat3x4 m_bones[MAX_GPU_BONES];\n"
"#endif\n"
"#endif\n"
"uniform mat4 m_invviewprojection;\n"
"uniform mat4 m_invmodelviewprojection;\n"
@ -1371,145 +1372,148 @@ static const char *glsl_hdrs[] =
,
"sys/skeletal.h",
"#ifndef DEFS_DEFINED\n"
"attribute vec3 v_normal;\n"
"attribute vec3 v_svector;\n"
"attribute vec3 v_tvector;\n"
"attribute vec3 v_normal;\n"
"attribute vec3 v_svector;\n"
"attribute vec3 v_tvector;\n"
"#endif\n"
"#ifdef SKELETAL\n"
"#ifndef DEFS_DEFINED\n"
"attribute vec4 v_bone;"
"attribute vec4 v_weight;"
#ifdef GLESONLY
"uniform vec4 m_bones[3*"STRINGIFY(MAX_GPU_BONES)"];\n"
#else
"uniform mat3x4 m_bones["STRINGIFY(MAX_GPU_BONES)"];\n"
#endif
"attribute vec4 v_weight;\n"
"#ifdef PACKEDBONES\n"
"uniform vec4 m_bones[3*MAX_GPU_BONES];\n"
"#else\n"
"uniform mat3x4 m_bones[MAX_GPU_BONES];\n"
"#endif\n"
"#endif\n"
"vec4 skeletaltransform()"
"{"
#ifdef GLESONLY
"mat4 wmat;\n"
"wmat[0] = m_bones[0+3*int(v_bone.x)] * v_weight.x;\n"
"wmat[0] += m_bones[0+3*int(v_bone.y)] * v_weight.y;\n"
"wmat[0] += m_bones[0+3*int(v_bone.z)] * v_weight.z;\n"
"wmat[0] += m_bones[0+3*int(v_bone.w)] * v_weight.w;\n"
"wmat[1] = m_bones[1+3*int(v_bone.x)] * v_weight.x;\n"
"wmat[1] += m_bones[1+3*int(v_bone.y)] * v_weight.y;\n"
"wmat[1] += m_bones[1+3*int(v_bone.z)] * v_weight.z;\n"
"wmat[1] += m_bones[1+3*int(v_bone.w)] * v_weight.w;\n"
"wmat[2] = m_bones[2+3*int(v_bone.x)] * v_weight.x;\n"
"wmat[2] += m_bones[2+3*int(v_bone.y)] * v_weight.y;\n"
"wmat[2] += m_bones[2+3*int(v_bone.z)] * v_weight.z;\n"
"wmat[2] += m_bones[2+3*int(v_bone.w)] * v_weight.w;\n"
"wmat[3] = vec4(0.0,0.0,0.0,1.0);\n"
"return m_modelviewprojection * (vec4(v_position.xyz, 1.0) * wmat);"
#else
"mat3x4 wmat;\n"
"wmat = m_bones[int(v_bone.x)] * v_weight.x;\n"
"wmat += m_bones[int(v_bone.y)] * v_weight.y;\n"
"wmat += m_bones[int(v_bone.z)] * v_weight.z;\n"
"wmat += m_bones[int(v_bone.w)] * v_weight.w;\n"
"return m_modelviewprojection * vec4(vec4(v_position.xyz, 1.0) * wmat, 1.0);"
#endif
"}\n"
"vec4 skeletaltransform_nst(out vec3 n, out vec3 t, out vec3 b)"
"{"
#ifdef GLESONLY
"mat4 wmat;\n"
"wmat[0] = m_bones[0+3*int(v_bone.x)] * v_weight.x;\n"
"wmat[0] += m_bones[0+3*int(v_bone.y)] * v_weight.y;\n"
"wmat[0] += m_bones[0+3*int(v_bone.z)] * v_weight.z;\n"
"wmat[0] += m_bones[0+3*int(v_bone.w)] * v_weight.w;\n"
"wmat[1] = m_bones[1+3*int(v_bone.x)] * v_weight.x;\n"
"wmat[1] += m_bones[1+3*int(v_bone.y)] * v_weight.y;\n"
"wmat[1] += m_bones[1+3*int(v_bone.z)] * v_weight.z;\n"
"wmat[1] += m_bones[1+3*int(v_bone.w)] * v_weight.w;\n"
"wmat[2] = m_bones[2+3*int(v_bone.x)] * v_weight.x;\n"
"wmat[2] += m_bones[2+3*int(v_bone.y)] * v_weight.y;\n"
"wmat[2] += m_bones[2+3*int(v_bone.z)] * v_weight.z;\n"
"wmat[2] += m_bones[2+3*int(v_bone.w)] * v_weight.w;\n"
"wmat[3] = vec4(0.0,0.0,0.0,1.0);\n"
"n = (vec4(v_normal.xyz, 0.0) * wmat).xyz;"
"t = (vec4(v_svector.xyz, 0.0) * wmat).xyz;"
"b = (vec4(v_tvector.xyz, 0.0) * wmat).xyz;"
"return m_modelviewprojection * (vec4(v_position.xyz, 1.0) * wmat);"
#else
"mat3x4 wmat;\n"
"wmat = m_bones[int(v_bone.x)] * v_weight.x;"
"wmat += m_bones[int(v_bone.y)] * v_weight.y;"
"wmat += m_bones[int(v_bone.z)] * v_weight.z;"
"wmat += m_bones[int(v_bone.w)] * v_weight.w;"
"n = vec4(v_normal.xyz, 0.0) * wmat;"
"t = vec4(v_svector.xyz, 0.0) * wmat;"
"b = vec4(v_tvector.xyz, 0.0) * wmat;"
"return m_modelviewprojection * vec4(vec4(v_position.xyz, 1.0) * wmat, 1.0);"
#endif
"}\n"
"vec4 skeletaltransform_wnst(out vec3 w, out vec3 n, out vec3 t, out vec3 b)"
"{"
#ifdef GLESONLY
"mat4 wmat;\n"
"wmat[0] = m_bones[0+3*int(v_bone.x)] * v_weight.x;\n"
"wmat[0] += m_bones[0+3*int(v_bone.y)] * v_weight.y;\n"
"wmat[0] += m_bones[0+3*int(v_bone.z)] * v_weight.z;\n"
"wmat[0] += m_bones[0+3*int(v_bone.w)] * v_weight.w;\n"
"wmat[1] = m_bones[1+3*int(v_bone.x)] * v_weight.x;\n"
"wmat[1] += m_bones[1+3*int(v_bone.y)] * v_weight.y;\n"
"wmat[1] += m_bones[1+3*int(v_bone.z)] * v_weight.z;\n"
"wmat[1] += m_bones[1+3*int(v_bone.w)] * v_weight.w;\n"
"wmat[2] = m_bones[2+3*int(v_bone.x)] * v_weight.x;\n"
"wmat[2] += m_bones[2+3*int(v_bone.y)] * v_weight.y;\n"
"wmat[2] += m_bones[2+3*int(v_bone.z)] * v_weight.z;\n"
"wmat[2] += m_bones[2+3*int(v_bone.w)] * v_weight.w;\n"
"wmat[3] = vec4(0.0,0.0,0.0,1.0);\n"
"n = (vec4(v_normal.xyz, 0.0) * wmat).xyz;"
"t = (vec4(v_svector.xyz, 0.0) * wmat).xyz;"
"b = (vec4(v_tvector.xyz, 0.0) * wmat).xyz;"
"w = (vec4(v_position.xyz, 1.0) * wmat).xyz;"
"return m_modelviewprojection * (vec4(v_position.xyz, 1.0) * wmat);"
#else
"mat3x4 wmat;\n"
"wmat = m_bones[int(v_bone.x)] * v_weight.x;"
"wmat += m_bones[int(v_bone.y)] * v_weight.y;"
"wmat += m_bones[int(v_bone.z)] * v_weight.z;"
"wmat += m_bones[int(v_bone.w)] * v_weight.w;"
"n = vec4(v_normal.xyz, 0.0) * wmat;"
"t = vec4(v_svector.xyz, 0.0) * wmat;"
"b = vec4(v_tvector.xyz, 0.0) * wmat;"
"w = vec4(v_position.xyz, 1.0) * wmat;"
"return m_modelviewprojection * vec4(w, 1.0);"
#endif
"}\n"
"vec4 skeletaltransform_n(out vec3 n)"
"{"
#ifdef GLESONLY
"mat4 wmat;\n"
"wmat[0] = m_bones[0+3*int(v_bone.x)] * v_weight.x;\n"
"wmat[0] += m_bones[0+3*int(v_bone.y)] * v_weight.y;\n"
"wmat[0] += m_bones[0+3*int(v_bone.z)] * v_weight.z;\n"
"wmat[0] += m_bones[0+3*int(v_bone.w)] * v_weight.w;\n"
"wmat[1] = m_bones[1+3*int(v_bone.x)] * v_weight.x;\n"
"wmat[1] += m_bones[1+3*int(v_bone.y)] * v_weight.y;\n"
"wmat[1] += m_bones[1+3*int(v_bone.z)] * v_weight.z;\n"
"wmat[1] += m_bones[1+3*int(v_bone.w)] * v_weight.w;\n"
"wmat[2] = m_bones[2+3*int(v_bone.x)] * v_weight.x;\n"
"wmat[2] += m_bones[2+3*int(v_bone.y)] * v_weight.y;\n"
"wmat[2] += m_bones[2+3*int(v_bone.z)] * v_weight.z;\n"
"wmat[2] += m_bones[2+3*int(v_bone.w)] * v_weight.w;\n"
"wmat[3] = vec4(0.0,0.0,0.0,1.0);\n"
"n = (vec4(v_normal.xyz, 0.0) * wmat).xyz;"
"return m_modelviewprojection * (vec4(v_position.xyz, 1.0) * wmat);"
#else
"mat3x4 wmat;\n"
"wmat = m_bones[int(v_bone.x)] * v_weight.x;"
"wmat += m_bones[int(v_bone.y)] * v_weight.y;"
"wmat += m_bones[int(v_bone.z)] * v_weight.z;"
"wmat += m_bones[int(v_bone.w)] * v_weight.w;"
"n = vec4(v_normal.xyz, 0.0) * wmat;"
"return m_modelviewprojection * vec4(vec4(v_position.xyz, 1.0) * wmat, 1.0);"
#endif
"}\n"
"#ifdef PACKEDBONES\n"
"vec4 skeletaltransform()"
"{"
"mat4 wmat;"
"wmat[0] = m_bones[0+3*int(v_bone.x)] * v_weight.x;"
"wmat[0] += m_bones[0+3*int(v_bone.y)] * v_weight.y;"
"wmat[0] += m_bones[0+3*int(v_bone.z)] * v_weight.z;"
"wmat[0] += m_bones[0+3*int(v_bone.w)] * v_weight.w;"
"wmat[1] = m_bones[1+3*int(v_bone.x)] * v_weight.x;"
"wmat[1] += m_bones[1+3*int(v_bone.y)] * v_weight.y;"
"wmat[1] += m_bones[1+3*int(v_bone.z)] * v_weight.z;"
"wmat[1] += m_bones[1+3*int(v_bone.w)] * v_weight.w;"
"wmat[2] = m_bones[2+3*int(v_bone.x)] * v_weight.x;"
"wmat[2] += m_bones[2+3*int(v_bone.y)] * v_weight.y;"
"wmat[2] += m_bones[2+3*int(v_bone.z)] * v_weight.z;"
"wmat[2] += m_bones[2+3*int(v_bone.w)] * v_weight.w;"
"wmat[3] = vec4(0.0,0.0,0.0,1.0);\n"
"return m_modelviewprojection * (vec4(v_position.xyz, 1.0) * wmat);"
"}\n"
"vec4 skeletaltransform_nst(out vec3 n, out vec3 t, out vec3 b)"
"{"
"mat4 wmat;"
"wmat[0] = m_bones[0+3*int(v_bone.x)] * v_weight.x;"
"wmat[0] += m_bones[0+3*int(v_bone.y)] * v_weight.y;"
"wmat[0] += m_bones[0+3*int(v_bone.z)] * v_weight.z;"
"wmat[0] += m_bones[0+3*int(v_bone.w)] * v_weight.w;"
"wmat[1] = m_bones[1+3*int(v_bone.x)] * v_weight.x;"
"wmat[1] += m_bones[1+3*int(v_bone.y)] * v_weight.y;"
"wmat[1] += m_bones[1+3*int(v_bone.z)] * v_weight.z;"
"wmat[1] += m_bones[1+3*int(v_bone.w)] * v_weight.w;"
"wmat[2] = m_bones[2+3*int(v_bone.x)] * v_weight.x;"
"wmat[2] += m_bones[2+3*int(v_bone.y)] * v_weight.y;"
"wmat[2] += m_bones[2+3*int(v_bone.z)] * v_weight.z;"
"wmat[2] += m_bones[2+3*int(v_bone.w)] * v_weight.w;"
"wmat[3] = vec4(0.0,0.0,0.0,1.0);"
"n = (vec4(v_normal.xyz, 0.0) * wmat).xyz;"
"t = (vec4(v_svector.xyz, 0.0) * wmat).xyz;"
"b = (vec4(v_tvector.xyz, 0.0) * wmat).xyz;"
"return m_modelviewprojection * (vec4(v_position.xyz, 1.0) * wmat);"
"}\n"
"vec4 skeletaltransform_wnst(out vec3 w, out vec3 n, out vec3 t, out vec3 b)"
"{"
"mat4 wmat;"
"wmat[0] = m_bones[0+3*int(v_bone.x)] * v_weight.x;"
"wmat[0] += m_bones[0+3*int(v_bone.y)] * v_weight.y;"
"wmat[0] += m_bones[0+3*int(v_bone.z)] * v_weight.z;"
"wmat[0] += m_bones[0+3*int(v_bone.w)] * v_weight.w;"
"wmat[1] = m_bones[1+3*int(v_bone.x)] * v_weight.x;"
"wmat[1] += m_bones[1+3*int(v_bone.y)] * v_weight.y;"
"wmat[1] += m_bones[1+3*int(v_bone.z)] * v_weight.z;"
"wmat[1] += m_bones[1+3*int(v_bone.w)] * v_weight.w;"
"wmat[2] = m_bones[2+3*int(v_bone.x)] * v_weight.x;"
"wmat[2] += m_bones[2+3*int(v_bone.y)] * v_weight.y;"
"wmat[2] += m_bones[2+3*int(v_bone.z)] * v_weight.z;"
"wmat[2] += m_bones[2+3*int(v_bone.w)] * v_weight.w;"
"wmat[3] = vec4(0.0,0.0,0.0,1.0);"
"n = (vec4(v_normal.xyz, 0.0) * wmat).xyz;"
"t = (vec4(v_svector.xyz, 0.0) * wmat).xyz;"
"b = (vec4(v_tvector.xyz, 0.0) * wmat).xyz;"
"w = (vec4(v_position.xyz, 1.0) * wmat).xyz;"
"return m_modelviewprojection * (vec4(v_position.xyz, 1.0) * wmat);"
"}\n"
"vec4 skeletaltransform_n(out vec3 n)"
"{"
"mat4 wmat;"
"wmat[0] = m_bones[0+3*int(v_bone.x)] * v_weight.x;"
"wmat[0] += m_bones[0+3*int(v_bone.y)] * v_weight.y;"
"wmat[0] += m_bones[0+3*int(v_bone.z)] * v_weight.z;"
"wmat[0] += m_bones[0+3*int(v_bone.w)] * v_weight.w;"
"wmat[1] = m_bones[1+3*int(v_bone.x)] * v_weight.x;"
"wmat[1] += m_bones[1+3*int(v_bone.y)] * v_weight.y;"
"wmat[1] += m_bones[1+3*int(v_bone.z)] * v_weight.z;"
"wmat[1] += m_bones[1+3*int(v_bone.w)] * v_weight.w;"
"wmat[2] = m_bones[2+3*int(v_bone.x)] * v_weight.x;"
"wmat[2] += m_bones[2+3*int(v_bone.y)] * v_weight.y;"
"wmat[2] += m_bones[2+3*int(v_bone.z)] * v_weight.z;"
"wmat[2] += m_bones[2+3*int(v_bone.w)] * v_weight.w;"
"wmat[3] = vec4(0.0,0.0,0.0,1.0);"
"n = (vec4(v_normal.xyz, 0.0) * wmat).xyz;"
"return m_modelviewprojection * (vec4(v_position.xyz, 1.0) * wmat);"
"}\n"
"#else\n"
"vec4 skeletaltransform()"
"{"
"mat3x4 wmat;"
"wmat = m_bones[int(v_bone.x)] * v_weight.x;"
"wmat += m_bones[int(v_bone.y)] * v_weight.y;"
"wmat += m_bones[int(v_bone.z)] * v_weight.z;"
"wmat += m_bones[int(v_bone.w)] * v_weight.w;"
"return m_modelviewprojection * vec4(vec4(v_position.xyz, 1.0) * wmat, 1.0);"
"}\n"
"vec4 skeletaltransform_nst(out vec3 n, out vec3 t, out vec3 b)"
"{"
"mat3x4 wmat;"
"wmat = m_bones[int(v_bone.x)] * v_weight.x;"
"wmat += m_bones[int(v_bone.y)] * v_weight.y;"
"wmat += m_bones[int(v_bone.z)] * v_weight.z;"
"wmat += m_bones[int(v_bone.w)] * v_weight.w;"
"n = vec4(v_normal.xyz, 0.0) * wmat;"
"t = vec4(v_svector.xyz, 0.0) * wmat;"
"b = vec4(v_tvector.xyz, 0.0) * wmat;"
"return m_modelviewprojection * vec4(vec4(v_position.xyz, 1.0) * wmat, 1.0);"
"}\n"
"vec4 skeletaltransform_wnst(out vec3 w, out vec3 n, out vec3 t, out vec3 b)"
"{"
"mat3x4 wmat;"
"wmat = m_bones[int(v_bone.x)] * v_weight.x;"
"wmat += m_bones[int(v_bone.y)] * v_weight.y;"
"wmat += m_bones[int(v_bone.z)] * v_weight.z;"
"wmat += m_bones[int(v_bone.w)] * v_weight.w;"
"n = vec4(v_normal.xyz, 0.0) * wmat;"
"t = vec4(v_svector.xyz, 0.0) * wmat;"
"b = vec4(v_tvector.xyz, 0.0) * wmat;"
"w = vec4(v_position.xyz, 1.0) * wmat;"
"return m_modelviewprojection * vec4(w, 1.0);"
"}\n"
"vec4 skeletaltransform_n(out vec3 n)"
"{"
"mat3x4 wmat;"
"wmat = m_bones[int(v_bone.x)] * v_weight.x;"
"wmat += m_bones[int(v_bone.y)] * v_weight.y;"
"wmat += m_bones[int(v_bone.z)] * v_weight.z;"
"wmat += m_bones[int(v_bone.w)] * v_weight.w;"
"n = vec4(v_normal.xyz, 0.0) * wmat;"
"return m_modelviewprojection * vec4(vec4(v_position.xyz, 1.0) * wmat, 1.0);"
"}\n"
"#endif\n"
"#else\n"
"#define skeletaltransform ftetransform\n"
"vec4 skeletaltransform_wnst(out vec3 w, out vec3 n, out vec3 t, out vec3 b)"
@ -2342,21 +2346,16 @@ qboolean GLSlang_ValidateProgramPermu(program_t *prog, const char *name, unsigne
}
qboolean GLSlang_CreateProgramPermu(program_t *prog, const char *name, unsigned int permu, int ver, const char **precompilerconstants, const char *vert, const char *tcs, const char *tes, const char *geom, const char *frag, qboolean noerrors, vfsfile_t *blobfile)
{
#ifdef FTE_TARGET_WEB
//emscripten's uniform code results in excessive stalls that hinder usability.
//the uniforms required for bones basically turn it into a DOS attack.
//so lets just do all the work inside javascript instead... (oh god this is going to be painful)
if (permu & PERMUTATION_SKELETAL)
return false;
#endif
if (!ver)
{
ver = gl_config.gles?100:110;
#ifndef GLESONLY
if (permu & PERMUTATION_SKELETAL)
ver = 120;
#endif
if (gl_config.gles)
ver = 100;
else
{
ver = 110;
if (sh_config.maxver>=120 && (permu & PERMUTATION_SKELETAL))
ver = 120;
}
}
if ((permu & PERMUTATION_SKELETAL) && gl_config.maxattribs < 10)
return false; //can happen in gles2

View file

@ -2033,7 +2033,7 @@ static void Doom_LoadVerticies(char *name)
glc = 0;
gl1 = NULL;
}
else if (gl2[0] == *(int*)"gNd2")
else if (gl2[0] == (('g'<<0)|('N'<<8)|('d'<<16)|('2'<<24)))
{
gl2++;
glc = (fsize-4)/sizeof(int)/2;

View file

@ -64,7 +64,7 @@ static vec_t CastRay (struct relight_ctx_s *ctx, vec3_t p1, vec3_t p2)
if (ctx->shadows)
{
ctx->models[0]->funcs.NativeTrace (ctx->models[0], 0, 0, NULL, p1, p2, vec3_origin, vec3_origin, false, FTECONTENTS_SOLID, &trace);
ctx->models[0]->funcs.NativeTrace (ctx->models[0], 0, NULLFRAMESTATE, NULL, p1, p2, vec3_origin, vec3_origin, false, FTECONTENTS_SOLID, &trace);
if (trace.fraction < 1)
return -1;
}

View file

@ -696,6 +696,7 @@ typedef struct
qboolean progs_required; //no fixed function if this is true (d3d11, gles, gl3core)
unsigned int minver; //lowest glsl version usable
unsigned int maxver; //highest glsl version usable
unsigned int max_gpu_bones; //max number of bones supported by uniforms.
qboolean texfmt[PTI_MAX]; //which texture formats are supported (renderable not implied)
unsigned int texture_maxsize; //max size of a 2d texture

View file

@ -553,8 +553,8 @@ typedef struct
#define PROG_VERSION 6
#define PROG_KKQWSVVERSION 7
#define PROG_EXTENDEDVERSION 7
#define PROG_SECONDARYVERSION16 (*(int*)"1FTE" ^ *(int*)"PROG") //something unlikly and still meaningful (to me)
#define PROG_SECONDARYVERSION32 (*(int*)"1FTE" ^ *(int*)"32B ") //something unlikly and still meaningful (to me)
#define PROG_SECONDARYVERSION16 ((('1'<<0)|('F'<<8)|('T'<<16)|('E'<<24))^(('P'<<0)|('R'<<8)|('O'<<16)|('G'<<24))) //something unlikly and still meaningful (to me)
#define PROG_SECONDARYVERSION32 ((('1'<<0)|('F'<<8)|('T'<<16)|('E'<<24))^(('3'<<0)|('2'<<8)|('B'<<16)|(' '<<24))) //something unlikly and still meaningful (to me)
typedef struct
{
int version;

View file

@ -262,8 +262,8 @@ char *PDECL filefromprogs(pubprogfuncs_t *ppf, progsnum_t prnum, char *fname, si
return NULL;
if (pr_progstate[prnum].progs->version != PROG_EXTENDEDVERSION)
return NULL;
if (!pr_progstate[prnum].progs->secondaryversion != PROG_SECONDARYVERSION16 &&
!pr_progstate[prnum].progs->secondaryversion != PROG_SECONDARYVERSION32)
if (pr_progstate[prnum].progs->secondaryversion != PROG_SECONDARYVERSION16 &&
pr_progstate[prnum].progs->secondaryversion != PROG_SECONDARYVERSION32)
return NULL;
num = *(int*)((char *)pr_progstate[prnum].progs + pr_progstate[prnum].progs->ofsfiles);

View file

@ -874,7 +874,7 @@ void NPP_NQFlush(void)
requireextension = PEXT_TE_BULLET;
SV_MulticastProtExt(org, multicasttype, pr_global_struct->dimension_send, 0, requireextension);
buffer[1] = TEQW_EXPLOSIONNOSPRITE;
buffer[1] = TEQW_EXPLOSION_NOSPRITE;
}
break;
case TENQ_BEAM:

View file

@ -3346,7 +3346,7 @@ static void QCBUILTIN PF_sound (pubprogfuncs_t *prinst, struct globalvars_s *pr_
volume = G_FLOAT(OFS_PARM3) * 255;
attenuation = G_FLOAT(OFS_PARM4);
if (svprogfuncs->callargc > 5)
pitchadj = G_FLOAT(OFS_PARM5);
pitchadj = G_FLOAT(OFS_PARM5)*0.01;
else
pitchadj = 0;
if (svprogfuncs->callargc > 6)
@ -3386,7 +3386,7 @@ static void QCBUILTIN PF_pointsound(pubprogfuncs_t *prinst, struct globalvars_s
volume = G_FLOAT(OFS_PARM2);
attenuation = G_FLOAT(OFS_PARM3);
if (prinst->callargc >= 5)
pitchpct = G_FLOAT(OFS_PARM4);
pitchpct = G_FLOAT(OFS_PARM4)*0.01;
else
pitchpct = 0;
@ -5388,12 +5388,12 @@ void SV_point_tempentity (vec3_t o, int type, int count) //count (usually 1) is
MSG_WriteByte (&sv.nqmulticast, type); //nq doesn't have a count.
#endif
break;
case TEQW_EXPLOSIONNOSPRITE:
case TEQW_EXPLOSION_NOSPRITE:
MSG_WriteByte (&sv.multicast, TE_EXPLOSION);
#ifdef NQPROT
MSG_WriteByte (&sv.nqmulticast, TE_EXPLOSION);
#endif
type = TEQW_EXPLOSIONNOSPRITE;
type = TEQW_EXPLOSION_NOSPRITE;
split = PEXT_TE_BULLET;
break;
case TE_LIGHTNING1:
@ -8493,7 +8493,7 @@ static void QCBUILTIN PF_te_superspikequad(pubprogfuncs_t *prinst, struct global
static void QCBUILTIN PF_te_explosion(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
if (progstype != PROG_QW)
SV_point_tempentity(G_VECTOR(OFS_PARM0), TEQW_EXPLOSIONNOSPRITE, 1);
SV_point_tempentity(G_VECTOR(OFS_PARM0), TEQW_EXPLOSION_NOSPRITE, 1);
else
SV_point_tempentity(G_VECTOR(OFS_PARM0), TE_EXPLOSION, 1);
}
@ -11508,7 +11508,7 @@ void PR_DumpPlatform_f(void)
{"m_init", "void()", MENU},
{"m_shutdown", "void()", MENU},
{"m_draw", "void(vector screensize)", MENU, "Provides the menuqc with a chance to draw. Will be called even if the menu does not have focus, so be sure to avoid that. COMPAT: screensize is not provided in DP."},
{"m_drawloading", "void(vector screensize)", MENU, "Additional drawing function to draw loading screen overlays."},
{"m_drawloading", "void(vector screensize, float opaque)", MENU, "Additional drawing function to draw loading screens. If opaque is set, then this function must ensure that the entire screen is overdrawn (even if just by a black drawfill)."},
{"m_keydown", "void(float scan, float chr)", MENU},
{"m_keyup", "void(float scan, float chr)", MENU},
{"m_toggle", "void(float wantmode)", MENU},

View file

@ -2294,7 +2294,7 @@ qboolean Cull_Traceline(pvscamera_t *cameras, edict_t *seen)
for (c = 0; c < cameras->numents; c++)
{
tr.fraction = 1;
if (!sv.world.worldmodel->funcs.NativeTrace (sv.world.worldmodel, 1, 0, NULL, cameras->org[c], seen->v->origin, vec3_origin, vec3_origin, false, FTECONTENTS_SOLID, &tr))
if (!sv.world.worldmodel->funcs.NativeTrace (sv.world.worldmodel, 1, NULLFRAMESTATE, NULL, cameras->org[c], seen->v->origin, vec3_origin, vec3_origin, false, FTECONTENTS_SOLID, &tr))
return false; //wasn't blocked
}
@ -2308,7 +2308,7 @@ qboolean Cull_Traceline(pvscamera_t *cameras, edict_t *seen)
end[2] = seen->v->origin[2] + ((i&4)?seen->v->mins[2]+0.1:seen->v->maxs[2]);
tr.fraction = 1;
if (!sv.world.worldmodel->funcs.NativeTrace (sv.world.worldmodel, 1, 0, NULL, cameras->org[c], end, vec3_origin, vec3_origin, false, FTECONTENTS_SOLID, &tr))
if (!sv.world.worldmodel->funcs.NativeTrace (sv.world.worldmodel, 1, NULLFRAMESTATE, NULL, cameras->org[c], end, vec3_origin, vec3_origin, false, FTECONTENTS_SOLID, &tr))
return false; //this trace went through, so don't cull
}
}

View file

@ -27,7 +27,7 @@ cvar_t rank_parms_last = CVARD("rank_parms_last", "31", "Mod setting: the index
char rank_cvargroup[] = "server rankings";
#define RANKFILE_VERSION ((NUM_RANK_SPAWN_PARMS==32)?0:0x00000001)
#define RANKFILE_IDENT *(int*)"RANK"
#define RANKFILE_IDENT (('R'<<0)|('A'<<8)|('N'<<16)|('K'<<24))
static void READ_PLAYERSTATS(int x, rankstats_t *os)
{

View file

@ -1239,7 +1239,7 @@ struct startsoundcontext_s
unsigned int sampleidx;
unsigned int volume;
float attenuation;
float pitchpct;
float ratemul;
unsigned int chflags;
unsigned int timeofs;
};
@ -1263,7 +1263,7 @@ static void SV_SoundMulticast(client_t *client, sizebuf_t *msg, void *vctx)
field_mask |= NQSND_LARGESOUND;
if (client->fteprotocolextensions2 & PEXT2_REPLACEMENTDELTAS)
{
if (ctx->pitchpct && (ctx->pitchpct != 100))
if (ctx->ratemul && (ctx->ratemul != 1))
field_mask |= FTESND_PITCHADJ;
if (ctx->timeofs != 0)
field_mask |= FTESND_TIMEOFS;
@ -1273,6 +1273,14 @@ static void SV_SoundMulticast(client_t *client, sizebuf_t *msg, void *vctx)
if (field_mask > 0xff)
field_mask |= FTESND_MOREFLAGS;
}
if (client->protocol == SCP_DARKPLACES7)
{ //dpp7 clients get slightly higher precision
if (ctx->ratemul && (ctx->ratemul != 1))
{
field_mask |= DPSND_SPEEDUSHORT4000;
field_mask &= ~FTESND_PITCHADJ;
}
}
if (ISNQCLIENT(client) || ctx->chan >= 8 || ctx->ent >= 2048 || (field_mask & ~(NQSND_VOLUME|NQSND_ATTENUATION)))
{
@ -1293,7 +1301,7 @@ static void SV_SoundMulticast(client_t *client, sizebuf_t *msg, void *vctx)
if (field_mask & NQSND_ATTENUATION)
MSG_WriteByte (msg, bound(0, ctx->attenuation*64, 255));
if (field_mask & FTESND_PITCHADJ)
MSG_WriteByte (msg, bound(1, ctx->pitchpct, 255));
MSG_WriteByte (msg, bound(1, ctx->ratemul*100, 255));
if (field_mask & FTESND_TIMEOFS)
MSG_WriteShort (msg, bound(-32768, ctx->timeofs*1000, 32767));
if (field_mask & FTESND_VELOCITY)
@ -1302,6 +1310,8 @@ static void SV_SoundMulticast(client_t *client, sizebuf_t *msg, void *vctx)
MSG_WriteShort (msg, ctx->vel[1]*8);
MSG_WriteShort (msg, ctx->vel[2]*8);
}
if (field_mask & DPSND_SPEEDUSHORT4000)
MSG_WriteShort (msg, bound(1, ctx->ratemul*4000, 65535));
if (field_mask & NQSND_LARGEENTITY)
{
MSG_WriteEntity (msg, ctx->ent);
@ -1336,7 +1346,7 @@ static void SV_SoundMulticast(client_t *client, sizebuf_t *msg, void *vctx)
MSG_WriteCoord (msg, ctx->org[i]);
}
}
void SV_StartSound (int ent, vec3_t origin, float *velocity, int seenmask, int channel, const char *sample, int volume, float attenuation, float pitchadj, float timeofs, unsigned int chflags)
void SV_StartSound (int ent, vec3_t origin, float *velocity, int seenmask, int channel, const char *sample, int volume, float attenuation, float ratemul, float timeofs, unsigned int chflags)
{
qboolean use_phs;
qboolean reliable = chflags & CF_RELIABLE;
@ -1366,7 +1376,7 @@ void SV_StartSound (int ent, vec3_t origin, float *velocity, int seenmask, int c
ctx.chflags = chflags;
ctx.org = origin;
ctx.vel = velocity;
ctx.pitchpct = pitchadj;
ctx.ratemul = ratemul;
ctx.timeofs = timeofs;
ctx.volume = volume;

View file

@ -819,7 +819,7 @@ char *QDECL GHL_TraceTexture(hledict_t *againstent, vec3_t start, vec3_t end)
{
trace_t tr;
bi_trace();
sv.world.worldmodel->funcs.NativeTrace(sv.world.worldmodel, 0, 0, NULL, start, end, vec3_origin, vec3_origin, false, MASK_WORLDSOLID, &tr);
sv.world.worldmodel->funcs.NativeTrace(sv.world.worldmodel, 0, NULLFRAMESTATE, NULL, start, end, vec3_origin, vec3_origin, false, MASK_WORLDSOLID, &tr);
return tr.surface->name;
}
unk QDECL GHL_TraceSphere(unk){notimpf(__func__);}

View file

@ -421,7 +421,7 @@ static void SVQ3_Trace(q3trace_t *result, vec3_t start, vec3_t mins, vec3_t maxs
if (!maxs)
maxs = vec3_origin;
sv.world.worldmodel->funcs.NativeTrace(sv.world.worldmodel, 0, 0, NULL, start, end, mins, maxs, capsule, contentmask, &tr);
sv.world.worldmodel->funcs.NativeTrace(sv.world.worldmodel, 0, NULLFRAMESTATE, NULL, start, end, mins, maxs, capsule, contentmask, &tr);
result->allsolid = tr.allsolid;
result->contents = tr.contents;
VectorCopy(tr.endpos, result->endpos);

View file

@ -2077,7 +2077,7 @@ trace_t WorldQ2_Move (world_t *w, vec3_t start, vec3_t mins, vec3_t maxs, vec3_t
memset ( &clip, 0, sizeof ( moveclip_t ) );
// clip to world
w->worldmodel->funcs.NativeTrace(w->worldmodel, 0, 0, NULL, start, end, mins, maxs, false, hitcontentsmask, &clip.trace);
w->worldmodel->funcs.NativeTrace(w->worldmodel, 0, NULLFRAMESTATE, NULL, start, end, mins, maxs, false, hitcontentsmask, &clip.trace);
clip.trace.ent = ge->edicts;
if (clip.trace.fraction == 0)