fix TW patch/uncrouch bug.

use sdl 2.0.4 audio queuing output when mixerthread is disabled.
first attempt at BIH traces. doesn't yet work properly so disabled for now, but does fix some performance blackholes in xonotic.
first attempt at a lfield_nearclip value.
add VF_SKYROOM_CAMERA for easier skyrooms.


git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5442 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2019-04-01 10:16:36 +00:00
parent 8dc9a9a117
commit 974a8074a3
27 changed files with 829 additions and 182 deletions

View File

@ -345,6 +345,7 @@ typedef struct dlight_s
} face [6];
int style; //multiply by style values if > 0
float fov; //spotlight
float nearclip; //for spotlights...
struct dlight_s *next;
} dlight_t;

View File

@ -1158,6 +1158,9 @@ static void QCBUILTIN PF_R_DynamicLight_Set(pubprogfuncs_t *prinst, struct globa
case lfield_fov:
l->fov = G_FLOAT(OFS_PARM2);
break;
case lfield_nearclip:
l->nearclip = G_FLOAT(OFS_PARM2);
break;
case lfield_corona:
l->corona = G_FLOAT(OFS_PARM2);
break;
@ -1245,6 +1248,9 @@ static void QCBUILTIN PF_R_DynamicLight_Get(pubprogfuncs_t *prinst, struct globa
case lfield_fov:
G_FLOAT(OFS_RETURN) = l->fov;
break;
case lfield_nearclip:
G_FLOAT(OFS_PARM2) = l->nearclip;
break;
case lfield_corona:
G_FLOAT(OFS_RETURN) = l->corona;
break;
@ -1978,6 +1984,13 @@ nogameaccess:
*r = r_refdef.afov;
break;
case VF_SKYROOM_CAMERA:
if (r_refdef.skyroom_enabled)
VectorCopy(r_refdef.skyroom_pos, r);
else
VectorClear(r); //not really correct, but no other way to really signal this. -0? yuck.
break;
case VF_ORIGIN:
if (csqc_nogameaccess && prinst == csqc_world.progs)
goto nogameaccess;
@ -2178,6 +2191,11 @@ void QCBUILTIN PF_R_SetViewFlag(pubprogfuncs_t *prinst, struct globalvars_s *pr_
r_refdef.dirty |= RDFD_FOV;
break;
case VF_SKYROOM_CAMERA:
r_refdef.skyroom_enabled = true;
VectorCopy(p, r_refdef.skyroom_pos);
break;
case VF_ORIGIN:
VectorCopy(p, r_refdef.vieworg);
if (csqc_playerview)

View File

@ -3990,6 +3990,10 @@ void Surf_BuildModelLightmaps (model_t *m)
dst[2] = src[2];
}
break;
case PTI_RGB565:
for (; src < stop; dst += 2, src += 3)
*(unsigned short*)dst = ((src[0]>>3)<<11)|((src[1]>>2)<<5)|((src[2]>>3)<<0);
break;
case PTI_L8:
for (; src < stop; dst += 1, src += 3)
{

View File

@ -289,6 +289,9 @@ typedef struct
fogstate_t globalfog;
float hdr_value;
vec3_t skyroom_pos; /*the camera position for sky rooms*/
qboolean skyroom_enabled; /*whether a skyroom position is defined*/
pxrect_t pxrect; /*vrect, but in pixels rather than virtual coords*/
qboolean externalview; /*draw external models and not viewmodels*/
int recurse; /*in a mirror/portal/half way through drawing something else*/

View File

@ -898,8 +898,8 @@ void Renderer_Init(void)
Cvar_Register (&r_telestyle, GRAPHICALNICETIES);
Cvar_Register (&r_wireframe, GRAPHICALNICETIES);
Cvar_Register (&r_wireframe_smooth, GRAPHICALNICETIES);
Cvar_Register (&r_outline, GRAPHICALNICETIES);
Cvar_Register (&r_outline_width, GRAPHICALNICETIES);
// Cvar_Register (&r_outline, GRAPHICALNICETIES);
// Cvar_Register (&r_outline_width, GRAPHICALNICETIES);
Cvar_Register (&r_refract_fbo, GRAPHICALNICETIES);
Cvar_Register (&r_refractreflect_scale, GRAPHICALNICETIES);
Cvar_Register (&r_postprocshader, GRAPHICALNICETIES);
@ -2734,7 +2734,7 @@ qbyte *R_MarkLeaves_Q1 (qboolean getvisonly)
vis = cvis[portal] = r_refdef.forcedvis;
r_oldviewcluster = -1;
r_oldviewcluster2 = -1;
r_oldviewcluster2 = -2;
}
else
{
@ -2749,7 +2749,7 @@ qbyte *R_MarkLeaves_Q1 (qboolean getvisonly)
else
{
r_oldviewcluster = -1;
r_oldviewcluster2 = -1;
r_oldviewcluster2 = -2;
}
if (r_novis.ival)
@ -2760,7 +2760,7 @@ qbyte *R_MarkLeaves_Q1 (qboolean getvisonly)
memset (curframevis[portal].buffer, 0xff, curframevis[portal].buffersize);
r_oldviewcluster = -1;
r_oldviewcluster2 = -1;
r_oldviewcluster2 = -2;
}
else
{

View File

@ -61,8 +61,11 @@ static int (SDLCALL *SDL_CloseAudioDevice) (SDL_AudioDeviceID fd);
static int (SDLCALL *SDL_GetNumAudioDevices) (int iscapture);
static const char *(SDLCALL *SDL_GetAudioDeviceName) (int index, int iscapture);
static const char *(SDLCALL *SDL_GetError) (void);
#if SDL_VERSION_ATLEAST(2,0,5)
#if SDL_VERSION_ATLEAST(2,0,4)
static int (SDLCALL *SDL_QueueAudio) (SDL_AudioDeviceID dev, const void *data, uint32_t len);
static uint32_t (SDLCALL *SDL_GetQueuedAudioSize) (SDL_AudioDeviceID dev);
#endif
#if SDL_VERSION_ATLEAST(2,0,5)
static uint32_t (SDLCALL *SDL_DequeueAudio) (SDL_AudioDeviceID dev, void *data, uint32_t len);
#endif
static dllfunction_t sdl_funcs[] =
@ -77,8 +80,11 @@ static dllfunction_t sdl_funcs[] =
{(void*)&SDL_GetNumAudioDevices, "SDL_GetNumAudioDevices"},
{(void*)&SDL_GetAudioDeviceName, "SDL_GetAudioDeviceName"},
{(void*)&SDL_GetError, "SDL_GetError"},
#if SDL_VERSION_ATLEAST(2,0,5)
#if SDL_VERSION_ATLEAST(2,0,4)
{(void*)&SDL_QueueAudio, "SDL_QueueAudio"},
{(void*)&SDL_GetQueuedAudioSize, "SDL_GetQueuedAudioSize"},
#endif
#if SDL_VERSION_ATLEAST(2,0,5)
{(void*)&SDL_DequeueAudio, "SDL_DequeueAudio"},
#endif
{NULL, NULL}
@ -154,7 +160,7 @@ static void SSDL_Shutdown(soundcardinfo_t *sc)
#endif
sc->sn.buffer = NULL;
}
static unsigned int SSDL_GetDMAPos(soundcardinfo_t *sc)
static unsigned int SSDL_Callback_GetDMAPos(soundcardinfo_t *sc)
{
sc->sn.samplepos = sc->snd_sent / sc->sn.samplebytes;
return sc->sn.samplepos;
@ -162,7 +168,7 @@ static unsigned int SSDL_GetDMAPos(soundcardinfo_t *sc)
//this function is called from inside SDL.
//transfer the 'dma' buffer into the buffer it requests.
static void VARGS SSDL_Paint(void *userdata, qbyte *stream, int len)
static void VARGS SSDL_Callback_Paint(void *userdata, qbyte *stream, int len)
{
soundcardinfo_t *sc = userdata;
@ -194,7 +200,7 @@ static void VARGS SSDL_Paint(void *userdata, qbyte *stream, int len)
#endif
}
static void *SSDL_LockBuffer(soundcardinfo_t *sc, unsigned int *sampidx)
static void *SSDL_Callback_LockBuffer(soundcardinfo_t *sc, unsigned int *sampidx)
{
#if SDL_MAJOR_VERSION >= 2
SDL_LockAudioDevice(sc->audio_fd);
@ -205,7 +211,7 @@ static void *SSDL_LockBuffer(soundcardinfo_t *sc, unsigned int *sampidx)
return sc->sn.buffer;
}
static void SSDL_UnlockBuffer(soundcardinfo_t *sc, void *buffer)
static void SSDL_Callback_UnlockBuffer(soundcardinfo_t *sc, void *buffer)
{
#if SDL_MAJOR_VERSION >= 2
SDL_UnlockAudioDevice(sc->audio_fd);
@ -214,11 +220,42 @@ static void SSDL_UnlockBuffer(soundcardinfo_t *sc, void *buffer)
#endif
}
static void SSDL_Submit(soundcardinfo_t *sc, int start, int end)
static void SSDL_Callback_Submit(soundcardinfo_t *sc, int start, int end)
{
//SDL will call SSDL_Paint to paint when it's time, and the sound buffer is always there...
}
#if SDL_VERSION_ATLEAST(2,0,4)
static unsigned int SSDL_Queue_GetDMAPos(soundcardinfo_t *sc)
{ //keep proper track of how much data has actually been sent to the audio device.
//note that SDL may have already submitted more than this to the physical device.
//note: if we don't mix enough data then sdl will mix 0s for us.
uint32_t queued = SDL_GetQueuedAudioSize(sc->audio_fd);
extern cvar_t _snd_mixahead;
int ahead = (_snd_mixahead.value*sc->sn.speed) - (queued / (sc->sn.samplebytes*sc->sn.numchannels));
if (ahead < 0)
ahead = 0; //never behind
sc->samplequeue = -1; //return value is a desired timestamp
return sc->sn.samplepos + ahead*sc->sn.numchannels;
}
static void *SSDL_Queue_LockBuffer(soundcardinfo_t *sc, unsigned int *sampidx)
{ //queuing uses private memory, so no need to lock
*sampidx = 0; //don't bother ringing it.
return sc->sn.buffer;
}
static void SSDL_Queue_UnlockBuffer(soundcardinfo_t *sc, void *buffer)
{ //nor a need to unlock
}
static void SSDL_Queue_Submit(soundcardinfo_t *sc, int start, int end)
{
int bytecount = (end-start)*sc->sn.samplebytes*sc->sn.numchannels;
SDL_QueueAudio(sc->audio_fd, sc->sn.buffer, bytecount);
sc->sn.samplepos += bytecount/sc->sn.samplebytes;
}
#endif
static qboolean QDECL SDL_InitCard(soundcardinfo_t *sc, const char *devicename)
{
SDL_AudioSpec desired, obtained;
@ -234,7 +271,12 @@ static qboolean QDECL SDL_InitCard(soundcardinfo_t *sc, const char *devicename)
desired.freq = sc->sn.speed;
desired.channels = sc->sn.numchannels; //fixme!
desired.samples = 0x0200; //'Good values seem to range between 512 and 8192 inclusive, depending on the application and CPU speed.'
desired.callback = (void*)SSDL_Paint;
#if SDL_VERSION_ATLEAST(2,0,4)
if (!snd_mixerthread.ival)
desired.callback = NULL;
else
#endif
desired.callback = (void*)SSDL_Callback_Paint;
desired.userdata = sc;
memcpy(&obtained, &desired, sizeof(obtained));
@ -299,26 +341,44 @@ static qboolean QDECL SDL_InitCard(soundcardinfo_t *sc, const char *devicename)
break;
}
#ifdef SELFPAINT
sc->selfpainting = true;
#endif
Con_DPrintf("channels: %i\n", sc->sn.numchannels);
Con_DPrintf("Speed: %i\n", sc->sn.speed);
Con_DPrintf("Samplebits: %i\n", sc->sn.samplebytes*8);
Con_DPrintf("SDLSamples: %i (low for latency)\n", obtained.samples);
Con_DPrintf("FakeSamples: %i\n", sc->sn.samples);
#ifndef SELFPAINT
sc->sn.buffer = malloc(sc->sn.samples*sc->sn.samplebytes);
#endif
Con_DPrintf("Got sound %i-%i\n", obtained.freq, obtained.format);
sc->Lock = SSDL_LockBuffer;
sc->Unlock = SSDL_UnlockBuffer;
sc->Submit = SSDL_Submit;
sc->Shutdown = SSDL_Shutdown;
sc->GetDMAPos = SSDL_GetDMAPos;
#if SDL_VERSION_ATLEAST(2,0,4)
if (!obtained.callback)
{
sc->Lock = SSDL_Queue_LockBuffer;
sc->Unlock = SSDL_Queue_UnlockBuffer;
sc->Submit = SSDL_Queue_Submit;
sc->Shutdown = SSDL_Shutdown;
sc->GetDMAPos = SSDL_Queue_GetDMAPos;
sc->sn.buffer = malloc(sc->sn.samples*sc->sn.samplebytes);
Con_DPrintf("Using SDL audio queues\n");
}
else
#endif
{
sc->Lock = SSDL_Callback_LockBuffer;
sc->Unlock = SSDL_Callback_UnlockBuffer;
sc->Submit = SSDL_Callback_Submit;
sc->Shutdown = SSDL_Shutdown;
sc->GetDMAPos = SSDL_Callback_GetDMAPos;
#ifdef SELFPAINT
sc->selfpainting = true;
Con_DPrintf("Using SDL audio threading\n");
#else
sc->sn.buffer = malloc(sc->sn.samples*sc->sn.samplebytes);
Con_DPrintf("Using SDL audio callbacks\n");
#endif
}
#if SDL_MAJOR_VERSION >= 2
SDL_PauseAudioDevice(sc->audio_fd, 0);

View File

@ -755,7 +755,7 @@ void *Sys_GetAddressForName(dllhandle_t *module, const char *exportname)
// =======================================================================
//friendly way to crash, including stack traces. should help reduce gdb use.
#ifdef __linux__ /*should probably be GNUC but whatever*/
#if defined(__linux__) && defined(__GNUC__) /*should probably be GNUC but whatever*/
#include <execinfo.h>
#ifdef __i386__
#include <ucontext.h>
@ -927,7 +927,7 @@ int main (int c, const char **v)
}
#endif
#ifdef __linux__
#if defined(__linux__) && defined(__GNUC__)
if (!COM_CheckParm("-nodumpstack"))
{
struct sigaction act;

View File

@ -1502,6 +1502,8 @@ void V_ClearRefdef(playerview_t *pv)
r_refdef.drawsbar = (cl.intermissionmode == IM_NONE);
r_refdef.flags = 0;
r_refdef.skyroom_enabled = false;
r_refdef.areabitsknown = false;
// memset(r_refdef.postprocshader, 0, sizeof(r_refdef.postprocshader));

View File

@ -3153,7 +3153,7 @@ const gamemode_info_t gamemode_info[] = {
//because we can. quakespasm is hopefully close enough...
{"-fitz", NULL, "FTE-Quake DarkPlaces-Quake",{"id1/pak0.pak", "id1/quake.rc"},NQCFG"fps_preset spasm\n",{"id1"}, "NetQuake", "https://triptohell.info/downloadables.php" /*,"id1/pak0.pak|http://quakeservers.nquake.com/qsw106.zip|http://nquake.localghost.net/qsw106.zip|http://qw.quakephil.com/nquake/qsw106.zip|http://fnu.nquake.com/qsw106.zip"*/},
//because we can
{"-tenebrae", NULL, "FTE-Quake DarkPlaces-Quake",{"id1/pak0.pak", "id1/quake.rc"},QCFG"fps_preset tenebrae\n",{"id1","qw","*fte"},"Tenebrae", "https://triptohell.info/downloadables.php" /*,"id1/pak0.pak|http://quakeservers.nquake.com/qsw106.zip|http://nquake.localghost.net/qsw106.zip|http://qw.quakephil.com/nquake/qsw106.zip|http://fnu.nquake.com/qsw106.zip"*/},
{"-tenebrae", NULL, "FTE-Quake DarkPlaces-Quake",{"id1/pak0.pak", "id1/quake.rc"},NQCFG"fps_preset tenebrae\n",{"id1","qw","*fte"},"Tenebrae", "https://triptohell.info/downloadables.php" /*,"id1/pak0.pak|http://quakeservers.nquake.com/qsw106.zip|http://nquake.localghost.net/qsw106.zip|http://qw.quakephil.com/nquake/qsw106.zip|http://fnu.nquake.com/qsw106.zip"*/},
//quake's mission packs should not be favoured over the base game nor autodetected
//third part mods also tend to depend upon the mission packs for their huds, even if they don't use any other content.

View File

@ -38,6 +38,7 @@
cvar_t q3bsp_surf_meshcollision_flag = CVARD("q3bsp_surf_meshcollision_flag", "0x80000000", "The surfaceparm flag(s) that enables q3bsp trisoup collision");
cvar_t q3bsp_surf_meshcollision_force = CVARD("q3bsp_surf_meshcollision_force", "0", "Force mesh-based collisions on all q3bsp trisoup surfaces.");
cvar_t q3bsp_mergeq3lightmaps = CVARD("q3bsp_mergedlightmaps", "16", "Specifies the maximum number of lightmaps that may be merged for performance reasons. Unfortunately this breaks tcgen on lightmap passes - if you care, set this to 1.");
cvar_t q3bsp_bihtraces = CVARFD("_q3bsp_bihtraces", "0", CVAR_RENDERERLATCH, "Uses runtime-generated bih collision culling for faster traces.");
#if Q3SURF_NODRAW != TI_NODRAW
#error "nodraw isn't constant"
@ -60,6 +61,9 @@ static qboolean CM_NativeTrace(model_t *model, int forcehullnum, framestate_t *f
static unsigned int CM_NativeContents(struct model_s *model, int hulloverride, framestate_t *framestate, vec3_t axis[3], vec3_t p, vec3_t mins, vec3_t maxs);
static unsigned int Q2BSP_PointContents(model_t *mod, vec3_t axis[3], vec3_t p);
static int CM_PointCluster (model_t *mod, vec3_t p);
struct cminfo_s;
static struct bihnode_s *CM_BuildBIH (model_t *mod, struct cminfo_s *prv);
static unsigned int CM_PointContentsBIH (fte_restrict const struct bihnode_s *node, fte_restrict const vec3_t p);
#endif
float RadiusFromBounds (vec3_t mins, vec3_t maxs)
@ -126,7 +130,7 @@ void CalcSurfaceExtents (model_t *mod, msurface_t *s)
}
}
void AddPointToBounds (vec3_t v, vec3_t mins, vec3_t maxs)
void AddPointToBounds (const vec3_t v, vec3_t mins, vec3_t maxs)
{
int i;
vec_t val;
@ -411,6 +415,8 @@ typedef struct cminfo_s
q3cface_t *faces;
int numfaces;
#endif
struct bihnode_s *bihnodes;
} cminfo_t;
static q2mapsurface_t nullsurface;
@ -426,7 +432,7 @@ void CM_InitBoxHull (void);
static void CM_FinalizeBrush(q2cbrush_t *brush);
static void FloodAreaConnections (cminfo_t *prv);
qboolean BoundsIntersect (vec3_t mins1, vec3_t maxs1, vec3_t mins2, vec3_t maxs2)
qboolean BoundsIntersect (const vec3_t mins1, const vec3_t maxs1, const vec3_t mins2, const vec3_t maxs2)
{
return (mins1[0] <= maxs2[0] && mins1[1] <= maxs2[1] && mins1[2] <= maxs2[2] &&
maxs1[0] >= mins2[0] && maxs1[1] >= mins2[1] && maxs1[2] >= mins2[2]);
@ -695,7 +701,7 @@ static int CM_CreateFacetFromPoints(q2cbrush_t *facet, vec3_t *verts, int numver
{
int i, j;
int axis, dir;
vec3_t normal, mins, maxs;
vec3_t normal;
float d, dist;
mplane_t mainplane;
vec3_t vec, vec2;
@ -745,9 +751,9 @@ static int CM_CreateFacetFromPoints(q2cbrush_t *facet, vec3_t *verts, int numver
brushplanes[numbrushplanes].dist = mainplane.dist; numbrushplanes++;
// calculate mins & maxs
ClearBounds( mins, maxs );
ClearBounds( facet->absmins, facet->absmaxs );
for( i = 0; i < numverts; i++ )
AddPointToBounds( verts[i], mins, maxs );
AddPointToBounds( verts[i], facet->absmins, facet->absmaxs );
// add the axial planes
for( axis = 0; axis < 3; axis++ )
@ -765,9 +771,9 @@ static int CM_CreateFacetFromPoints(q2cbrush_t *facet, vec3_t *verts, int numver
VectorClear( normal );
normal[axis] = dir;
if( dir == 1 )
dist = maxs[axis];
dist = facet->absmaxs[axis];
else
dist = -mins[axis];
dist = -facet->absmins[axis];
VectorCopy( normal, brushplanes[numbrushplanes].normal );
brushplanes[numbrushplanes].dist = dist; numbrushplanes++;
@ -4593,6 +4599,10 @@ static cmodel_t *CM_LoadMap (model_t *mod, qbyte *filein, size_t filelen, qboole
mod->terrain = Mod_LoadTerrainInfo(mod, loadname, false);
#endif
if (q3bsp_bihtraces.ival)
prv->bihnodes = CM_BuildBIH(mod, prv);
else
prv->bihnodes = NULL;
return &prv->cmodels[0];
}
@ -4897,38 +4907,43 @@ int CM_PointContents (model_t *mod, vec3_t p)
if (!mod) // map not loaded
return 0;
i = CM_PointLeafnum_r (mod, p, mod->hulls[0].firstclipnode);
if (mod->fromgame == fg_quake2)
contents = mod->leafs[i].contents; //q2 is simple.
if (mod->fromgame != fg_quake2 && ((cminfo_t*)mod->meshinfo)->bihnodes)
contents = CM_PointContentsBIH(((cminfo_t*)mod->meshinfo)->bihnodes, p);
else
{
leaf = &mod->leafs[i];
i = CM_PointLeafnum_r (mod, p, mod->hulls[0].firstclipnode);
// if ( leaf->contents & CONTENTS_NODROP ) {
// contents = CONTENTS_NODROP;
// } else {
contents = 0;
// }
for (i = 0; i < leaf->numleafbrushes; i++)
if (mod->fromgame == fg_quake2)
contents = mod->leafs[i].contents; //q2 is simple.
else
{
brush = prv->leafbrushes[leaf->firstleafbrush + i];
leaf = &mod->leafs[i];
// check if brush actually adds something to contents
if ( (contents & brush->contents) == brush->contents ) {
continue;
}
// if ( leaf->contents & CONTENTS_NODROP ) {
// contents = CONTENTS_NODROP;
// } else {
contents = 0;
// }
brushside = brush->brushside;
for ( j = 0; j < brush->numsides; j++, brushside++ )
for (i = 0; i < leaf->numleafbrushes; i++)
{
if ( PlaneDiff (p, brushside->plane) > 0 )
break;
}
brush = prv->leafbrushes[leaf->firstleafbrush + i];
if (j == brush->numsides)
contents |= brush->contents;
// check if brush actually adds something to contents
if ( (contents & brush->contents) == brush->contents ) {
continue;
}
brushside = brush->brushside;
for ( j = 0; j < brush->numsides; j++, brushside++ )
{
if ( PlaneDiff (p, brushside->plane) > 0 )
break;
}
if (j == brush->numsides)
contents |= brush->contents;
}
}
}
#ifdef TERRAIN
@ -5611,17 +5626,60 @@ static void CM_TestBoxInPatch (vec3_t mins, vec3_t maxs, vec3_t p1,
{
int i, j;
mplane_t *plane;
vec3_t ofs;
float dist;
float d1, maxdist;
vec3_t ofs, ofs2;
float dist, thickness;
float d1;
q2cbrushside_t *side;
if (!brush->numsides)
return;
maxdist = -9999;
i = 0; //front plane
{
side = brush->brushside+i;
plane = side->plane;
for (i=0 ; i<brush->numsides ; i++)
switch(trace_shape)
{
default:
case shape_isbox:
for (j=0 ; j<3 ; j++)
{
if (plane->normal[j] < 0)
ofs[j] = maxs[j], ofs2[j] = mins[j];
else
ofs[j] = mins[j], ofs2[j] = maxs[j];
}
dist = DotProduct (ofs, plane->normal);
thickness = DotProduct (ofs2, plane->normal)-dist;
dist = plane->dist - dist;
break;
case shape_iscapsule:
dist = DotProduct(trace_up, plane->normal);
thickness = dist*(trace_capsulesize[(dist<0)?2:1]) + trace_capsulesize[0]*2;
dist = dist*(trace_capsulesize[(dist<0)?1:2]) - trace_capsulesize[0];
dist = plane->dist - dist;
break;
case shape_ispoint:
dist = plane->dist;
break;
}
d1 = DotProduct (p1, plane->normal) - dist;
// if completely in front of face, no intersection
if (d1 > 0)
return;
//point is behind the front plane, so no real intersection.
if (thickness < 0.25)
thickness = 0.25; //FIXME: patches should probably be infinitely thin, but that makes stuff messy.
if (d1 < -thickness)
return;
}
for (i=1 ; i<brush->numsides ; i++)
{
side = brush->brushside+i;
plane = side->plane;
@ -5657,15 +5715,8 @@ static void CM_TestBoxInPatch (vec3_t mins, vec3_t maxs, vec3_t p1,
// if completely in front of face, no intersection
if (d1 > 0)
return;
if (side->surface && d1 > maxdist)
maxdist = d1;
}
// FIXME
if (maxdist < -0.25)
return; // deep inside the patch
// inside this patch
trace->startsolid = trace->allsolid = true;
trace->contents = brush->contents;
@ -5951,6 +6002,386 @@ return;
CM_RecursiveHullCheck (mod, node->childnum[side^1], midf, p2f, mid, p2);
}
struct bihnode_s
{
//in a bih tree there are two values per node instead of a kd-tree's single midpoint
//this allows the two sides to overlap, which prevents the need to chop large objects into multiple leafs
//(it also allows gaps in the middle, which can further skip recursion)
enum {
BIH_X,
BIH_Y,
BIH_Z,
BIH_BRUSH,
BIH_PATCHBRUSH,
} type;
union
{
struct{
vec3_t temp_mins;
vec3_t temp_maxs;
int firstchild;
float cmin[2];
float cmax[2];
};
union bihdata_s{
q2cbrush_t *brush;
q2cbrush_t *patchbrush;
} data;
};
};
struct bihbox_s {
vec3_t min;
vec3_t max;
};
struct bihtrace_s
{
struct bihbox_s bounds;
struct bihbox_s size;
vec3_t expand;
qboolean negativedir[3];
vec_t *startpos; //bounds.[min|max]
vec3_t totalmove;
vec_t *endpos; //bounds.[min|max]
trace_t *trace;
};
static void CM_RecursiveBIHTrace (fte_restrict struct bihtrace_s *tr, fte_restrict const struct bihnode_s *node, fte_restrict struct bihbox_s *movesubbounds, fte_restrict struct bihbox_s *nodebox)
{
//if the tree were 1d, we wouldn't need to be so careful with the bounds, but if the trace is long then we want to avoid hitting all surfaces within that entire-map-encompassing move aabb
if (node->type > BIH_Z)
{ //leaf
if (node->type == BIH_BRUSH)
{
q2cbrush_t *b = node->data.brush;
if (b->contents & trace_contents)
if (BoundsIntersect(tr->bounds.min, tr->bounds.max, b->absmins, b->absmaxs))
CM_ClipBoxToBrush (tr->size.min, tr->size.max, tr->startpos, tr->endpos, tr->trace, b);
}
else //if (node->type == BIH_PATCHBRUSH)
{
q2cbrush_t *b = node->data.patchbrush;
if (b->contents & trace_contents)
if (BoundsIntersect(tr->bounds.min, tr->bounds.max, b->absmins, b->absmaxs))
CM_ClipBoxToPatch (tr->size.min, tr->size.max, tr->startpos, tr->endpos, tr->trace, b);
}
}
else
{ //node (x y or z)
struct bihbox_s bounds;
struct bihbox_s newbounds;
float distnear, distfar, nearfrac, farfrac, min, max;
unsigned int axis = node->type, child;
if (!tr->totalmove[axis])
{ //doesn't move with respect to this axis. don't allow infinities.
for (child = 0; child < 2; child++)
{ //only recurse if we are actually within the child
min = node->cmin[child] - tr->expand[axis];
max = node->cmax[child] + tr->expand[axis];
if (min <= tr->startpos[axis] && tr->startpos[axis] <= max)
{
bounds = *nodebox;
bounds.min[axis] = min;
bounds.max[axis] = max;
CM_RecursiveBIHTrace(tr, node+node->firstchild+child, movesubbounds, &bounds);
}
}
}
else if (tr->negativedir[axis])
{ //trace goes from right to left so favour the right.
for (child = 2; child-- > 0;)
{
bounds = *nodebox;
bounds.min[axis] = node->cmin[child] - tr->expand[axis];
bounds.max[axis] = node->cmax[child] + tr->expand[axis]; //expand the bounds according to the player's size
// CM_RecursiveBIHTrace(tr, node+node->firstchild+child, nodebox, &bounds);
// continue;
if (bounds.min[axis] > movesubbounds->max[axis])
continue; //(clipped) move bounds is outside this child
if (bounds.max[axis] < movesubbounds->min[axis])
continue; //(clipped) move bounds is outside this child
distnear = bounds.max[axis] - tr->startpos[axis];
nearfrac = distnear/tr->totalmove[axis];
// if (/*nearfrac <= trace_truefraction &&*/ tr->startpos[axis] >= bounds.min[axis] && tr->trace->endpos[axis] <= bounds.max[axis])
{
//we need to be careful when tracing, so that we can ignore children that do not overlap the trace
if (movesubbounds->min[axis] < bounds.min[axis])
{
distfar = bounds.min[axis] - tr->startpos[axis];
farfrac = distfar/tr->totalmove[axis];
VectorMA(tr->startpos, farfrac, tr->totalmove, newbounds.min); //clip the new movebounds (this is more to clip the other axis too)
}
else
VectorCopy(movesubbounds->min, newbounds.min);
if (bounds.max[axis] < movesubbounds->max[axis])
VectorMA(tr->startpos, nearfrac, tr->totalmove, newbounds.max);
else
VectorCopy(movesubbounds->max, newbounds.max);
CM_RecursiveBIHTrace(tr, node+node->firstchild+child, &newbounds, &bounds);
}
}
}
else
{ //trace goes from left to right
for (child = 0; child < 2; child++)
{
bounds = *nodebox;
bounds.min[axis] = node->cmin[child] - tr->expand[axis];
bounds.max[axis] = node->cmax[child] + tr->expand[axis]; //expand the bounds according to the player's size
// CM_RecursiveBIHTrace(tr, node+node->firstchild+child, nodebox, &bounds);
// continue;
if (bounds.min[axis] > movesubbounds->max[axis])
continue; //(clipped) move bounds is outside this child
if (bounds.max[axis] < movesubbounds->min[axis])
continue; //(clipped) move bounds is outside this child
distnear = bounds.min[axis] - tr->startpos[axis];
nearfrac = distnear/tr->totalmove[axis];
// if (/*nearfrac <= trace_truefraction &&*/ tr->startpos[axis] <= bounds.max[axis] && tr->trace->endpos[axis] >= bounds.min[axis])
{
//we need to be careful when tracing, so that we can ignore children that do not overlap the trace
if (movesubbounds->min[axis] < bounds.min[axis])
VectorMA(tr->startpos, nearfrac, tr->totalmove, newbounds.min); //clip the new movebounds (this is more to clip the other axis too)
else
VectorCopy(movesubbounds->min, newbounds.min);
if (bounds.max[axis] < movesubbounds->max[axis])
{
distfar = bounds.max[axis] - tr->startpos[axis];
farfrac = distfar/tr->totalmove[axis];
VectorMA(tr->startpos, farfrac, tr->totalmove, newbounds.max);
}
else
VectorCopy(movesubbounds->max, newbounds.max);
CM_RecursiveBIHTrace(tr, node+node->firstchild+child, &newbounds, &bounds);
}
}
}
}
}
static void CM_RecursiveBIHTest (fte_restrict struct bihtrace_s *tr, fte_restrict const struct bihnode_s *node)
{ //with BIH, its possible for a large child node to have a box larger than its sibling.
if (node->type > BIH_Z)
{ //leaf
if (node->type == BIH_BRUSH)
{
q2cbrush_t *b = node->data.brush;
if (b->contents & trace_contents)
// if (BoundsIntersect(tr->bounds.min, tr->bounds.max, b->absmins, b->absmaxs))
CM_TestBoxInBrush (tr->size.min, tr->size.max, tr->startpos, tr->trace, b);
}
else //if (node->type == BIH_PATCHBRUSH)
{
q2cbrush_t *b = node->data.patchbrush;
if (b->contents & trace_contents)
// if (BoundsIntersect(tr->bounds.min, tr->bounds.max, b->absmins, b->absmaxs))
CM_TestBoxInPatch (tr->size.min, tr->size.max, tr->startpos, tr->trace, b);
}
}
else
{ //node (x y or z)
float min; float max;
int axis = node->type;
min = node->cmin[0] - tr->expand[axis];
max = node->cmax[0] + tr->expand[axis]; //expand the bounds according to the player's size
//the point can potentially be within both children, or neither.
//it doesn't really matter which order we walk the tree, just be sure to do it efficiently.
if (min <= tr->startpos[axis] && tr->startpos[axis] <= max)
{
CM_RecursiveBIHTest(tr, node+node->firstchild+0);
if (trace_trace.allsolid)
return;
}
min = node->cmin[1] - tr->expand[axis];
max = node->cmax[1] + tr->expand[axis];
if (min <= tr->startpos[axis] && tr->startpos[axis] <= max)
return CM_RecursiveBIHTest(tr, node+node->firstchild+1);
}
}
static unsigned int CM_PointContentsBIH (fte_restrict const struct bihnode_s *node, fte_restrict const vec3_t p)
{
if (node->type > BIH_Z)
{ //leaf
if (node->type == BIH_BRUSH)
{
q2cbrush_t *b = node->data.brush;
q2cbrushside_t *brushside = b->brushside;
size_t j;
if (!BoundsIntersect(p, p, b->absmins, b->absmaxs))
return 0;
for ( j = 0; j < b->numsides; j++, brushside++ )
{
if ( PlaneDiff (p, brushside->plane) > 0 )
return 0;
}
return b->contents; //inside all planes
}
else //if (node->type == BIH_PATCHBRUSH)
{ //patches have no contents...
return 0;
}
}
else
{ //node (x y or z)
unsigned int contents;
//the point can potentially be within both children, or neither.
//it doesn't really matter which order we walk the tree, just be sure to do it efficiently.
if (node->cmin[0] <= p[node->type] && p[node->type] <= node->cmax[0])
contents = CM_PointContentsBIH(node+node->firstchild+0, p);
else
contents = 0;
if (node->cmin[1] <= p[node->type] && p[node->type] <= node->cmax[1])
contents |= CM_PointContentsBIH(node+node->firstchild+1, p);
return contents;
}
}
struct bihleaf_s
{
int type;
vec3_t mins;
vec3_t maxs;
union bihdata_s data;
};
static int QDECL CM_SortBIH_X (const void *va, const void *vb)
{
const struct bihleaf_s *a = va, *b = vb;
float am = a->maxs[0]+a->mins[0];
float bm = b->maxs[0]+b->mins[0];
if (am == bm)
return 0;
return am > bm;
}
static int QDECL CM_SortBIH_Y (const void *va, const void *vb)
{
const struct bihleaf_s *a = va, *b = vb;
float am = a->maxs[1]+a->mins[1];
float bm = b->maxs[1]+b->mins[1];
if (am == bm)
return 0;
return am > bm;
}
static int QDECL CM_SortBIH_Z (const void *va, const void *vb)
{
const struct bihleaf_s *a = va, *b = vb;
float am = a->maxs[2]+a->mins[2];
float bm = b->maxs[2]+b->mins[2];
if (am == bm)
return 0;
return am > bm;
}
static struct bihbox_s CM_BuildBIHNode (struct bihnode_s *node, struct bihnode_s **freenodes, struct bihleaf_s *leafs, size_t numleafs)
{
struct bihbox_s bounds;
if (numleafs == 1) //the leaf just gives the brush pointer.
{
VectorCopy(leafs[0].mins, bounds.min);
VectorCopy(leafs[0].maxs, bounds.max);
node->type = leafs[0].type;
node->data = leafs[0].data;
}
else
{
size_t i, j;
size_t numleft = numleafs / 2; //this ends up splitting at the median point.
size_t numright = numleafs - numleft;
struct bihbox_s left, right;
vec3_t size;
struct bihnode_s *cnodes;
VectorCopy(leafs[0].mins, bounds.min);
VectorCopy(leafs[0].maxs, bounds.max);
for (i = 1; i < numleafs; i++)
{
for(j = 0; j < 3; j++)
{
if (bounds.min[j] > leafs[i].mins[j])
bounds.min[j] = leafs[i].mins[j];
if (bounds.max[j] < leafs[i].maxs[j])
bounds.max[j] = leafs[i].maxs[j];
}
}
VectorSubtract(bounds.max, bounds.min, size);
if (size[0] > size[1] && size[0] > size[2])
{
qsort(leafs, numleafs, sizeof(*leafs), CM_SortBIH_X);
node->type = BIH_X;
}
else if (size[1] > size[2])
{
qsort(leafs, numleafs, sizeof(*leafs), CM_SortBIH_Y);
node->type = BIH_Y;
}
else
{
qsort(leafs, numleafs, sizeof(*leafs), CM_SortBIH_Z);
node->type = BIH_Z;
}
VectorCopy(bounds.min, node->temp_mins);
VectorCopy(bounds.max, node->temp_maxs);
cnodes = *freenodes;
*freenodes += 2;
node->firstchild = cnodes - node;
left = CM_BuildBIHNode (cnodes+0, freenodes, leafs, numleft);
right = CM_BuildBIHNode (cnodes+1, freenodes, &leafs[numleft], numright);
node->cmin[0] = left.min[node->type];
node->cmax[0] = left.max[node->type];
node->cmin[1] = right.min[node->type];
node->cmax[1] = right.max[node->type];
}
return bounds;
}
static struct bihnode_s *CM_BuildBIH (model_t *mod, cminfo_t *prv)
{
size_t numleafs, numnodes, i, j;
struct bihnode_s *nodes, *tmpnodes;
struct bihleaf_s *leafs, *leaf;
numleafs = prv->numbrushes;
for (i = 0; i < prv->numpatches; i++)
numleafs += prv->patches[i].numfacets;
numnodes = numleafs*2-1;
leafs = BZ_Malloc(sizeof(*leafs)*numleafs);
nodes = ZG_Malloc(&mod->memgroup, sizeof(*nodes)*numnodes);
for (leaf=leafs, i = 0; i < prv->numbrushes; i++, leaf++)
{
q2cbrush_t *b = &prv->brushes[i];
leaf->type = BIH_BRUSH;
leaf->data.brush = b;
VectorCopy(b->absmins, leaf->mins);
VectorCopy(b->absmaxs, leaf->maxs);
}
for (i = 0; i < prv->numpatches; i++)
{
q3cpatch_t *p = &prv->patches[i];
for (j = 0; j < p->numfacets; j++, leaf++)
{
leaf->type = BIH_PATCHBRUSH;
leaf->data.patchbrush = &p->facets[j];
VectorCopy(p->facets[j].absmins, leaf->mins);
VectorCopy(p->facets[j].absmaxs, leaf->maxs);
}
}
tmpnodes = nodes+1;
CM_BuildBIHNode(nodes, &tmpnodes, leafs, numleafs);
if (tmpnodes != nodes+numnodes)
Sys_Error("CM_BuildBIH: generated wrong number of nodes");
BZ_Free(leafs); //just for temporary storage so that CM_BuildBIHNode doesn't need to care
return nodes;
}
//======================================================================
@ -6019,6 +6450,9 @@ static trace_t CM_BoxTrace (model_t *mod, vec3_t start, vec3_t end,
trace_capsulesize[0] = ((maxs[0]-mins[0]) + (maxs[1]-mins[1]))/4.0;
trace_capsulesize[1] = maxs[2];
trace_capsulesize[2] = mins[2];
//make sure the mins_z/maxs_z isn't screwed.
// if (trace_capsulesize[1]-trace_capsulesize[2] < trace_capsulesize[0])
// trace_capsulesize[1] = trace_capsulesize[0]+trace_capsulesize[2];
ext = (trace_capsulesize[1] > -trace_capsulesize[2])?trace_capsulesize[1]:-trace_capsulesize[2];
trace_capsulesize[1] -= trace_capsulesize[0];
trace_capsulesize[2] += trace_capsulesize[0];
@ -6084,6 +6518,29 @@ static trace_t CM_BoxTrace (model_t *mod, vec3_t start, vec3_t end,
}
else
#endif
if (((cminfo_t*)mod->meshinfo)->bihnodes)
{
cminfo_t *prv = mod->meshinfo;
struct bihtrace_s tr;
int j;
VectorCopy(trace_mins, tr.size.min);
VectorCopy(trace_maxs, tr.size.max);
VectorCopy(trace_absmins, tr.bounds.min);
VectorCopy(trace_absmaxs, tr.bounds.max);
for (j = 0; j < 3; j++)
tr.negativedir[j] = (end[j] - start[j]) < 0;
VectorSubtract(end, start, tr.totalmove);
VectorCopy(trace_extents, tr.expand);
tr.startpos = trace_start;
tr.endpos = trace_end;
tr.trace = &trace_trace;
if (start[0] == end[0] && start[1] == end[1] && start[2] == end[2])
CM_RecursiveBIHTest(&tr, prv->bihnodes);
else
CM_RecursiveBIHTrace(&tr, prv->bihnodes, &tr.bounds, &tr.bounds);
}
else
//
// check for position test special case
//
@ -6846,6 +7303,7 @@ void CM_Init(void) //register cvars.
Cvar_Register(&q3bsp_surf_meshcollision_flag, MAPOPTIONS);
Cvar_Register(&q3bsp_surf_meshcollision_force, MAPOPTIONS);
Cvar_Register(&q3bsp_mergeq3lightmaps, MAPOPTIONS);
Cvar_Register(&q3bsp_bihtraces, MAPOPTIONS);
Cvar_Register(&r_subdivisions, MAPOPTIONS);
CM_InitBoxHull ();

View File

@ -126,7 +126,7 @@ typedef struct {
//void _VectorAdd (vec3_t veca, vec3_t vecb, vec3_t out);
//void _VectorCopy (vec3_t in, vec3_t out);
//void _VectorSubtract (vec3_t veca, vec3_t vecb, vec3_t out);
void AddPointToBounds (vec3_t v, vec3_t mins, vec3_t maxs);
void AddPointToBounds (const vec3_t v, vec3_t mins, vec3_t maxs);
float anglemod (float a);
void QDECL AngleVectors (const vec3_t angles, vec3_t forward, vec3_t right, vec3_t up);
void QDECL VectorAngles (float *forward, float *up, float *angles, qboolean meshpitch); //up may be NULL

View File

@ -122,15 +122,15 @@ typedef struct {
qboolean slidyslopes;
int stepheight;
qbyte coordsize;
qbyte coordsize; //FIXME: EZPEXT1_FLOATENTCOORDS should mean 4, but the result does not match ezquake/mvdsv which would result in inconsistencies. so player coords are rounded inconsistently.
unsigned int flags;
} movevars_t;
#define MOVEFLAG_VALID 0x80000000 //to signal that these are actually known. otherwise reserved.
#define MOVEFLAG_Q2AIRACCELERATE 0x00000001
//#define MOVEFLAG_Q2AIRACCELERATE 0x00000001
#define MOVEFLAG_NOGRAVITYONGROUND 0x00000002 //no slope sliding
#define MOVEFLAG_GRAVITYUNAFFECTEDBYTICRATE 0x00000004 //apply half-gravity both before AND after the move, which better matches the curve
//#define MOVEFLAG_GRAVITYUNAFFECTEDBYTICRATE 0x00000004 //apply half-gravity both before AND after the move, which better matches the curve
#define MOVEFLAG_QWEDGEBOX 0x00010000 //calculate edgefriction using tracebox and a buggy start pos
#define MOVEFLAG_QWCOMPAT (MOVEFLAG_NOGRAVITYONGROUND|MOVEFLAG_QWEDGEBOX)

View File

@ -730,6 +730,7 @@ typedef enum
VF_RT_DESTCOLOUR7 = 219,
VF_ENVMAP = 220, //cubemap image for reflectcube
VF_USERDATA = 221,
VF_SKYROOM_CAMERA = 222,
} viewflags;
/*FIXME: this should be changed*/
@ -777,8 +778,8 @@ enum lightfield_e
lfield_dietime=14,
lfield_rgbdecay=15,
lfield_radiusdecay=16,
lfield_stylestring=17
lfield_stylestring=17,
lfield_nearclip=18
};
enum csqc_input_event
{

View File

@ -1059,7 +1059,7 @@ void GLBE_SetupForShadowMap(dlight_t *dl, int texwidth, int texheight, float sha
{
extern cvar_t r_shadow_shadowmapping_bias;
extern cvar_t r_shadow_shadowmapping_nearclip;
float n = r_shadow_shadowmapping_nearclip.value;
float n = dl->nearclip?dl->nearclip:r_shadow_shadowmapping_nearclip.value;
float f = dl->radius;
float b = r_shadow_shadowmapping_bias.value;
@ -1303,13 +1303,12 @@ static void Shader_BindTextureForPass(int tmu, const shaderpass_t *pass)
GL_LazyBind(tmu, GL_TEXTURE_3D, t);
return;
case T_GEN_VIDEOMAP:
#ifdef HAVE_MEDIA_DECODER
case T_GEN_VIDEOMAP:
t = Media_UpdateForShader(pass->cin);
#else
t = shaderstate.curtexnums?shaderstate.curtexnums->base:r_nulltex;
#endif
break;
#endif
case T_GEN_CURRENTRENDER:
T_Gen_CurrentRender(tmu);
@ -4261,7 +4260,7 @@ qboolean GLBE_SelectDLight(dlight_t *dl, vec3_t colour, vec3_t axis[3], unsigned
float view[16];
float proj[16];
extern cvar_t r_shadow_shadowmapping_nearclip;
Matrix4x4_CM_Projection_Far(proj, dl->fov, dl->fov, r_shadow_shadowmapping_nearclip.value, dl->radius, false);
Matrix4x4_CM_Projection_Far(proj, dl->fov, dl->fov, dl->nearclip?dl->nearclip:r_shadow_shadowmapping_nearclip.value, dl->radius, false);
Matrix4x4_CM_ModelViewMatrixFromAxis(view, axis[0], axis[1], axis[2], dl->origin);
Matrix4_Multiply(proj, view, shaderstate.lightprojmatrix);
}
@ -5442,8 +5441,13 @@ static void GLBE_SubmitMeshesSortList(batch_t *sortlist)
{
if (shaderstate.mode == BEM_STANDARD || shaderstate.mode == BEM_DEPTHDARK)// || shaderstate.mode == BEM_WIREFRAME)
{
float il = shaderstate.identitylighting; //this stuff sucks!
if (R_DrawSkyChain(batch))
{
shaderstate.identitylighting = il;
continue;
}
shaderstate.identitylighting = il;
}
else if (/*shaderstate.mode != BEM_FOG &&*/ shaderstate.mode != BEM_CREPUSCULAR && shaderstate.mode != BEM_WIREFRAME)
continue;

View File

@ -1188,7 +1188,7 @@ qboolean R_LoadRTLights(void)
float radius;
vec3_t rgb;
vec3_t avel;
float fov;
float fov, nearclip;
unsigned int flags;
float coronascale;
@ -1294,7 +1294,7 @@ qboolean R_LoadRTLights(void)
file = COM_Parse(file);
flags |= file?atoi(com_token):LFLAG_REALTIMEMODE;
fov = avel[0] = avel[1] = avel[2] = 0;
nearclip = fov = avel[0] = avel[1] = avel[2] = 0;
*customstyle = 0;
while(file)
{
@ -1307,6 +1307,8 @@ qboolean R_LoadRTLights(void)
avel[2] = file?atof(com_token+5):0;
else if (!strncmp(com_token, "fov=", 4))
fov = file?atof(com_token+4):0;
else if (!strncmp(com_token, "nearclip=", 9))
nearclip = file?atof(com_token+9):0;
else if (!strncmp(com_token, "nostencil=", 10))
flags |= atoi(com_token+10)?LFLAG_SHADOWMAP:0;
else if (!strncmp(com_token, "crepuscular=", 12))
@ -1333,6 +1335,7 @@ qboolean R_LoadRTLights(void)
dl->die = 0;
dl->flags = flags;
dl->fov = fov;
dl->nearclip = nearclip;
dl->lightcolourscales[0] = ambientscale;
dl->lightcolourscales[1] = diffusescale;
dl->lightcolourscales[2] = specularscale;
@ -1418,6 +1421,8 @@ static void R_SaveRTLights_f(void)
//spotlights
if (light->fov)
VFS_PRINTF(f, " fov=%g", light->fov); //aka: outer cone
if (light->nearclip)
VFS_PRINTF(f, " nearclip=%g", light->nearclip); //aka: distance into a wall, for lights that are meant to appear to come from a texture
if (light->customstyle)
VFS_PRINTF(f, " \"stylestring=%s\"", light->customstyle); //aka: outer cone
@ -1588,6 +1593,8 @@ static int R_EditLight(dlight_t *dl, const char *cmd, int argc, const char *x, c
else if (!strcmp(cmd, "outercone") || !strcmp(cmd, "fov"))
dl->fov = atof(x);
else if (!strcmp(cmd, "nearclip"))
dl->nearclip = atof(x);
else if (!strcmp(cmd, "color") || !strcmp(cmd, "colour"))
{
dl->color[0] = atof(x);
@ -1676,6 +1683,7 @@ void R_EditLights_DrawInfo(void)
"RealTimeMode : %s\n"
" Spin : %.0f %.0f %.0f\n"
" Cone : %.0f\n"
" Nearclip : %.0f\n"
//"NoStencil : %s\n"
//"Crepuscular : %s\n"
//"Ortho : %s\n"
@ -1686,7 +1694,7 @@ void R_EditLights_DrawInfo(void)
,((dl->flags&LFLAG_NOSHADOWS)?"no":"yes"), dl->cubemapname, dl->coronascale
,dl->lightcolourscales[0], dl->lightcolourscales[1], dl->lightcolourscales[2]
,((dl->flags&LFLAG_NORMALMODE)?"yes":"no"), ((dl->flags&LFLAG_REALTIMEMODE)?"yes":"no")
,dl->rotation[0],dl->rotation[1],dl->rotation[2], dl->fov
,dl->rotation[0],dl->rotation[1],dl->rotation[2], dl->fov, dl->nearclip
//,((dl->flags&LFLAG_SHADOWMAP)?"no":"yes"),((dl->flags&LFLAG_CREPUSCULAR)?"yes":"no"),((dl->flags&LFLAG_ORTHO)?"yes":"no")
);
}
@ -1882,6 +1890,7 @@ static void R_EditLights_Edit_f(void)
Con_Printf("RealTimeMode : ^[%s\\type\\r_editlights_edit realtimemode %s^]\n", ((dl->flags&LFLAG_REALTIMEMODE)?"yes":"no"), ((dl->flags&LFLAG_REALTIMEMODE)?"yes":"no"));
Con_Printf("Spin : ^[%f %f %f\\type\\r_editlights_edit avel %g %g %g^]\n", dl->rotation[0],dl->rotation[1],dl->rotation[2], dl->origin[0],dl->origin[1],dl->origin[2]);
Con_Printf("Cone : ^[%f\\type\\r_editlights_edit outercone %g^]\n", dl->fov, dl->fov);
Con_Printf("NearClip : ^[%f\\type\\r_editlights_edit nearclip %g^]\n", dl->nearclip, dl->nearclip);
// Con_Printf("NoStencil : ^[%s\\type\\r_editlights_edit nostencil %s^]\n", ((dl->flags&LFLAG_SHADOWMAP)?"no":"yes"), ((dl->flags&LFLAG_SHADOWMAP)?"no":"yes"));
// Con_Printf("Crepuscular : ^[%s\\type\\r_editlights_edit crepuscular %s^]\n", ((dl->flags&LFLAG_CREPUSCULAR)?"yes":"no"), ((dl->flags&LFLAG_CREPUSCULAR)?"yes":"no"));
// Con_Printf("Ortho : ^[%s\\type\\r_editlights_edit ortho %s^]\n", ((dl->flags&LFLAG_ORTHO)?"yes":"no"), ((dl->flags&LFLAG_ORTHO)?"yes":"no"));

View File

@ -709,6 +709,11 @@ static int Shader_SetImageFlags(parsestate_t *parsestate, shaderpass_t *pass, ch
*name += 7;
flags |= IF_CLAMP;
}
else if (!Q_strnicmp(*name, "$premul:", 8))
{ //have the engine premultiply textures for you, instead of needing to do it in an editor.
*name += 8;
flags |= IF_PREMULTIPLYALPHA;
}
else if (!Q_strnicmp(*name, "$3d:", 4))
{
*name+=4;
@ -1120,19 +1125,10 @@ static void Shader_Portal (parsestate_t *ps, char **ptr)
static void Shader_PolygonOffset (parsestate_t *ps, char **ptr)
{
int m;
char *token;
shader_t *shader = ps->s;
float m = Shader_ParseFloat(shader, ptr, 1);
token = Shader_ParseString(ptr);
m = atoi(token);
if (m) {
shader->polyoffset.unit = -25 * m;
} else {
shader->polyoffset.unit = -25;
}
shader->polyoffset.unit = -25 * m;
shader->polyoffset.factor = -0.05;
shader->flags |= SHADER_POLYGONOFFSET; //some backends might be lazy and only allow simple values.
}
@ -5085,7 +5081,11 @@ done:;
if (pass->rgbgen != RGB_GEN_IDENTITY && pass->rgbgen != RGB_GEN_IDENTITY_OVERBRIGHT && pass->rgbgen != RGB_GEN_IDENTITY_LIGHTING)
weight += 100;
if (pass->texgen != T_GEN_ANIMMAP && pass->texgen != T_GEN_SINGLEMAP && pass->texgen != T_GEN_VIDEOMAP)
if (pass->texgen != T_GEN_ANIMMAP && pass->texgen != T_GEN_SINGLEMAP
#ifdef HAVE_MEDIA_DECODER
&& pass->texgen != T_GEN_VIDEOMAP
#endif
)
weight += 1000;
if ((pass->texgen == T_GEN_ANIMMAP || pass->texgen == T_GEN_SINGLEMAP) && pass->anim_frames[0] && *pass->anim_frames[0]->ident == '$')
@ -7163,7 +7163,46 @@ static char *Shader_DecomposePass(char *o, shaderpass_t *p, qboolean simple)
return o;
}
static char *Shader_DecomposeSubPass(char *o, shaderpass_t *p, qboolean simple)
static void Shader_DecomposeSubPassMap(char *o, shader_t *s, char *name, texid_t tex)
{
if (tex)
{
unsigned int flags = tex->flags;
sprintf(o, "%s \"%s\" %ix%i%s %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", name, tex->ident, tex->width, tex->height,
(tex->status == TEX_FAILED)?" FAILED":"",
Image_FormatName(tex->format),
(flags&IF_CLAMP)?" clamp":"",
(flags&IF_NOMIPMAP)?" nomipmap":"",
(flags&IF_NEAREST)?" nearest":"",
(flags&IF_LINEAR)?" linear":"",
(flags&IF_UIPIC)?" uipic":"",
(flags&IF_SRGB)?" srgb":"",
(flags&IF_NOPICMIP)?" nopicmip":"",
(flags&IF_NOALPHA)?" noalpha":"",
(flags&IF_NOGAMMA)?" noalpha":"",
(flags&IF_TEXTYPE)?" non-2d":"",
(flags&IF_MIPCAP)?"":" nomipcap",
(flags&IF_PREMULTIPLYALPHA)?" premultiply":"",
(flags&IF_NOSRGB)?" nosrgb":"",
(flags&IF_PALETTIZE)?" palettize":"",
(flags&IF_NOPURGE)?" nopurge":"",
(flags&IF_HIGHPRIORITY)?" highpri":"",
(flags&IF_LOWPRIORITY)?" lowpri":"",
(flags&IF_LOADNOW)?" loadnow":"",
(flags&IF_TRYBUMP)?" trybump":"",
(flags&IF_RENDERTARGET)?" rendertarget":"",
(flags&IF_EXACTEXTENSION)?" exactext":"",
(flags&IF_NOREPLACE)?" noreplace":"",
(flags&IF_NOWORKER)?" noworker":""
);
}
else
sprintf(o, "%s (%s)", name, "UNDEFINED");
}
static char *Shader_DecomposeSubPass(char *o, shader_t *s, shaderpass_t *p, qboolean simple)
{
int i;
if (!simple)
@ -7224,70 +7263,36 @@ static char *Shader_DecomposeSubPass(char *o, shaderpass_t *p, qboolean simple)
switch(p->texgen)
{
default: sprintf(o, "T_GEN_? "); break;
case T_GEN_SINGLEMAP:
if (p->anim_frames[0])
{
unsigned int flags = p->anim_frames[0]->flags;
sprintf(o, "singlemap \"%s\" %ix%i%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", p->anim_frames[0]->ident, p->anim_frames[0]->width, p->anim_frames[0]->height,
(p->anim_frames[0]->status == TEX_FAILED)?" FAILED":"",
(flags&IF_CLAMP)?" clamp":"",
(flags&IF_NOMIPMAP)?" nomipmap":"",
(flags&IF_NEAREST)?" nearest":"",
(flags&IF_LINEAR)?" linear":"",
(flags&IF_UIPIC)?" uipic":"",
(flags&IF_SRGB)?" srgb":"",
(flags&IF_NOPICMIP)?" nopicmip":"",
(flags&IF_NOALPHA)?" noalpha":"",
(flags&IF_NOGAMMA)?" noalpha":"",
(flags&IF_TEXTYPE)?" non-2d":"",
(flags&IF_MIPCAP)?"":" nomipcap",
(flags&IF_PREMULTIPLYALPHA)?" premultiply":"",
(flags&IF_NOSRGB)?" nosrgb":"",
(flags&IF_PALETTIZE)?" palettize":"",
(flags&IF_NOPURGE)?" nopurge":"",
(flags&IF_HIGHPRIORITY)?" highpri":"",
(flags&IF_LOWPRIORITY)?" lowpri":"",
(flags&IF_LOADNOW)?" loadnow":"",
(flags&IF_TRYBUMP)?" trybump":"",
(flags&IF_RENDERTARGET)?" rendertarget":"",
(flags&IF_EXACTEXTENSION)?" exactext":"",
(flags&IF_NOREPLACE)?" noreplace":"",
(flags&IF_NOWORKER)?" noworker":""
);
}
else
sprintf(o, "singlemap ");
break;
case T_GEN_ANIMMAP: sprintf(o, "animmap "); break;
case T_GEN_LIGHTMAP: sprintf(o, "lightmap "); break;
case T_GEN_DELUXMAP: sprintf(o, "deluxmap "); break;
case T_GEN_SHADOWMAP: sprintf(o, "shadowmap "); break;
case T_GEN_LIGHTCUBEMAP: sprintf(o, "lightcubemap "); break;
case T_GEN_DIFFUSE: sprintf(o, "diffuse "); break;
case T_GEN_NORMALMAP: sprintf(o, "normalmap "); break;
case T_GEN_SPECULAR: sprintf(o, "specular "); break;
case T_GEN_UPPEROVERLAY: sprintf(o, "upperoverlay "); break;
case T_GEN_LOWEROVERLAY: sprintf(o, "loweroverlay "); break;
case T_GEN_FULLBRIGHT: sprintf(o, "fullbright "); break;
case T_GEN_PALETTED: sprintf(o, "paletted "); break;
case T_GEN_REFLECTCUBE: sprintf(o, "reflectcube "); break;
case T_GEN_REFLECTMASK: sprintf(o, "reflectmask "); break;
case T_GEN_DISPLACEMENT: sprintf(o, "displacementmap "); break;
case T_GEN_CURRENTRENDER: sprintf(o, "currentrender "); break;
case T_GEN_SOURCECOLOUR: sprintf(o, "sourcecolour "); break;
case T_GEN_SOURCEDEPTH: sprintf(o, "sourcedepth "); break;
case T_GEN_REFLECTION: sprintf(o, "reflection "); break;
case T_GEN_REFRACTION: sprintf(o, "refraction "); break;
case T_GEN_REFRACTIONDEPTH: sprintf(o, "refractiondepth "); break;
case T_GEN_RIPPLEMAP: sprintf(o, "ripplemap "); break;
case T_GEN_SOURCECUBE: sprintf(o, "sourcecube "); break;
case T_GEN_VIDEOMAP: sprintf(o, "videomap "); break;
case T_GEN_CUBEMAP: sprintf(o, "cubemap "); break;
case T_GEN_3DMAP: sprintf(o, "3dmap "); break;
case T_GEN_GBUFFERCASE: sprintf(o, "gbuffer%i ",p->texgen-T_GEN_GBUFFER0); break;
case T_GEN_SINGLEMAP: Shader_DecomposeSubPassMap(o, s, "singlemap", p->anim_frames[0]); break;
case T_GEN_ANIMMAP: Shader_DecomposeSubPassMap(o, s, "animmap", p->anim_frames[0]); break;
#ifdef HAVE_MEDIA_DECODER
case T_GEN_VIDEOMAP: Shader_DecomposeSubPassMap(o, s, "videomap", Media_UpdateForShader(p->cin)); break;
#endif
case T_GEN_CUBEMAP: Shader_DecomposeSubPassMap(o, s, "cubemap", p->anim_frames[0]); break;
case T_GEN_3DMAP: Shader_DecomposeSubPassMap(o, s, "3dmap", p->anim_frames[0]); break;
case T_GEN_LIGHTMAP: sprintf(o, "lightmap "); break;
case T_GEN_DELUXMAP: sprintf(o, "deluxemap "); break;
case T_GEN_SHADOWMAP: sprintf(o, "shadowmap "); break;
case T_GEN_LIGHTCUBEMAP: sprintf(o, "lightcubemap "); break;
case T_GEN_DIFFUSE: Shader_DecomposeSubPassMap(o, s, "diffuse", s->defaulttextures[0].base); break;
case T_GEN_NORMALMAP: Shader_DecomposeSubPassMap(o, s, "normalmap", s->defaulttextures[0].bump); break;
case T_GEN_SPECULAR: Shader_DecomposeSubPassMap(o, s, "specular", s->defaulttextures[0].specular); break;
case T_GEN_UPPEROVERLAY: Shader_DecomposeSubPassMap(o, s, "upper", s->defaulttextures[0].upperoverlay); break;
case T_GEN_LOWEROVERLAY: Shader_DecomposeSubPassMap(o, s, "lower", s->defaulttextures[0].loweroverlay); break;
case T_GEN_FULLBRIGHT: Shader_DecomposeSubPassMap(o, s, "fullbright", s->defaulttextures[0].fullbright); break;
case T_GEN_PALETTED: Shader_DecomposeSubPassMap(o, s, "paletted", s->defaulttextures[0].paletted); break;
case T_GEN_REFLECTCUBE: Shader_DecomposeSubPassMap(o, s, "reflectcube", s->defaulttextures[0].reflectcube); break;
case T_GEN_REFLECTMASK: Shader_DecomposeSubPassMap(o, s, "reflectmask", s->defaulttextures[0].reflectmask); break;
case T_GEN_DISPLACEMENT: Shader_DecomposeSubPassMap(o, s, "displacement", s->defaulttextures[0].displacement); break;
case T_GEN_CURRENTRENDER: sprintf(o, "currentrender "); break;
case T_GEN_SOURCECOLOUR: sprintf(o, "sourcecolour"); break;
case T_GEN_SOURCEDEPTH: sprintf(o, "sourcedepth"); break;
case T_GEN_REFLECTION: sprintf(o, "reflection"); break;
case T_GEN_REFRACTION: sprintf(o, "refraction"); break;
case T_GEN_REFRACTIONDEPTH: sprintf(o, "refractiondepth"); break;
case T_GEN_RIPPLEMAP: sprintf(o, "ripplemap"); break;
case T_GEN_SOURCECUBE: sprintf(o, "sourcecube"); break;
case T_GEN_GBUFFERCASE: sprintf(o, "gbuffer%i ",p->texgen-T_GEN_GBUFFER0); break;
}
o+=strlen(o);
@ -7330,7 +7335,7 @@ char *Shader_Decompose(shader_t *s)
p = s->passes;
o = Shader_DecomposePass(o, p, true);
for (j = 0; j < s->numpasses; j++)
o = Shader_DecomposeSubPass(o, p+j, true);
o = Shader_DecomposeSubPass(o, s, p+j, true);
}
else
{
@ -7341,7 +7346,7 @@ char *Shader_Decompose(shader_t *s)
o = Shader_DecomposePass(o, p, false);
for (j = 0; j < p->numMergedPasses; j++)
o = Shader_DecomposeSubPass(o, p+j, !!p->prog);
o = Shader_DecomposeSubPass(o, s, p+j, !!p->prog);
sprintf(o, "}\n"); o+=strlen(o);
}
}

View File

@ -2223,7 +2223,7 @@ static void Sh_LightFrustumPlanes(dlight_t *l, vec3_t axis[3], vec4_t *planes, i
VectorCopy(l->origin, planes[4]);
VectorScale(axis[axis0], dir, planes[4]);
VectorNormalize(planes[4]);
planes[4][3] = r_shadow_shadowmapping_nearclip.value + DotProduct(planes[4], l->origin);
planes[4][3] = (l->nearclip?l->nearclip:r_shadow_shadowmapping_nearclip.value) + DotProduct(planes[4], l->origin);
for (i = 0; i < 4; i++)
{
@ -2497,7 +2497,7 @@ qboolean Sh_GenShadowMap (dlight_t *l, int lighttype, vec3_t axis[3], qbyte *lvi
smesh = SHM_BuildShadowMesh(l, lvis, (lighttype & LSHADER_ORTHO)?SMT_ORTHO:SMT_SHADOWMAP);
if (lighttype & LSHADER_SPOT)
Matrix4x4_CM_Projection_Far(r_refdef.m_projection_std, l->fov, l->fov, r_shadow_shadowmapping_nearclip.value, l->radius, false);
Matrix4x4_CM_Projection_Far(r_refdef.m_projection_std, l->fov, l->fov, l->nearclip?l->nearclip:r_shadow_shadowmapping_nearclip.value, l->radius, false);
else if (lighttype & LSHADER_ORTHO)
{
float xmin = -l->radius;
@ -2509,7 +2509,7 @@ qboolean Sh_GenShadowMap (dlight_t *l, int lighttype, vec3_t axis[3], qbyte *lvi
Matrix4x4_CM_Orthographic(r_refdef.m_projection_std, xmin, xmax, ymax, ymin, znear, zfar);
}
else
Matrix4x4_CM_Projection_Far(r_refdef.m_projection_std, 90, 90, r_shadow_shadowmapping_nearclip.value, l->radius, false);
Matrix4x4_CM_Projection_Far(r_refdef.m_projection_std, 90, 90, l->nearclip?l->nearclip:r_shadow_shadowmapping_nearclip.value, l->radius, false);
memcpy(r_refdef.m_projection_view, r_refdef.m_projection_std, sizeof(r_refdef.m_projection_view));

View File

@ -115,6 +115,74 @@ void R_DrawFastSky(batch_t *batch)
b.texture = NULL;
BE_SubmitBatch(&b);
}
void R_RenderScene (void);
qboolean R_DrawSkyroom(shader_t *skyshader)
{
#ifdef GLQUAKE
float vmat[16];
refdef_t oldrefdef;
if (qrenderer != QR_OPENGL)
return false; //FIXME
if (r_viewcluster == -1)
return false; //don't draw the skyroom if the camera is outside.
if (!r_refdef.skyroom_enabled || r_refdef.recurse >= R_MAX_RECURSE-1)
return false;
if (skyshader->numpasses)
{
shaderpass_t *pass = skyshader->passes;
if (pass->shaderbits & SBITS_ATEST_BITS) //alphatests
;
else if (pass->shaderbits & SBITS_MASK_BITS) //colormasks
;
else if ((pass->shaderbits & SBITS_BLEND_BITS) != 0 && (pass->shaderbits & SBITS_BLEND_BITS) != (SBITS_SRCBLEND_ONE|SBITS_DSTBLEND_ZERO)) //blendfunc
;
else
return false; //that shader looks like its opaque.
}
oldrefdef = r_refdef;
r_refdef.recurse+=1;
r_refdef.externalview = true;
r_refdef.skyroom_enabled = false;
/*work out where the camera should be (use the same angles)*/
VectorCopy(r_refdef.skyroom_pos, r_refdef.vieworg);
VectorCopy(r_refdef.skyroom_pos, r_refdef.pvsorigin);
Matrix4x4_CM_ModelViewMatrixFromAxis(vmat, vpn, vright, vup, r_refdef.vieworg);
R_SetFrustum (r_refdef.m_projection_std, vmat);
//now determine the stuff the backend will use.
memcpy(r_refdef.m_view, vmat, sizeof(float)*16);
VectorAngles(vpn, vup, r_refdef.viewangles, false);
VectorCopy(r_refdef.vieworg, r_origin);
Surf_SetupFrame();
//FIXME: just call Surf_DrawWorld instead?
R_RenderScene();
r_refdef = oldrefdef;
/*broken stuff*/
AngleVectors (r_refdef.viewangles, vpn, vright, vup);
VectorCopy (r_refdef.vieworg, r_origin);
GLBE_SelectEntity(&r_worldentity);
GL_ForceDepthWritable();
qglClear(GL_DEPTH_BUFFER_BIT);
currententity = NULL;
return true;
#else
return false;
#endif
}
/*
=================
GL_DrawSkyChain
@ -150,7 +218,11 @@ qboolean R_DrawSkyChain (batch_t *batch)
{
skyshader = batch->shader;
if (skyshader->prog) //glsl is expected to do the whole skybox/warpsky thing itself, with no assistance from this legacy code.
return false;
{
//if the first pass is transparent in some form, then be prepared to give it a skyroom behind.
R_DrawSkyroom(skyshader);
return false; //draw as normal...
}
}
if (skyshader->skydome)
@ -158,7 +230,12 @@ qboolean R_DrawSkyChain (batch_t *batch)
else
skyboxtex = NULL;
if (skyboxtex && TEXVALID(*skyboxtex))
if (R_DrawSkyroom(skyshader))
{
if (skyshader->numpasses)
GL_DrawSkySphere(batch, skyshader);
}
else if (skyboxtex && TEXVALID(*skyboxtex))
{ //draw a skybox if we were given the textures
R_CalcSkyChainBounds(batch);
GL_DrawSkyBox (skyboxtex, batch);

View File

@ -28,8 +28,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#pragma warning(disable : 4051) // ALPHA
#endif
void AddPointToBounds (vec3_t v, vec3_t mins, vec3_t maxs);
qboolean BoundsIntersect (vec3_t mins1, vec3_t maxs1, vec3_t mins2, vec3_t maxs2);
void AddPointToBounds (const vec3_t v, vec3_t mins, vec3_t maxs);
qboolean BoundsIntersect (const vec3_t mins1, const vec3_t maxs1, const vec3_t mins2, const vec3_t maxs2);
void ClearBounds (vec3_t mins, vec3_t maxs);
struct builddata_s

View File

@ -284,7 +284,9 @@ typedef struct shaderpass_s {
T_GEN_SOURCECUBE, //used for render-to-texture targets
#ifdef HAVE_MEDIA_DECODER
T_GEN_VIDEOMAP, //use the media playback as an image source, updating each frame for which it is visible
#endif
T_GEN_CUBEMAP, //use a cubemap instead, otherwise like T_GEN_SINGLEMAP
T_GEN_3DMAP, //use a 3d texture instead, otherwise T_GEN_SINGLEMAP.

View File

@ -12526,6 +12526,7 @@ void PR_DumpPlatform_f(void)
{"VF_RT_RIPPLE", "const float", CS|MENU, D("The texture name to use as a ripplemap (target for shaders with 'sort ripple'). Also used for shaders that specify $ripplemap. 1-based. Additional arguments are: format, sizexy."), VF_RT_RIPPLE},
{"VF_ENVMAP", "const float", CS|MENU, D("The cubemap name to use as a fallback for $reflectcube, if a shader was unable to load one. Note that this doesn't automatically change shader permutations or anything."), VF_ENVMAP},
{"VF_USERDATA", "const float", CS|MENU, D("Pointer (and byte size) to an array of vec4s. This data is then globally visible to all glsl via the w_user uniform."), VF_USERDATA},
{"VF_SKYROOM_CAMERA", "const float", CS, D("Controls the camera position of the skyroom (which will be drawn underneath transparent sky surfaces). This should move slightly with the real camera, but not so much that the skycamera enters walls. Requires a skyshader with a blend mode on the first pass (or no passes)."), VF_SKYROOM_CAMERA},
{"RF_VIEWMODEL", "const float", CS, D("Specifies that the entity is a view model, and that its origin is relative to the current view position. These entities are also subject to viewweapon bob."), CSQCRF_VIEWMODEL},
{"RF_EXTERNALMODEL", "const float", CS, D("Specifies that this entity should be displayed in mirrors (and may still cast shadows), but will not otherwise be visible."), CSQCRF_EXTERNALMODEL},
@ -12579,6 +12580,7 @@ void PR_DumpPlatform_f(void)
{"LFIELD_RGBDECAY", "const float", CS, NULL, lfield_rgbdecay},
{"LFIELD_RADIUSDECAY", "const float", CS, NULL, lfield_radiusdecay},
{"LFIELD_STYLESTRING", "const float", CS, NULL, lfield_stylestring},
{"LFIELD_NEARCLIP", "const float", CS, NULL, lfield_nearclip},
{"LFLAG_NORMALMODE", "const float", CS, NULL, LFLAG_NORMALMODE},
{"LFLAG_REALTIMEMODE", "const float", CS, NULL, LFLAG_REALTIMEMODE},

View File

@ -41,7 +41,7 @@ cvar_t sv_demoMaxDirCount = CVARD("sv_demoMaxDirCount", "500", "Maximum allowed
cvar_t sv_demoMaxDirAge = CVARD("sv_demoMaxDirAge", "0", "Maximum allowed age for demos, any older demos will be deleted when sv_demoClearOld is set (this doesn't prevent recording new demos).");
cvar_t sv_demoClearOld = CVARD("sv_demoClearOld", "0", "Automatically delete demos to keep the demos count reasonable.");
cvar_t sv_demoDir = CVARC("sv_demoDir", "demos", SV_DemoDir_Callback);
cvar_t sv_demoDirAlt = CVARD("sv_demoDir", "", "Provides a fallback directory name for demo downloads, for when sv_demoDir doesn't contain the requested demo.");
cvar_t sv_demoDirAlt = CVARCD("sv_demoDirAlt", "", SV_DemoDir_Callback, "Provides a fallback directory name for demo downloads, for when sv_demoDir doesn't contain the requested demo.");
cvar_t sv_demofps = CVAR("sv_demofps", "30");
cvar_t sv_demoPings = CVARD("sv_demoPings", "10", "Interval between ping updates in mvds");
cvar_t sv_demoMaxSize = CVARD("sv_demoMaxSize", "", "Demos will be truncated to be no larger than this size.");
@ -780,14 +780,14 @@ static void QDECL SV_DemoDir_Callback(struct cvar_s *var, char *oldvalue)
value = var->string;
if (!value[0] || value[0] == '/' || (value[0] == '\\' && value[1] == '\\'))
{
Cvar_ForceSet(&sv_demoDir, "demos");
Cvar_ForceSet(var, var->enginevalue);
return;
}
if (value[0] == '.' && value[1] == '.')
value += 2;
if (strstr(value,".."))
{
Cvar_ForceSet(&sv_demoDir, "demos");
Cvar_ForceSet(var, var->enginevalue);
return;
}
}

View File

@ -624,7 +624,7 @@ void Sys_Shutdown (void)
{
}
#ifdef __linux__ /*should probably be GNUC but whatever*/
#if defined(__linux__) && defined(__GNUC__)
#include <execinfo.h>
#ifdef __i386__
#include <ucontext.h>
@ -912,7 +912,7 @@ int main(int argc, char *argv[])
#ifdef __linux__
#if defined(__linux__) && defined(__GNUC__)
if (!COM_CheckParm("-nodumpstack"))
{
struct sigaction act;

View File

@ -6249,6 +6249,7 @@ ucmd_t nqucmds[] =
{"name", SVNQ_NQInfo_f},
{"color", SVNQ_NQColour_f},
{"playermodel", SVNQ_DPModel_f},
// {"pmodel", SVNQ_DPModel_f}, //nehahra
{"playerskin", SVNQ_DPSkin_f},
{"rate", SV_Rate_f},
{"rate_burstsize", NULL},

View File

@ -183,7 +183,7 @@ void main ()
//add on the fullbright
if (FULLBRIGHT)
gl_FragColor.rgb += texture2D(s_fullbright, tc).rgb;
}
}
//entity modifiers
gl_FragColor = gl_FragColor * e_colourident;

View File

@ -1705,12 +1705,12 @@ static texid_t SelectPassTexture(const shaderpass_t *pass)
case T_GEN_CURRENTRENDER:
return shaderstate.tex_currentrender;
case T_GEN_VIDEOMAP:
#ifdef HAVE_MEDIA_DECODER
case T_GEN_VIDEOMAP:
if (pass->cin)
return Media_UpdateForShader(pass->cin);
#endif
return r_nulltex;
#endif
case T_GEN_LIGHTCUBEMAP: //light's projected cubemap
if (shaderstate.curdlight)
@ -4268,7 +4268,7 @@ void VKBE_SetupLightCBuffer(dlight_t *l, vec3_t colour)
float view[16];
float proj[16];
extern cvar_t r_shadow_shadowmapping_nearclip;
Matrix4x4_CM_Projection_Far(proj, l->fov, l->fov, r_shadow_shadowmapping_nearclip.value, l->radius, false);
Matrix4x4_CM_Projection_Far(proj, l->fov, l->fov, l->nearclip?l->nearclip:r_shadow_shadowmapping_nearclip.value, l->radius, false);
Matrix4x4_CM_ModelViewMatrixFromAxis(view, l->axis[0], l->axis[1], l->axis[2], l->origin);
Matrix4_Multiply(proj, view, cbl->l_cubematrix);
}
@ -6166,7 +6166,7 @@ void VKBE_SetupForShadowMap(dlight_t *dl, int texwidth, int texheight, float sha
{
#define SHADOWMAP_SIZE 512
extern cvar_t r_shadow_shadowmapping_nearclip, r_shadow_shadowmapping_bias;
float nc = r_shadow_shadowmapping_nearclip.value;
float nc = dl->nearclip?dl->nearclip:r_shadow_shadowmapping_nearclip.value;
float bias = r_shadow_shadowmapping_bias.value;
//much of the projection matrix cancels out due to symmetry and stuff

View File

@ -86,7 +86,7 @@ void World_Bullet_Init(void)
{
physics_bullet_enable = pCvar_GetNVFDG("physics_bullet_enable", "1", 0, "", "Bullet");
physics_bullet_maxiterationsperframe = pCvar_GetNVFDG("physics_bullet_maxiterationsperframe", "10", 0, "FIXME: should be 1 when CCD is working properly.", "Bullet");
physics_bullet_framerate = pCvar_GetNVFDG("physics_bullet_framerate", "60", 0, "", "Bullet");
physics_bullet_framerate = pCvar_GetNVFDG("physics_bullet_framerate", "60", 0, "Bullet physics run at a fixed framerate in order to preserve numerical stability (interpolation is used to smooth out the result). Higher framerates are of course more demanding.", "Bullet");
pr_meshpitch = pCvar_GetNVFDG("r_meshpitch", "-1", 0, "", "Bullet");
}