committing for fixes for OMC

some minor changes. Mostly bug fixes and internal reorganisation.
Added code to provide an activex control as part of the npfte.dll plugin. If the dll is registered the regsvr32 way, the plugin can be used with IE as well.
fisheye/panoramic view enable is now controlled by rulesets instead of serverinfo.
server will list all pak files it has loaded. client will probably do the wrong thing and still needs fixing properly.

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@3910 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2011-10-27 16:16:29 +00:00
parent 5118de8bdd
commit f33873ddb7
78 changed files with 7999 additions and 6655 deletions

View file

@ -327,6 +327,7 @@ CLIENT_OBJS = \
cl_cg.o \ cl_cg.o \
clq3_parse.o \ clq3_parse.o \
pr_csqc.o \ pr_csqc.o \
pr_skelobj.o \
console.o \ console.o \
image.o \ image.o \
keys.o \ keys.o \

View file

@ -185,7 +185,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
// #define HLCLIENT 7 //we can run HL gamecode (not protocol compatible, set to 6 or 7) // #define HLCLIENT 7 //we can run HL gamecode (not protocol compatible, set to 6 or 7)
// #define HLSERVER 140 //we can run HL gamecode (not protocol compatible, set to 138 or 140) // #define HLSERVER 140 //we can run HL gamecode (not protocol compatible, set to 138 or 140)
#define NQPROT //server and client are capable of using quake1/netquake protocols. (qw is still prefered. uses the command 'nqconnect') #define NQPROT //server and client are capable of using quake1/netquake protocols. (qw is still prefered. uses the command 'nqconnect')
#define FISH //fisheye distortion stuff
#define ZLIB //zip/pk3 support #define ZLIB //zip/pk3 support
#define WEBSERVER //http/ftp servers #define WEBSERVER //http/ftp servers
#define WEBCLIENT //http/ftp clients. #define WEBCLIENT //http/ftp clients.

View file

@ -56,6 +56,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define BSPVERSION 29 #define BSPVERSION 29
//HalfLife support //HalfLife support
#define BSPVERSIONHL 30 #define BSPVERSIONHL 30
#define BSPVERSION_LONG (('B' << 24) | ('S' << 16) | ('P' << 8) | '2') /*RMQ support. 32bits instead of shorts for all but bbox sizes*/
typedef struct typedef struct
{ {
@ -169,13 +170,27 @@ typedef struct
short maxs[3]; short maxs[3];
unsigned short firstface; unsigned short firstface;
unsigned short numfaces; // counting both sides unsigned short numfaces; // counting both sides
} dnode_t; } dsnode_t;
typedef struct
{
int planenum;
int children[2]; // negative numbers are -(leafs+1), not nodes
short mins[3]; // for sphere culling
short maxs[3];
unsigned int firstface;
unsigned int numfaces; // counting both sides
} dlnode_t;
typedef struct typedef struct
{ {
int planenum; int planenum;
short children[2]; // negative numbers are contents short children[2]; // negative numbers are contents
} dclipnode_t; } dsclipnode_t;
typedef struct
{
int planenum;
int children[2]; // negative numbers are contents
} dlclipnode_t;
typedef struct typedef struct
{ {
@ -196,7 +211,11 @@ typedef struct texinfo_s
typedef struct typedef struct
{ {
unsigned short v[2]; // vertex numbers unsigned short v[2]; // vertex numbers
} dedge_t; } dsedge_t;
typedef struct
{
unsigned short v[2]; // vertex numbers
} dledge_t;
#define MAXLIGHTMAPS 4 #define MAXLIGHTMAPS 4
typedef struct typedef struct
@ -211,7 +230,20 @@ typedef struct
// lighting info // lighting info
qbyte styles[MAXLIGHTMAPS]; qbyte styles[MAXLIGHTMAPS];
int lightofs; // start of [numstyles*surfsize] samples int lightofs; // start of [numstyles*surfsize] samples
} dface_t; } dsface_t;
typedef struct
{
int planenum;
int side;
int firstedge; // we must support > 64k edges
int numedges;
int texinfo;
// lighting info
qbyte styles[MAXLIGHTMAPS];
int lightofs; // start of [numstyles*surfsize] samples
} dlface_t;
@ -236,7 +268,20 @@ typedef struct
unsigned short nummarksurfaces; unsigned short nummarksurfaces;
qbyte ambient_level[NUM_AMBIENTS]; qbyte ambient_level[NUM_AMBIENTS];
} dleaf_t; } dsleaf_t;
typedef struct
{
int contents;
int visofs; // -1 = no visibility info
short mins[3]; // for frustum culling
short maxs[3];
unsigned int firstmarksurface;
unsigned int nummarksurfaces;
qbyte ambient_level[NUM_AMBIENTS];
} dlleaf_t;
//============================================================================ //============================================================================

View file

@ -4,6 +4,8 @@
extern model_t *loadmodel; extern model_t *loadmodel;
extern char loadname[]; extern char loadname[];
qboolean r_loadbumpmapping;
extern cvar_t dpcompat_psa_ungroup;
//Common loader function. //Common loader function.
void Mod_DoCRC(model_t *mod, char *buffer, int buffersize) void Mod_DoCRC(model_t *mod, char *buffer, int buffersize)
@ -103,8 +105,8 @@ clampedmodel_t clampedmodel[] = {
{"progs/s_explod.spr", 1000}, {"progs/s_explod.spr", 1000},
//and now TF models //and now TF models
#ifndef _MSC_VER #ifdef warningmsg
#warning FIXME: these are placeholders #pragma warningmsg("FIXME: these are placeholders")
#endif #endif
{"progs/disp.mdl", 3000}, {"progs/disp.mdl", 3000},
{"progs/tf_flag.mdl", 3000}, {"progs/tf_flag.mdl", 3000},
@ -339,6 +341,7 @@ static void PSKGenMatrix(float x, float y, float z, float qx, float qy, float qz
#define restrict #define restrict
#if 0
/*transforms some skeletal vecV_t values*/ /*transforms some skeletal vecV_t values*/
static void Alias_TransformVerticies_V(float *bonepose, int vertcount, qbyte *bidx, float *weights, float *xyzin, float *restrict xyzout) static void Alias_TransformVerticies_V(float *bonepose, int vertcount, qbyte *bidx, float *weights, float *xyzin, float *restrict xyzout)
{ {
@ -376,6 +379,7 @@ static void Alias_TransformVerticies_V(float *bonepose, int vertcount, qbyte *bi
} }
} }
} }
#endif
/*transforms some skeletal vecV_t values*/ /*transforms some skeletal vecV_t values*/
static void Alias_TransformVerticies_VN(float *bonepose, int vertcount, qbyte *bidx, float *weights, static void Alias_TransformVerticies_VN(float *bonepose, int vertcount, qbyte *bidx, float *weights,
@ -423,7 +427,7 @@ static void Alias_TransformVerticies_VN(float *bonepose, int vertcount, qbyte *b
} }
} }
#if 0
/*transforms some skeletal vec3_t values*/ /*transforms some skeletal vec3_t values*/
static void Alias_TransformVerticies_3(float *bonepose, int vertcount, qbyte *bidx, float *weights, float *xyzin, float *restrict xyzout) static void Alias_TransformVerticies_3(float *bonepose, int vertcount, qbyte *bidx, float *weights, float *xyzin, float *restrict xyzout)
{ {
@ -461,6 +465,7 @@ static void Alias_TransformVerticies_3(float *bonepose, int vertcount, qbyte *bi
} }
} }
} }
#endif
static void Alias_TransformVerticies_SW(float *bonepose, galisskeletaltransforms_t *weights, int numweights, vecV_t *xyzout, vec3_t *normout) static void Alias_TransformVerticies_SW(float *bonepose, galisskeletaltransforms_t *weights, int numweights, vecV_t *xyzout, vec3_t *normout)
{ {
@ -1084,7 +1089,6 @@ struct
void R_LightArraysByte_BGR(const entity_t *entity, vecV_t *coords, byte_vec4_t *colours, int vertcount, vec3_t *normals) void R_LightArraysByte_BGR(const entity_t *entity, vecV_t *coords, byte_vec4_t *colours, int vertcount, vec3_t *normals)
{ {
//extern cvar_t r_vertexdlights; //unused
int i; int i;
int c; int c;
float l; float l;
@ -1129,7 +1133,7 @@ void R_LightArraysByte_BGR(const entity_t *entity, vecV_t *coords, byte_vec4_t *
} }
} }
void R_LightArrays(const entity_t *entity, vecV_t *coords, avec4_t *colours, int vertcount, vec3_t *normals) void R_LightArrays(const entity_t *entity, vecV_t *coords, avec4_t *colours, int vertcount, vec3_t *normals, float scale)
{ {
extern cvar_t r_vertexdlights; extern cvar_t r_vertexdlights;
int i; int i;
@ -1148,6 +1152,9 @@ void R_LightArrays(const entity_t *entity, vecV_t *coords, avec4_t *colours, int
} }
else else
{ {
vec3_t la, lr;
VectorScale(entity->light_avg, scale, la);
VectorScale(entity->light_range, scale, lr);
#ifdef SSE_INTRINSICS #ifdef SSE_INTRINSICS
__m128 va, vs, vl, vr; __m128 va, vs, vl, vr;
va = _mm_load_ps(ambientlight); va = _mm_load_ps(ambientlight);
@ -1167,9 +1174,9 @@ void R_LightArrays(const entity_t *entity, vecV_t *coords, avec4_t *colours, int
_mm_storeu_ps(colours[i], vr); _mm_storeu_ps(colours[i], vr);
//stomp on colour[i][3] (will be set to 1) //stomp on colour[i][3] (will be set to 1)
#else #else
colours[i][0] = l*entity->light_range[0]+entity->light_avg[0]; colours[i][0] = l*lr[0]+la[0];
colours[i][1] = l*entity->light_range[1]+entity->light_avg[1]; colours[i][1] = l*lr[1]+la[1];
colours[i][2] = l*entity->light_range[2]+entity->light_avg[2]; colours[i][2] = l*lr[2]+la[2];
#endif #endif
} }
} }
@ -2184,8 +2191,8 @@ static void *Alias_LoadFrameGroup (daliasframetype_t *pframetype, int *seamremap
pose->ofssvector = (char *)svec - (char *)pose; pose->ofssvector = (char *)svec - (char *)pose;
pose->ofstvector = (char *)tvec - (char *)pose; pose->ofstvector = (char *)tvec - (char *)pose;
#else #else
#ifdef _MSC_VER #ifdef warningmsg
#pragma message("wasted memory") #pragma warningmsg("wasted memory")
#endif #endif
#endif #endif
@ -2366,7 +2373,6 @@ static void *Q1_LoadSkins_SV (daliasskintype_t *pskintype, qboolean alpha)
#if defined(GLQUAKE) || defined(D3DQUAKE) #if defined(GLQUAKE) || defined(D3DQUAKE)
static void *Q1_LoadSkins_GL (daliasskintype_t *pskintype, unsigned int skintranstype) static void *Q1_LoadSkins_GL (daliasskintype_t *pskintype, unsigned int skintranstype)
{ {
extern cvar_t gl_bump;
texnums_t *texnums; texnums_t *texnums;
char skinname[MAX_QPATH]; char skinname[MAX_QPATH];
int i; int i;
@ -2397,9 +2403,12 @@ static void *Q1_LoadSkins_GL (daliasskintype_t *pskintype, unsigned int skintran
texture = R_LoadReplacementTexture(skinname, "models", IF_NOALPHA); texture = R_LoadReplacementTexture(skinname, "models", IF_NOALPHA);
if (TEXVALID(texture)) if (TEXVALID(texture))
{ {
snprintf(skinname, sizeof(skinname), "%s_%i_luma", loadmodel->name, i); if (TEXVALID(texture) && r_fb_models.ival)
fbtexture = R_LoadReplacementTexture(skinname, "models", 0); {
if (gl_bump.ival) snprintf(skinname, sizeof(skinname), "%s_%i_luma", loadmodel->name, i);
fbtexture = R_LoadReplacementTexture(skinname, "models", 0);
}
if (r_loadbumpmapping)
{ {
snprintf(skinname, sizeof(skinname), "%s_%i_bump", loadmodel->name, i); snprintf(skinname, sizeof(skinname), "%s_%i_bump", loadmodel->name, i);
bumptexture = R_LoadBumpmapTexture(skinname, "models"); bumptexture = R_LoadBumpmapTexture(skinname, "models");
@ -2414,7 +2423,7 @@ static void *Q1_LoadSkins_GL (daliasskintype_t *pskintype, unsigned int skintran
snprintf(skinname, sizeof(skinname), "%s_%i_luma", loadname, i); snprintf(skinname, sizeof(skinname), "%s_%i_luma", loadname, i);
fbtexture = R_LoadReplacementTexture(skinname, "models", 0); fbtexture = R_LoadReplacementTexture(skinname, "models", 0);
} }
if (TEXVALID(texture) && gl_bump.ival) if (TEXVALID(texture) && r_loadbumpmapping)
{ {
snprintf(skinname, sizeof(skinname), "%s_%i_bump", loadname, i); snprintf(skinname, sizeof(skinname), "%s_%i_bump", loadname, i);
bumptexture = R_LoadBumpmapTexture(skinname, "models"); bumptexture = R_LoadBumpmapTexture(skinname, "models");
@ -2444,7 +2453,7 @@ static void *Q1_LoadSkins_GL (daliasskintype_t *pskintype, unsigned int skintran
snprintf(skinname, sizeof(skinname), "%s__%i_luma", loadname, i); snprintf(skinname, sizeof(skinname), "%s__%i_luma", loadname, i);
fbtexture = R_LoadTextureFB(skinname, outskin->skinwidth, outskin->skinheight, saved, IF_NOGAMMA); fbtexture = R_LoadTextureFB(skinname, outskin->skinwidth, outskin->skinheight, saved, IF_NOGAMMA);
} }
if (gl_bump.ival) if (r_loadbumpmapping)
{ {
snprintf(skinname, sizeof(skinname), "%s__%i_bump", loadname, i); snprintf(skinname, sizeof(skinname), "%s__%i_bump", loadname, i);
bumptexture = R_LoadTexture8BumpPal(skinname, outskin->skinwidth, outskin->skinheight, saved, IF_NOGAMMA); bumptexture = R_LoadTexture8BumpPal(skinname, outskin->skinwidth, outskin->skinheight, saved, IF_NOGAMMA);
@ -2601,12 +2610,10 @@ static void *Q1_LoadSkins_GL (daliasskintype_t *pskintype, unsigned int skintran
Q_snprintfz(skinname, sizeof(skinname), "%s_%i_%i", loadname, i, t); Q_snprintfz(skinname, sizeof(skinname), "%s_%i_%i", loadname, i, t);
texnums->shader = R_RegisterSkin(skinname, loadmodel->name); texnums->shader = R_RegisterSkin(skinname, loadmodel->name);
texnums->base = texture; TEXASSIGN(texnums->base, texture);
texnums->fullbright = fbtexture; TEXASSIGN(texnums->fullbright, fbtexture);
TEXASSIGN(texnums->loweroverlay, r_nulltex);
//13/4/08 IMPLEMENTME TEXASSIGN(texnums->upperoverlay, r_nulltex);
texnums->loweroverlay = r_nulltex;
texnums->upperoverlay = r_nulltex;
R_BuildDefaultTexnums(texnums, texnums->shader); R_BuildDefaultTexnums(texnums, texnums->shader);
} }
@ -2710,11 +2717,11 @@ qboolean Mod_LoadQ1Model (model_t *mod, void *buffer)
//skins //skins
skinstart = (daliasskintype_t *)((char*)pq1inmodel+hdrsize); skinstart = (daliasskintype_t *)((char*)pq1inmodel+hdrsize);
if( mod->flags & EFH2_HOLEY ) if( mod->flags & MFH2_HOLEY )
skintranstype = 3; //hexen2 skintranstype = 3; //hexen2
else if( mod->flags & EFH2_TRANSPARENT ) else if( mod->flags & MFH2_TRANSPARENT )
skintranstype = 2; //hexen2 skintranstype = 2; //hexen2
else if( mod->flags & EFH2_SPECIAL_TRANS ) else if( mod->flags & MFH2_SPECIAL_TRANS )
skintranstype = 4; //hexen2 skintranstype = 4; //hexen2
else else
skintranstype = 0; skintranstype = 0;
@ -2984,7 +2991,7 @@ static void Q2_LoadSkins(md2_t *pq2inmodel, char *skins)
outskin->texnums=1; outskin->texnums=1;
COM_CleanUpPath(skins); //blooming tanks. COM_CleanUpPath(skins); //blooming tanks.
texnums->base = R_LoadReplacementTexture(skins, "models", IF_NOALPHA); TEXASSIGN(texnums->base, R_LoadReplacementTexture(skins, "models", IF_NOALPHA));
texnums->shader = R_RegisterSkin(skins, loadmodel->name); texnums->shader = R_RegisterSkin(skins, loadmodel->name);
R_BuildDefaultTexnums(texnums, texnums->shader); R_BuildDefaultTexnums(texnums, texnums->shader);
@ -3389,8 +3396,8 @@ qboolean Mod_GetTag(model_t *model, int tagnum, framestate_t *fstate, float *res
float f1time, f2time; float f1time, f2time;
float f2ness; float f2ness;
#ifdef _MSC_VER #ifdef warningmsg
#pragma message("fixme") #pragma warningmsg("fixme: no base info")
#endif #endif
frame1 = fstate->g[FS_REG].frame[0]; frame1 = fstate->g[FS_REG].frame[0];
frame2 = fstate->g[FS_REG].frame[1]; frame2 = fstate->g[FS_REG].frame[1];
@ -4466,13 +4473,12 @@ qboolean Mod_LoadPSKModel(model_t *mod, void *buffer)
galiasskin_t *skin; galiasskin_t *skin;
texnums_t *gtexnums; texnums_t *gtexnums;
#endif #endif
galisskeletaltransforms_t *trans;
galiasbone_t *bones; galiasbone_t *bones;
galiasgroup_t *group; galiasgroup_t *group;
float *animmatrix, *basematrix, *basematrix_inverse; float *animmatrix, *basematrix, *basematrix_inverse;
unsigned int num_trans;
index_t *indexes; index_t *indexes;
float vrad; float vrad;
int bonemap[MAX_BONES];
pskpnts_t *pnts = NULL; pskpnts_t *pnts = NULL;
pskvtxw_t *vtxw = NULL; pskvtxw_t *vtxw = NULL;
@ -4487,12 +4493,17 @@ qboolean Mod_LoadPSKModel(model_t *mod, void *buffer)
unsigned int num_animinfo=0, num_animkeys=0; unsigned int num_animinfo=0, num_animkeys=0;
int hunkstart, hunkend, hunktotal; int hunkstart, hunkend, hunktotal;
//extern cvar_t temp1; //unused variable
//#define PSK_GPU
#ifndef PSK_GPU
unsigned int num_trans;
galisskeletaltransforms_t *trans;
#else
vecV_t *skel_xyz; vecV_t *skel_xyz;
vec3_t *skel_norm; vec3_t *skel_norm;
byte_vec4_t *skel_idx; byte_vec4_t *skel_idx;
vec4_t *skel_weights; vec4_t *skel_weights;
#endif
/*load the psk*/ /*load the psk*/
while (pos < com_filesize && !fail) while (pos < com_filesize && !fail)
@ -4573,7 +4584,7 @@ qboolean Mod_LoadPSKModel(model_t *mod, void *buffer)
boneinfo[i].basepose.size[2] = LittleFloat(boneinfo[i].basepose.size[2]); boneinfo[i].basepose.size[2] = LittleFloat(boneinfo[i].basepose.size[2]);
/*not sure if this is needed, but mimic DP*/ /*not sure if this is needed, but mimic DP*/
if (i) if (i >= 0)
{ {
boneinfo[i].basepose.quat[0] *= -1; boneinfo[i].basepose.quat[0] *= -1;
boneinfo[i].basepose.quat[2] *= -1; boneinfo[i].basepose.quat[2] *= -1;
@ -4637,6 +4648,31 @@ qboolean Mod_LoadPSKModel(model_t *mod, void *buffer)
} }
else else
{ {
for (i = 0; i < num_boneinfo; i++)
{
/*assumption: 1:1 mapping will be common*/
if (!strcmp(boneinfo[i].name, animbones[i].name))
bonemap[i] = i;
else
{
/*non 1:1 mapping*/
for (j = 0; j < chunk->numrecords; j++)
{
if (!strcmp(boneinfo[i].name, animbones[j].name))
{
bonemap[i] = j;
break;
}
}
if (j == chunk->numrecords)
{
fail = true;
Con_Printf("PSK bone %s does not exist in PSA %s\n", boneinfo[i].name);
break;
}
}
}
/*
for (i = 0; i < num_boneinfo; i++) for (i = 0; i < num_boneinfo; i++)
{ {
animbones[i].parent = LittleLong(animbones[i].parent); animbones[i].parent = LittleLong(animbones[i].parent);
@ -4644,16 +4680,16 @@ qboolean Mod_LoadPSKModel(model_t *mod, void *buffer)
if (strcmp(boneinfo[i].name, animbones[i].name)) if (strcmp(boneinfo[i].name, animbones[i].name))
{ {
fail = true; fail = true;
Con_Printf("PSK/PSA bone names do not match\n"); Con_Printf("PSK/PSA bone names do not match %s vs %s\n", boneinfo[i].name, animbones[i].name);
break; break;
} }
if (boneinfo[i].parent != animbones[i].parent) else if (boneinfo[i].parent != animbones[i].parent)
{ {
fail = true; fail = true;
Con_Printf("PSK/PSA bone parents do not match\n"); Con_Printf("PSK/PSA bone parents do not match for bone %s\n", boneinfo[i].name);
break; break;
} }
} }*/
} }
} }
else if (!strcmp("ANIMINFO", chunk->id) && chunk->recordsize == sizeof(pskaniminfo_t)) else if (!strcmp("ANIMINFO", chunk->id) && chunk->recordsize == sizeof(pskaniminfo_t))
@ -4760,6 +4796,8 @@ qboolean Mod_LoadPSKModel(model_t *mod, void *buffer)
Matrix3x4_InvertTo4x4_Simple(basematrix+i*12, basematrix_inverse+i*16); Matrix3x4_InvertTo4x4_Simple(basematrix+i*12, basematrix_inverse+i*16);
} }
#ifndef PSK_GPU
/*expand the translations*/ /*expand the translations*/
num_trans = 0; num_trans = 0;
for (i = 0; i < num_vtxw; i++) for (i = 0; i < num_vtxw; i++)
@ -4791,7 +4829,7 @@ qboolean Mod_LoadPSKModel(model_t *mod, void *buffer)
} }
} }
} }
#else
skel_xyz = Hunk_Alloc(sizeof(*skel_xyz) * num_vtxw); skel_xyz = Hunk_Alloc(sizeof(*skel_xyz) * num_vtxw);
skel_norm = Hunk_Alloc(sizeof(*skel_norm) * num_vtxw); skel_norm = Hunk_Alloc(sizeof(*skel_norm) * num_vtxw);
skel_idx = Hunk_Alloc(sizeof(*skel_idx) * num_vtxw); skel_idx = Hunk_Alloc(sizeof(*skel_idx) * num_vtxw);
@ -4829,16 +4867,19 @@ qboolean Mod_LoadPSKModel(model_t *mod, void *buffer)
if (t != 1) if (t != 1)
for (j = 0; j < 4; j++) for (j = 0; j < 4; j++)
skel_weights[i][j] *= 1/t; skel_weights[i][j] *= 1/t;
skel_xyz[i][0] = pnts[vtxw[i].pntsindex].origin[0];
skel_xyz[i][1] = pnts[vtxw[i].pntsindex].origin[1];
skel_xyz[i][2] = pnts[vtxw[i].pntsindex].origin[2];
} }
#endif
#ifndef SERVERONLY #ifndef SERVERONLY
/*st coords, all share the same list*/ /*st coords, all share the same list*/
stcoord = Hunk_Alloc(sizeof(vec2_t)*num_vtxw); stcoord = Hunk_Alloc(sizeof(vec2_t)*num_vtxw);
for (i = 0; i < num_vtxw; i++) for (i = 0; i < num_vtxw; i++)
{ {
skel_xyz[i][0] = pnts[vtxw[i].pntsindex].origin[0];
skel_xyz[i][1] = pnts[vtxw[i].pntsindex].origin[1];
skel_xyz[i][2] = pnts[vtxw[i].pntsindex].origin[2];
stcoord[i*2+0] = vtxw[i].texcoord[0]; stcoord[i*2+0] = vtxw[i].texcoord[0];
stcoord[i*2+1] = vtxw[i].texcoord[1]; stcoord[i*2+1] = vtxw[i].texcoord[1];
} }
@ -4849,7 +4890,7 @@ qboolean Mod_LoadPSKModel(model_t *mod, void *buffer)
if (animinfo && animkeys) if (animinfo && animkeys)
{ {
if (1/*dpcompat_psa_ungroup.ival*/) if (dpcompat_psa_ungroup.ival)
{ {
/*unpack each frame of each animation to be a separate framegroup*/ /*unpack each frame of each animation to be a separate framegroup*/
unsigned int iframe; /*individual frame count*/ unsigned int iframe; /*individual frame count*/
@ -4886,15 +4927,20 @@ qboolean Mod_LoadPSKModel(model_t *mod, void *buffer)
Q_strncpyz(group[i].name, animinfo[i].name, sizeof(group[i].name)); Q_strncpyz(group[i].name, animinfo[i].name, sizeof(group[i].name));
group[i].loop = true; group[i].loop = true;
group[i].rate = animinfo[i].fps; group[i].rate = animinfo[i].fps;
group[i].isheirachical = false; group[i].isheirachical = true;
} }
} }
for (i = 0; i < num_animkeys; i++) for (j = 0; j < num_animkeys; j += num_boneinfo)
{ {
PSKGenMatrix( pskanimkeys_t *sb;
animkeys[i].origin[0], animkeys[i].origin[1], animkeys[i].origin[2], for (i = 0; i < num_boneinfo; i++)
animkeys[i].quat[0], animkeys[i].quat[1], animkeys[i].quat[2], animkeys[i].quat[3], {
animmatrix + i*12); sb = &animkeys[j + bonemap[i]];
PSKGenMatrix(
sb->origin[0], sb->origin[1], sb->origin[2],
sb->quat[0], sb->quat[1], sb->quat[2], sb->quat[3],
animmatrix + (j+i)*12);
}
} }
} }
else else
@ -4953,14 +4999,16 @@ qboolean Mod_LoadPSKModel(model_t *mod, void *buffer)
gmdl[i].ofsbones = (char*)bones - (char*)&gmdl[i]; gmdl[i].ofsbones = (char*)bones - (char*)&gmdl[i];
gmdl[i].numbones = num_boneinfo; gmdl[i].numbones = num_boneinfo;
#ifndef PSK_GPU
gmdl[i].ofsswtransforms = (char*)trans - (char*)&gmdl[i]; gmdl[i].ofsswtransforms = (char*)trans - (char*)&gmdl[i];
gmdl[i].numswtransforms = num_trans; gmdl[i].numswtransforms = num_trans;
/* #else
gmdl[i].ofs_skel_idx = (char*)skel_idx - (char*)&gmdl[i]; gmdl[i].ofs_skel_idx = (char*)skel_idx - (char*)&gmdl[i];
gmdl[i].ofs_skel_weight = (char*)skel_weights - (char*)&gmdl[i]; gmdl[i].ofs_skel_weight = (char*)skel_weights - (char*)&gmdl[i];
gmdl[i].ofs_skel_xyz = (char*)skel_xyz - (char*)&gmdl[i]; gmdl[i].ofs_skel_xyz = (char*)skel_xyz - (char*)&gmdl[i];
gmdl[i].ofs_skel_norm = (char*)skel_norm - (char*)&gmdl[i]; gmdl[i].ofs_skel_norm = (char*)skel_norm - (char*)&gmdl[i];
*/ #endif
gmdl[i].shares_verts = 0; gmdl[i].shares_verts = 0;
gmdl[i].shares_bones = 0; gmdl[i].shares_bones = 0;
gmdl[i].nextsurf = (i != num_matt-1)?sizeof(*gmdl):0; gmdl[i].nextsurf = (i != num_matt-1)?sizeof(*gmdl):0;

View file

@ -1417,7 +1417,7 @@ static void World_ODE_Frame_BodyToEntity(world_t *world, wedict_t *ed)
if (ed->v->modelindex) if (ed->v->modelindex)
{ {
model = world->GetCModel(world, ed->v->modelindex); model = world->Get_CModel(world, ed->v->modelindex);
if (!model || model->type == mod_alias) if (!model || model->type == mod_alias)
{ {
angles[PITCH] *= -1; angles[PITCH] *= -1;
@ -1776,7 +1776,7 @@ static void World_ODE_Frame_BodyFromEntity(world_t *world, wedict_t *ed)
{ {
case SOLID_BSP: case SOLID_BSP:
modelindex = (int)ed->v->modelindex; modelindex = (int)ed->v->modelindex;
model = world->GetCModel(world, modelindex); model = world->Get_CModel(world, modelindex);
if (model) if (model)
{ {
VectorScale(model->mins, scale, entmins); VectorScale(model->mins, scale, entmins);
@ -1971,7 +1971,7 @@ static void World_ODE_Frame_BodyFromEntity(world_t *world, wedict_t *ed)
if (ed->v->modelindex) if (ed->v->modelindex)
{ {
model = world->GetCModel(world, ed->v->modelindex); model = world->Get_CModel(world, ed->v->modelindex);
if (!model || model->type == mod_alias) if (!model || model->type == mod_alias)
{ {
qangles[PITCH] *= -1; qangles[PITCH] *= -1;

View file

@ -626,6 +626,43 @@ float Q_atof (const char *str)
return val*sign; return val*sign;
} }
/*
attempts to remove leet strange chars from a name
the resulting string is not intended to be visible to humans, but this functions results can be matched against each other.
*/
void deleetstring(char *result, char *leet)
{
char *s = result;
char *s2 = leet;
while(*s2)
{
if (*s2 == 0xff)
{
s2++;
continue;
}
*s = *s2 & ~128;
s2++;
if (*s == '3')
*s = 'e';
else if (*s == '4')
*s = 'a';
else if (*s == '0')
*s = 'o';
else if (*s == '1' || *s == '7')
*s = 'l';
else if (*s >= 18 && *s < 27)
*s = *s - 18 + '0';
else if (*s >= 'A' && *s <= 'Z')
*s = *s - 'A' + 'a';
else if (*s == '_' || *s == ' ' || *s == '~')
continue;
s++;
}
*s = '\0';
}
/* /*
============================================================================ ============================================================================

View file

@ -239,7 +239,7 @@ int Q_strncasecmp (const char *s1, const char *s2, int n);
int Q_strcasecmp (const char *s1, const char *s2); int Q_strcasecmp (const char *s1, const char *s2);
int Q_atoi (const char *str); int Q_atoi (const char *str);
float Q_atof (const char *str); float Q_atof (const char *str);
void deleetstring(char *result, char *leet);
//============================================================================ //============================================================================
@ -321,7 +321,7 @@ struct vfsfile_s *FS_OpenReadLocation(flocation_t *location);
char *FS_WhichPackForLocation(flocation_t *loc); char *FS_WhichPackForLocation(flocation_t *loc);
char *FS_GetPackHashes(char *buffer, int buffersize, qboolean referencedonly); char *FS_GetPackHashes(char *buffer, int buffersize, qboolean referencedonly);
char *FS_GetPackNames(char *buffer, int buffersize, qboolean referencedonly); char *FS_GetPackNames(char *buffer, int buffersize, qboolean referencedonly, qboolean ext);
int COM_FOpenFile (const char *filename, FILE **file); int COM_FOpenFile (const char *filename, FILE **file);
int COM_FOpenWriteFile (const char *filename, FILE **file); int COM_FOpenWriteFile (const char *filename, FILE **file);
@ -390,6 +390,7 @@ qbyte *COM_LoadHunkFile (const char *path);
qbyte *COM_LoadMallocFile (const char *path); qbyte *COM_LoadMallocFile (const char *path);
void COM_LoadCacheFile (const char *path, struct cache_user_s *cu); void COM_LoadCacheFile (const char *path, struct cache_user_s *cu);
void FS_ForceToPure(const char *str, const char *crcs, int seed); void FS_ForceToPure(const char *str, const char *crcs, int seed);
void FS_ImpurePacks(const char *names, const char *crcs);
char *COM_GetPathInfo (int i, int *crc); char *COM_GetPathInfo (int i, int *crc);
char *COM_NextPath (char *prevpath); char *COM_NextPath (char *prevpath);
void COM_FlushFSCache(void); //a file was written using fopen void COM_FlushFSCache(void); //a file was written using fopen

View file

@ -751,14 +751,14 @@ qboolean Cvar_ApplyLatchFlag(cvar_t *var, char *value, int flag)
var->latched_string = NULL; var->latched_string = NULL;
if (!latch) if (!latch)
{ {
#ifndef _MSC_VER #ifdef warningmsg
#warning this means the callback will never be called #pragma warningmsg("this means the callback will never be called")
#endif #endif
latch = var->string; latch = var->string;
var->string = NULL; var->string = NULL;
} }
#ifndef _MSC_VER #ifdef warningmsg
#warning set or forceset? #pragma warningmsg("set or forceset?")
#endif #endif
Cvar_ForceSet(var, value); Cvar_ForceSet(var, value);
@ -801,8 +801,8 @@ void Cvar_ForceCheatVars(qboolean semicheats, qboolean absolutecheats)
var->latched_string = NULL; var->latched_string = NULL;
if (!latch) if (!latch)
{ {
#ifndef _MSC_VER #ifdef warningmsg
#warning this means the callback will never be called #pragma warningmsg("this means the callback will never be called")
#endif #endif
latch = var->string; latch = var->string;
var->string = NULL; var->string = NULL;

View file

@ -607,7 +607,7 @@ char *FS_GetPackHashes(char *buffer, int buffersize, qboolean referencedonly)
return buffer; return buffer;
} }
} }
char *FS_GetPackNames(char *buffer, int buffersize, qboolean referencedonly) char *FS_GetPackNames(char *buffer, int buffersize, qboolean referencedonly, qboolean ext)
{ {
char temp[MAX_OSPATH]; char temp[MAX_OSPATH];
searchpath_t *search; searchpath_t *search;
@ -618,8 +618,15 @@ char *FS_GetPackNames(char *buffer, int buffersize, qboolean referencedonly)
{ {
for (search = com_purepaths ; search ; search = search->nextpure) for (search = com_purepaths ; search ; search = search->nextpure)
{ {
COM_StripExtension(search->purepath, temp, sizeof(temp)); if (!ext)
Q_strncatz(buffer, va("%s ", temp), buffersize); {
COM_StripExtension(search->purepath, temp, sizeof(temp));
Q_strncatz(buffer, va("%s ", temp), buffersize);
}
else
{
Q_strncatz(buffer, va("%s ", search->purepath), buffersize);
}
} }
return buffer; return buffer;
} }
@ -631,8 +638,15 @@ char *FS_GetPackNames(char *buffer, int buffersize, qboolean referencedonly)
search->crc_check = search->funcs->GeneratePureCRC(search->handle, 0, 0); search->crc_check = search->funcs->GeneratePureCRC(search->handle, 0, 0);
if (search->crc_check) if (search->crc_check)
{ {
COM_StripExtension(search->purepath, temp, sizeof(temp)); if (!ext)
Q_strncatz(buffer, va("%s ", temp), buffersize); {
COM_StripExtension(search->purepath, temp, sizeof(temp));
Q_strncatz(buffer, va("%s ", temp), buffersize);
}
else
{
Q_strncatz(buffer, va("%s ", search->purepath), buffersize);
}
} }
} }
return buffer; return buffer;
@ -815,6 +829,7 @@ qboolean FS_NativePath(const char *fname, enum fs_relative relativeto, char *out
return true; return true;
} }
/*locates and opens a file*/
vfsfile_t *FS_OpenVFS(const char *filename, const char *mode, enum fs_relative relativeto) vfsfile_t *FS_OpenVFS(const char *filename, const char *mode, enum fs_relative relativeto)
{ {
char cleanname[MAX_QPATH]; char cleanname[MAX_QPATH];
@ -906,6 +921,7 @@ vfsfile_t *FS_OpenVFS(const char *filename, const char *mode, enum fs_relative r
return NULL; return NULL;
} }
/*opens a vfsfile from an already discovered location*/
vfsfile_t *FS_OpenReadLocation(flocation_t *location) vfsfile_t *FS_OpenReadLocation(flocation_t *location)
{ {
if (location->search) if (location->search)
@ -1138,16 +1154,24 @@ void COM_EnumerateFiles (const char *match, int (*func)(const char *, int, void
void COM_FlushTempoaryPacks(void) void COM_FlushTempoaryPacks(void)
{ {
searchpath_t *next; searchpath_t *sp, **link;
while (com_searchpaths && com_searchpaths->istemporary) link = &com_searchpaths;
while (*link)
{ {
com_searchpaths->funcs->ClosePath(com_searchpaths->handle); sp = *link;
next = com_searchpaths->next; if (sp->istemporary)
Z_Free (com_searchpaths); {
com_searchpaths = next; FS_FlushFSHash();
com_fschanged = true; *link = sp->next;
sp->funcs->ClosePath(sp->handle);
Z_Free (sp);
}
else
link = &sp->next;
} }
com_purepaths = NULL;
} }
qboolean COM_LoadMapPackFile (const char *filename, int ofs) qboolean COM_LoadMapPackFile (const char *filename, int ofs)
@ -1324,7 +1348,7 @@ static searchpath_t *FS_AddPathHandle(const char *purepath, const char *probable
{ {
unsigned int i; unsigned int i;
searchpath_t *search; searchpath_t *search, **link;
if (!funcs) if (!funcs)
{ {
@ -1340,19 +1364,35 @@ static searchpath_t *FS_AddPathHandle(const char *purepath, const char *probable
search->funcs = funcs; search->funcs = funcs;
Q_strncpyz(search->purepath, purepath, sizeof(search->purepath)); Q_strncpyz(search->purepath, purepath, sizeof(search->purepath));
search->next = com_searchpaths; if (istemporary)
com_searchpaths = search; {
//add at end. pureness will reorder if needed.
link = &com_searchpaths;
while(*link)
{
link = &(*link)->next;
}
*link = search;
}
else
{
search->next = com_searchpaths;
com_searchpaths = search;
}
com_fschanged = true; com_fschanged = true;
//temp packages also do not nest
for (i = 0; i < sizeof(searchpathformats)/sizeof(searchpathformats[0]); i++) if (!istemporary)
{ {
if (!searchpathformats[i].extension || !searchpathformats[i].funcs || !searchpathformats[i].funcs->OpenNew) for (i = 0; i < sizeof(searchpathformats)/sizeof(searchpathformats[0]); i++)
continue;
if (loadstuff & (1<<i))
{ {
FS_AddDataFiles(purepath, probablepath, search, searchpathformats[i].extension, searchpathformats[i].funcs); if (!searchpathformats[i].extension || !searchpathformats[i].funcs || !searchpathformats[i].funcs->OpenNew)
continue;
if (loadstuff & (1<<i))
{
FS_AddDataFiles(purepath, probablepath, search, searchpathformats[i].extension, searchpathformats[i].funcs);
}
} }
} }
@ -1641,7 +1681,7 @@ void COM_Gamedir (const char *dir)
/*set some stuff so our regular qw client appears more like hexen2*/ /*set some stuff so our regular qw client appears more like hexen2*/
#define HEX2CFG "set r_particlesdesc \"spikeset tsshaft h2part\"\nset sv_maxspeed 640\nset watervis 1\nset r_wateralpha 0.5\nset sv_pupglow 1\nset cl_model_bobbing 1\nsv_sound_land \"fx/thngland.wav\"\n" #define HEX2CFG "set r_particlesdesc \"spikeset tsshaft h2part\"\nset sv_maxspeed 640\nset watervis 1\nset r_wateralpha 0.5\nset sv_pupglow 1\nset cl_model_bobbing 1\nsv_sound_land \"fx/thngland.wav\"\n"
/*Q3's ui doesn't like empty model/headmodel/handicap cvars, even if the gamecode copes*/ /*Q3's ui doesn't like empty model/headmodel/handicap cvars, even if the gamecode copes*/
#define Q3CFG "seta model sarge\nseta headmodel sarge\nseta handicap 100\n" #define Q3CFG "gl_overbright 2\nseta model sarge\nseta headmodel sarge\nseta handicap 100\n"
typedef struct { typedef struct {
const char *protocolname; //sent to the master server when this is the current gamemode. const char *protocolname; //sent to the master server when this is the current gamemode.
@ -1665,9 +1705,9 @@ const gamemode_info_t gamemode_info[] = {
{"Darkplaces-Rogue", "rogue", "-rogue", {NULL}, NULL, {"id1", "qw", "rogue", "fte"}, "Quake: Dissolution of Eternity"}, {"Darkplaces-Rogue", "rogue", "-rogue", {NULL}, NULL, {"id1", "qw", "rogue", "fte"}, "Quake: Dissolution of Eternity"},
{"Nexuiz", "nexuiz", "-nexuiz", {"nexuiz.exe"}, NEXCFG, {"data", "ftedata"}, "Nexuiz"}, {"Nexuiz", "nexuiz", "-nexuiz", {"nexuiz.exe"}, NEXCFG, {"data", "ftedata"}, "Nexuiz"},
{"Xonotic", "xonotic", "-xonotic", {"xonotic.exe"}, NEXCFG, {"data", "ftedata"}, "Xonotic"}, {"Xonotic", "xonotic", "-xonotic", {"xonotic.exe"}, NEXCFG, {"data", "ftedata"}, "Xonotic"},
{"DMF", "dmf", "-dmf", {"base/src/progs.src", {"Spark", "spark", "-spark", {"base/src/progs.src",
"base/qwprogs.dat", "base/qwprogs.dat",
"base/pak0.pak"}, DMFCFG, {"base", }, "DMF"}, "base/pak0.pak"}, DMFCFG, {"base", }, "Spark"},
//supported commercial mods (some are currently only partially supported) //supported commercial mods (some are currently only partially supported)
{"FTE-H2MP", "h2mp", "-portals", {"portals/hexen.rc", {"FTE-H2MP", "h2mp", "-portals", {"portals/hexen.rc",
@ -1687,27 +1727,117 @@ const gamemode_info_t gamemode_info[] = {
{NULL} {NULL}
}; };
void FS_GenCachedPakName(char *pname, char *crc, char *local, int llen)
{
char *fn;
unsigned int h;
if (strstr(pname, "dlcache"))
{
Q_strncpyz(local, pname, llen);
return;
}
fn = COM_SkipPath(pname);
Q_strncpyz(local, pname, min((fn - pname) + 1, llen));
Q_strncatz(local, "dlcache/", llen);
Q_strncatz(local, fn, llen);
if (*crc)
{
Q_strncatz(local, ".", llen);
h = atoi(crc);
Q_strncatz(local, va("%x", h), llen);
}
}
//if a server is using private pak files then load the same version of those, but deprioritise them
//crcs are not used, but matched only if the server has a different version from a previous file
void FS_ImpurePacks(const char *names, const char *crcs)
{
int crc;
searchpath_t *sp;
char *pname;
while(names)
{
crcs = COM_Parse(crcs);
crc = atoi(com_token);
names = COM_Parse(names);
if (!crc)
continue;
pname = com_token;
if (*pname == '*')
pname++;
for (sp = com_searchpaths; sp; sp = sp->next)
{
if (!stricmp(sp->purepath, pname))
{
break;
}
}
if (!sp)
{
char local[MAX_OSPATH];
vfsfile_t *vfs;
char *ext = COM_FileExtension(pname);
void *handle;
int i;
FS_GenCachedPakName(pname, va("%i", crc), local, sizeof(local));
vfs = FS_OpenVFS(local, "rb", FS_ROOT);
if (vfs)
{
for (i = 0; i < sizeof(searchpathformats)/sizeof(searchpathformats[0]); i++)
{
if (!searchpathformats[i].extension || !searchpathformats[i].funcs || !searchpathformats[i].funcs->OpenNew)
continue;
if (!strcmp(ext, searchpathformats[i].extension))
{
handle = searchpathformats[i].funcs->OpenNew (vfs, local);
if (!handle)
break;
sp = FS_AddPathHandle(pname, local, searchpathformats[i].funcs, handle, true, true, false, (unsigned int)-1);
FS_FlushFSHash();
break;
}
}
}
if (!sp)
Con_DPrintf("Unable to load matching package file %s\n", pname);
}
}
FS_ForceToPure(NULL, NULL, 0);
}
//space-seperate pk3 names followed by space-seperated crcs //space-seperate pk3 names followed by space-seperated crcs
//note that we'll need to reorder and filter out files that don't match the crc. //note that we'll need to reorder and filter out files that don't match the crc.
void FS_ForceToPure(const char *str, const char *crcs, int seed) void FS_ForceToPure(const char *names, const char *crcs, int seed)
{ {
//pure files are more important than non-pure. //pure files are more important than non-pure.
searchpath_t *sp; searchpath_t *sp;
searchpath_t *lastpure = NULL; searchpath_t *lastpure = NULL;
int crc; int crc;
qboolean waspure = com_purepaths != NULL;
char *pname;
if (!str) if (!crcs || !*crcs)
{ //pure isn't in use. { //pure isn't in use.
if (com_purepaths) if (com_purepaths)
{
Con_Printf("Pure FS deactivated\n"); Con_Printf("Pure FS deactivated\n");
com_purepaths = NULL; com_purepaths = NULL;
FS_FlushFSHash(); FS_FlushFSHash();
}
return; return;
} }
if (!com_purepaths)
Con_Printf("Pure FS activated\n");
com_purepaths = NULL;
for (sp = com_searchpaths; sp; sp = sp->next) for (sp = com_searchpaths; sp; sp = sp->next)
{ {
if (sp->funcs->GeneratePureCRC) if (sp->funcs->GeneratePureCRC)
@ -1718,6 +1848,7 @@ void FS_ForceToPure(const char *str, const char *crcs, int seed)
} }
else else
{ {
sp->nextpure = NULL;
sp->crc_check = 0; sp->crc_check = 0;
sp->crc_reply = 0; sp->crc_reply = 0;
} }
@ -1727,10 +1858,15 @@ void FS_ForceToPure(const char *str, const char *crcs, int seed)
{ {
crcs = COM_Parse(crcs); crcs = COM_Parse(crcs);
crc = atoi(com_token); crc = atoi(com_token);
names = COM_Parse(names);
if (!crc) if (!crc)
continue; continue;
pname = com_token;
if (*pname == '*')
pname++;
for (sp = com_searchpaths; sp; sp = sp->next) for (sp = com_searchpaths; sp; sp = sp->next)
{ {
if (sp->nextpure == (void*)0x1) //don't add twice. if (sp->nextpure == (void*)0x1) //don't add twice.
@ -1746,23 +1882,54 @@ void FS_ForceToPure(const char *str, const char *crcs, int seed)
} }
} }
if (!sp) if (!sp)
Con_Printf("Pure crc %i wasn't found\n", crc);
}
/* don't add any extras.
for (sp = com_searchpaths; sp; sp = sp->next)
{
if (sp->nextpure == (void*)0x1)
{ {
if (lastpure) char local[MAX_OSPATH];
lastpure->nextpure = sp; vfsfile_t *vfs;
sp->nextpure = NULL; char *ext = COM_FileExtension(pname);
lastpure = sp; void *handle;
int i;
FS_GenCachedPakName(pname, va("%i", crc), local, sizeof(local));
vfs = FS_OpenVFS(local, "rb", FS_ROOT);
if (vfs)
{
for (i = 0; i < sizeof(searchpathformats)/sizeof(searchpathformats[0]); i++)
{
if (!searchpathformats[i].extension || !searchpathformats[i].funcs || !searchpathformats[i].funcs->OpenNew)
continue;
if (!strcmp(ext, searchpathformats[i].extension))
{
handle = searchpathformats[i].funcs->OpenNew (vfs, local);
if (!handle)
break;
sp = FS_AddPathHandle(pname, local, searchpathformats[i].funcs, handle, true, true, false, (unsigned int)-1);
sp->crc_check = sp->funcs->GeneratePureCRC(sp->handle, seed, 0);
sp->crc_reply = sp->funcs->GeneratePureCRC(sp->handle, seed, 1);
if (sp->crc_check == crc)
{
if (lastpure)
lastpure->nextpure = sp;
else
com_purepaths = sp;
sp->nextpure = NULL;
lastpure = sp;
}
break;
}
}
}
if (!sp)
Con_DPrintf("Pure crc %i wasn't found\n", crc);
} }
} }
*/
FS_FlushFSHash(); FS_FlushFSHash();
if (com_purepaths && !waspure)
Con_Printf("Pure FS activated\n");
} }
char *FSQ3_GenerateClientPacksList(char *buffer, int maxlen, int basechecksum) char *FSQ3_GenerateClientPacksList(char *buffer, int maxlen, int basechecksum)
@ -1858,6 +2025,8 @@ void FS_ReloadPackFilesFlags(unsigned int reloadflags)
if (!com_base_searchpaths) if (!com_base_searchpaths)
com_base_searchpaths = com_searchpaths; com_base_searchpaths = com_searchpaths;
/*sv_pure: Reload pure paths*/
} }
void FS_UnloadPackFiles(void) void FS_UnloadPackFiles(void)

View file

@ -148,6 +148,36 @@ int FSPAK_EnumerateFiles (void *handle, const char *match, int (*func)(const cha
return true; return true;
} }
int FSPAK_GeneratePureCRC(void *handle, int seed, int crctype)
{
pack_t *pak = handle;
int result;
int *filecrcs;
int numcrcs=0;
int i;
filecrcs = BZ_Malloc((pak->numfiles+1)*sizeof(int));
filecrcs[numcrcs++] = seed;
for (i = 0; i < pak->numfiles; i++)
{
if (pak->files[i].filelen > 0)
{
filecrcs[numcrcs++] = pak->files[i].filepos ^ pak->files[i].filelen ^ QCRC_Block(pak->files[i].name, sizeof(56));
}
}
if (crctype)
result = Com_BlockChecksum(filecrcs, numcrcs*sizeof(int));
else
result = Com_BlockChecksum(filecrcs+1, (numcrcs-1)*sizeof(int));
BZ_Free(filecrcs);
return result;
}
/* /*
================= =================
COM_LoadPackFile COM_LoadPackFile
@ -352,7 +382,7 @@ searchpathfuncs_t packfilefuncs = {
FSPAK_ReadFile, FSPAK_ReadFile,
FSPAK_EnumerateFiles, FSPAK_EnumerateFiles,
FSPAK_LoadPackFile, FSPAK_LoadPackFile,
NULL, FSPAK_GeneratePureCRC,
FSPAK_OpenVFS FSPAK_OpenVFS
}; };

View file

@ -427,6 +427,7 @@ int FSZIP_GeneratePureCRC(void *handle, int seed, int crctype)
zipfile_t *zip = handle; zipfile_t *zip = handle;
unz_file_info file_info; unz_file_info file_info;
int result;
int *filecrcs; int *filecrcs;
int numcrcs=0; int numcrcs=0;
int i; int i;
@ -446,9 +447,12 @@ int FSZIP_GeneratePureCRC(void *handle, int seed, int crctype)
} }
if (crctype) if (crctype)
return Com_BlockChecksum(filecrcs, numcrcs*sizeof(int)); result = Com_BlockChecksum(filecrcs, numcrcs*sizeof(int));
else else
return Com_BlockChecksum(filecrcs+1, (numcrcs-1)*sizeof(int)); result = Com_BlockChecksum(filecrcs+1, (numcrcs-1)*sizeof(int));
BZ_Free(filecrcs);
return result;
} }
typedef struct { typedef struct {

View file

@ -28,7 +28,7 @@ extern cvar_t r_shadow_bumpscale_basetexture;
//these are in model.c (or gl_model.c) //these are in model.c (or gl_model.c)
qboolean RMod_LoadVertexes (lump_t *l); qboolean RMod_LoadVertexes (lump_t *l);
qboolean RMod_LoadEdges (lump_t *l); qboolean RMod_LoadEdges (lump_t *l, qboolean lm);
qboolean RMod_LoadMarksurfaces (lump_t *l); qboolean RMod_LoadMarksurfaces (lump_t *l);
qboolean RMod_LoadSurfedges (lump_t *l); qboolean RMod_LoadSurfedges (lump_t *l);
void RMod_LoadLighting (lump_t *l); void RMod_LoadLighting (lump_t *l);
@ -1323,7 +1323,7 @@ Mod_LoadFaces
#ifndef SERVERONLY #ifndef SERVERONLY
qboolean CMod_LoadFaces (lump_t *l) qboolean CMod_LoadFaces (lump_t *l)
{ {
dface_t *in; dsface_t *in;
msurface_t *out; msurface_t *out;
int i, count, surfnum; int i, count, surfnum;
int planenum, side; int planenum, side;
@ -3863,7 +3863,7 @@ q2cmodel_t *CM_LoadMap (char *name, char *filein, qboolean clientload, unsigned
// load into heap // load into heap
#ifndef SERVERONLY #ifndef SERVERONLY
noerrors = noerrors && RMod_LoadVertexes (&header.lumps[Q2LUMP_VERTEXES]); noerrors = noerrors && RMod_LoadVertexes (&header.lumps[Q2LUMP_VERTEXES]);
noerrors = noerrors && RMod_LoadEdges (&header.lumps[Q2LUMP_EDGES]); noerrors = noerrors && RMod_LoadEdges (&header.lumps[Q2LUMP_EDGES], false);
noerrors = noerrors && RMod_LoadSurfedges (&header.lumps[Q2LUMP_SURFEDGES]); noerrors = noerrors && RMod_LoadSurfedges (&header.lumps[Q2LUMP_SURFEDGES]);
if (noerrors) if (noerrors)
RMod_LoadLighting (&header.lumps[Q2LUMP_LIGHTING]); RMod_LoadLighting (&header.lumps[Q2LUMP_LIGHTING]);

View file

@ -403,34 +403,9 @@ void QDECL AngleVectors (const vec3_t angles, vec3_t forward, vec3_t right, vec3
} }
} }
void QDECL vectoangles(vec3_t vec, vec3_t ang) void QDECL vectoangles(vec3_t fwd, vec3_t ang)
{ {
float forward; VectorAngles(fwd, NULL, ang);
float yaw, pitch;
if (vec[1] == 0 && vec[0] == 0)
{
yaw = 0;
if (vec[2] > 0)
pitch = 90;
else
pitch = 270;
}
else
{
yaw = /*(int)*/ (atan2(vec[1], vec[0]) * 180 / M_PI);
if (yaw < 0)
yaw += 360;
forward = sqrt (vec[0]*vec[0] + vec[1]*vec[1]);
pitch = /*(int)*/ (atan2(vec[2], forward) * 180 / M_PI);
if (pitch < 0)
pitch += 360;
}
ang[0] = pitch;
ang[1] = yaw;
ang[2] = 0;
} }
int VectorCompare (const vec3_t v1, const vec3_t v2) int VectorCompare (const vec3_t v1, const vec3_t v2)

View file

@ -78,7 +78,7 @@ void NET_InitServer (void);
void NET_CloseServer (void); void NET_CloseServer (void);
void UDP_CloseSocket (int socket); void UDP_CloseSocket (int socket);
void NET_Shutdown (void); void NET_Shutdown (void);
qboolean NET_GetPacket (netsrc_t socket); int NET_GetPacket (netsrc_t netsrc, int firstsock);
void NET_SendPacket (netsrc_t socket, int length, void *data, netadr_t to); void NET_SendPacket (netsrc_t socket, int length, void *data, netadr_t to);
int NET_LocalAddressForRemote(struct ftenet_connections_s *collection, netadr_t *remote, netadr_t *local, int idx); int NET_LocalAddressForRemote(struct ftenet_connections_s *collection, netadr_t *remote, netadr_t *local, int idx);
void NET_PrintAddresses(struct ftenet_connections_s *collection); void NET_PrintAddresses(struct ftenet_connections_s *collection);
@ -232,9 +232,20 @@ void Huff_EmitByte(int ch, qbyte *buffer, int *count);
#define H2_PROTOCOL_VERSION 19 #define H2_PROTOCOL_VERSION 19
#define NEHD_PROTOCOL_VERSION 250 #define NEHD_PROTOCOL_VERSION 250
#define FITZ_PROTOCOL_VERSION 666 #define FITZ_PROTOCOL_VERSION 666
#define RMQ_PROTOCOL_VERSION 999
#define DP5_PROTOCOL_VERSION 3502 #define DP5_PROTOCOL_VERSION 3502
#define DP6_PROTOCOL_VERSION 3503 #define DP6_PROTOCOL_VERSION 3503
#define DP7_PROTOCOL_VERSION 3504 #define DP7_PROTOCOL_VERSION 3504
/*RMQ protocol flags*/
#define RMQFL_SHORTANGLE (1 << 1)
#define RMQFL_FLOATANGLE (1 << 2)
#define RMQFL_24BITCOORD (1 << 3)
#define RMQFL_FLOATCOORD (1 << 4)
#define RMQFL_EDICTSCALE (1 << 5)
#define RMQFL_ALPHASANITY (1 << 6)
#define RMQFL_MOREFLAGS (1 << 31)
#endif #endif
int UDP_OpenSocket (int port, qboolean bcast); int UDP_OpenSocket (int port, qboolean bcast);

View file

@ -205,6 +205,8 @@ qboolean Netchan_CanPacket (netchan_t *chan, int rate)
{ {
if (chan->remote_address.type == NA_LOOPBACK) if (chan->remote_address.type == NA_LOOPBACK)
return true; //don't ever drop packets due to possible routing problems when there is no routing. return true; //don't ever drop packets due to possible routing problems when there is no routing.
if (!rate)
return true;
if (chan->cleartime < realtime + MAX_BACKUP/(float)rate) if (chan->cleartime < realtime + MAX_BACKUP/(float)rate)
return true; return true;
return false; return false;
@ -212,10 +214,13 @@ qboolean Netchan_CanPacket (netchan_t *chan, int rate)
void Netchan_Block (netchan_t *chan, int bytes, int rate) void Netchan_Block (netchan_t *chan, int bytes, int rate)
{ {
if (chan->cleartime < realtime-0.25) //0.25 allows it to be a little bursty. if (rate)
chan->cleartime = realtime + bytes/(float)rate; {
else if (chan->cleartime < realtime-0.25) //0.25 allows it to be a little bursty.
chan->cleartime += bytes/(float)rate; chan->cleartime = realtime + bytes/(float)rate;
else
chan->cleartime += bytes/(float)rate;
}
} }
@ -275,6 +280,13 @@ nqprot_t NQNetChan_Process(netchan_t *chan)
else if (sequence > chan->reliable_sequence) else if (sequence > chan->reliable_sequence)
Con_Printf("Future ack recieved\n"); Con_Printf("Future ack recieved\n");
if (showpackets.value)
Con_Printf ("<-- a s=%i a=%i(%i) %i\n"
, chan->outgoing_sequence
, chan->incoming_sequence
, chan->incoming_reliable_sequence
, 0);
return NQP_ERROR; //don't try execing the 'payload'. I hate ack packets. return NQP_ERROR; //don't try execing the 'payload'. I hate ack packets.
} }
@ -297,6 +309,13 @@ nqprot_t NQNetChan_Process(netchan_t *chan)
chan->incoming_acknowledged++; chan->incoming_acknowledged++;
chan->good_count++; chan->good_count++;
if (showpackets.value)
Con_Printf ("<-- u s=%i a=%i(%i) %i\n"
, chan->outgoing_sequence
, chan->incoming_sequence
, chan->incoming_reliable_sequence
, net_message.cursize);
return NQP_DATAGRAM; return NQP_DATAGRAM;
} }
if (header & NETFLAG_DATA) if (header & NETFLAG_DATA)
@ -327,11 +346,19 @@ nqprot_t NQNetChan_Process(netchan_t *chan)
SZ_Write(&net_message, chan->in_fragment_buf, chan->in_fragment_length); SZ_Write(&net_message, chan->in_fragment_buf, chan->in_fragment_length);
chan->in_fragment_length = 0; chan->in_fragment_length = 0;
MSG_BeginReading(chan->netprim); MSG_BeginReading(chan->netprim);
if (showpackets.value)
Con_Printf ("<-- r s=%i a=%i(%i) %i\n"
, chan->outgoing_sequence
, chan->incoming_sequence
, chan->incoming_reliable_sequence
, net_message.cursize);
return NQP_RELIABLE; //we can read it now return NQP_RELIABLE; //we can read it now
} }
} }
else else
Con_DPrintf("Stale reliable (%i)\n", sequence); Con_DPrintf("Stale reliable (%i)\n", sequence);
return NQP_ERROR; return NQP_ERROR;
} }

View file

@ -23,10 +23,7 @@ struct sockaddr;
#include "quakedef.h" #include "quakedef.h"
#include "netinc.h" #include "netinc.h"
#ifdef _MSC_VER netadr_t net_local_cl_ipadr; //still used to match local ui requests (quake/gamespy), and to generate ip reports for q3 servers (which is probably pointless).
#pragma message("these two are never set. A NET_ReplySource function that returns the address a reply would originate from would be sufficient. Note that INADDR_ANY can be multiple however, so these are just a hint.")
#endif
netadr_t net_local_cl_ipadr; //still used to match local ui requests, and to generate ip reports for q3 servers.
netadr_t net_from; netadr_t net_from;
sizebuf_t net_message; sizebuf_t net_message;
@ -64,7 +61,7 @@ void (*pfreeaddrinfo) (struct addrinfo*);
void NET_GetLocalAddress (int socket, netadr_t *out); void NET_GetLocalAddress (int socket, netadr_t *out);
int TCP_OpenListenSocket (int port); int TCP_OpenListenSocket (int port);
extern cvar_t sv_port; extern cvar_t sv_port_ipv4;
#ifdef IPPROTO_IPV6 #ifdef IPPROTO_IPV6
int UDP6_OpenSocket (int port, qboolean bcast); int UDP6_OpenSocket (int port, qboolean bcast);
extern cvar_t sv_port_ipv6; extern cvar_t sv_port_ipv6;
@ -1024,26 +1021,22 @@ qboolean NET_CompareAdrMasked(netadr_t a, netadr_t b, netadr_t mask)
// check to make sure all types match // check to make sure all types match
if (a.type != b.type) if (a.type != b.type)
{ {
if (a.type == NA_IP && b.type == NA_IPV6) if (a.type == NA_IP && b.type == NA_IPV6 && mask.type == NA_IP)
{ {
#ifndef _MSC_VER for (i = 0; i < 10; i++)
#warning code me if (b.address.ip6[i] != 0)
#endif return false; //only matches if they're 0s, otherwise its not an ipv4 address there
//okay, comparing an ipv4 address against an ipv4-as-6
/* for (i = 0; i < 10; i++)
if (mask.address.ip[i] != 0)
return false;
for (; i < 12; i++) for (; i < 12; i++)
if (b.address.ip6[i] != 0xff && b.address.ip6[i] != 0x00) //0x00 is depricated
return false; //only matches if they're 0s or ffs, otherwise its not an ipv4 address there
for (i = 0; i < 4; i++)
{ {
if (mask.address.ip[i] != 0xff) if ((a.address.ip[i] & mask.address.ip[i]) != (b.address.ip6[12+i] & mask.address.ip[i]))
return false; //mask doesn't match
} }
if (i == 12) return true; //its an ipv4 address in there, the mask matched the whole way through
{
}*/
} }
if (a.type == NA_IPV6 && b.type == NA_IP) if (a.type == NA_IPV6 && b.type == NA_IP && mask.type == NA_IP)
{ {
for (i = 0; i < 10; i++) for (i = 0; i < 10; i++)
if (a.address.ip6[i] != 0) if (a.address.ip6[i] != 0)
@ -1696,6 +1689,7 @@ ftenet_generic_connection_t *FTENET_Generic_EstablishConnection(int adrfamily, i
int family; int family;
int port; int port;
int bindtries; int bindtries;
int bufsz;
if (!NET_PortToAdr(adrfamily, address, &adr)) if (!NET_PortToAdr(adrfamily, address, &adr))
@ -1711,6 +1705,9 @@ ftenet_generic_connection_t *FTENET_Generic_EstablishConnection(int adrfamily, i
return NULL; return NULL;
} }
bufsz = 1<<18;
setsockopt(newsocket, SOL_SOCKET, SO_RCVBUF, (void*)&bufsz, sizeof(bufsz));
//try and find an unused port. //try and find an unused port.
port = ntohs(((struct sockaddr_in*)&qs)->sin_port); port = ntohs(((struct sockaddr_in*)&qs)->sin_port);
for (bindtries = 100; bindtries > 0; bindtries--) for (bindtries = 100; bindtries > 0; bindtries--)
@ -1735,6 +1732,13 @@ ftenet_generic_connection_t *FTENET_Generic_EstablishConnection(int adrfamily, i
if (ioctlsocket (newsocket, FIONBIO, &_true) == -1) if (ioctlsocket (newsocket, FIONBIO, &_true) == -1)
Sys_Error ("UDP_OpenSocket: ioctl FIONBIO: %s", strerror(qerrno)); Sys_Error ("UDP_OpenSocket: ioctl FIONBIO: %s", strerror(qerrno));
//
// determine my name & address if we don't already know it
//
if (!net_local_cl_ipadr.type == NA_INVALID)
NET_GetLocalAddress (newsocket, &net_local_cl_ipadr);
newcon = Z_Malloc(sizeof(*newcon)); newcon = Z_Malloc(sizeof(*newcon));
if (newcon) if (newcon)
{ {
@ -2669,9 +2673,9 @@ struct ftenet_generic_connection_s *FTENET_IRCConnect_EstablishConnection(qboole
#endif #endif
qboolean NET_GetPacket (netsrc_t netsrc) /*firstsock is a cookie*/
int NET_GetPacket (netsrc_t netsrc, int firstsock)
{ {
int i;
ftenet_connections_t *collection; ftenet_connections_t *collection;
if (netsrc == NS_SERVER) if (netsrc == NS_SERVER)
{ {
@ -2693,20 +2697,20 @@ qboolean NET_GetPacket (netsrc_t netsrc)
} }
if (!collection) if (!collection)
return false; return -1;
for (i = 0; i < MAX_CONNECTIONS; i++) for (; firstsock < MAX_CONNECTIONS; firstsock+=1)
{ {
if (!collection->conn[i]) if (!collection->conn[firstsock])
break; break;
if (collection->conn[i]->GetPacket(collection->conn[i])) if (collection->conn[firstsock]->GetPacket(collection->conn[firstsock]))
{ {
net_from.connum = i+1; net_from.connum = firstsock+1;
return true; return firstsock;
} }
} }
return false; return -1;
} }
int NET_LocalAddressForRemote(ftenet_connections_t *collection, netadr_t *remote, netadr_t *local, int idx) int NET_LocalAddressForRemote(ftenet_connections_t *collection, netadr_t *remote, netadr_t *local, int idx)
@ -3314,11 +3318,6 @@ void NET_InitClient(void)
net_message.maxsize = sizeof(net_message_buffer); net_message.maxsize = sizeof(net_message_buffer);
net_message.data = net_message_buffer; net_message.data = net_message_buffer;
//
// determine my name & address
//
// NET_GetLocalAddress (cls.socketip, &net_local_cl_ipadr);
Con_TPrintf(TL_CLIENTPORTINITED); Con_TPrintf(TL_CLIENTPORTINITED);
} }
#endif #endif
@ -3381,7 +3380,7 @@ void NET_InitServer(void)
allowconnects = true; allowconnects = true;
Cvar_ForceCallback(&sv_port); Cvar_ForceCallback(&sv_port_ipv4);
#ifdef IPPROTO_IPV6 #ifdef IPPROTO_IPV6
Cvar_ForceCallback(&sv_port_ipv6); Cvar_ForceCallback(&sv_port_ipv6);
#endif #endif

View file

@ -128,7 +128,7 @@ typedef struct {
int (*FindParticleType) (char *name); int (*FindParticleType) (char *name);
int (*RunParticleEffectTypeString) (vec3_t org, vec3_t dir, float count, char *name); int (*RunParticleEffectTypeString) (vec3_t org, vec3_t dir, float count, char *name);
int (*ParticleTrail) (vec3_t startpos, vec3_t end, int type, trailstate_t **tsk); int (*ParticleTrail) (vec3_t startpos, vec3_t end, int type, int dlkey, trailstate_t **tsk);
int (*RunParticleEffectState) (vec3_t org, vec3_t dir, float count, int typenum, trailstate_t **tsk); int (*RunParticleEffectState) (vec3_t org, vec3_t dir, float count, int typenum, trailstate_t **tsk);
void (*RunParticleWeather) (vec3_t minb, vec3_t maxb, vec3_t dir, float count, int colour, char *efname); void (*RunParticleWeather) (vec3_t minb, vec3_t maxb, vec3_t dir, float count, int colour, char *efname);
void (*RunParticleCube) (vec3_t minb, vec3_t maxb, vec3_t dir, float count, int colour, qboolean gravity, float jitter); void (*RunParticleCube) (vec3_t minb, vec3_t maxb, vec3_t dir, float count, int colour, qboolean gravity, float jitter);

View file

@ -1059,6 +1059,7 @@ void QCBUILTIN PF_Spawn (progfuncs_t *prinst, struct globalvars_s *pr_globals)
{ {
struct edict_s *ed; struct edict_s *ed;
ed = ED_Alloc(prinst); ed = ED_Alloc(prinst);
pr_globals = PR_globals(prinst, PR_CURRENT);
RETURN_EDICT(prinst, ed); RETURN_EDICT(prinst, ed);
} }
@ -2394,7 +2395,6 @@ void QCBUILTIN PF_vlen (progfuncs_t *prinst, struct globalvars_s *pr_globals)
void QCBUILTIN PF_vectoangles (progfuncs_t *prinst, struct globalvars_s *pr_globals) void QCBUILTIN PF_vectoangles (progfuncs_t *prinst, struct globalvars_s *pr_globals)
{ {
float *value1, *up; float *value1, *up;
float yaw, pitch, roll;
value1 = G_VECTOR(OFS_PARM0); value1 = G_VECTOR(OFS_PARM0);
if (*prinst->callargc >= 2) if (*prinst->callargc >= 2)
@ -2402,56 +2402,7 @@ void QCBUILTIN PF_vectoangles (progfuncs_t *prinst, struct globalvars_s *pr_glob
else else
up = NULL; up = NULL;
VectorAngles(value1, up, G_VECTOR(OFS_RETURN));
if (value1[1] == 0 && value1[0] == 0)
{
if (value1[2] > 0)
{
pitch = -M_PI*0.5;
yaw = up ? atan2(-up[1], -up[0]) : 0;
}
else
{
pitch = M_PI*0.5;
yaw = up ? atan2(up[1], up[0]) : 0;
}
roll = 0;
}
else
{
yaw = atan2(value1[1], value1[0]);
pitch = -atan2(value1[2], sqrt (value1[0]*value1[0] + value1[1]*value1[1]));
if (up)
{
vec_t cp = cos(pitch), sp = sin(pitch);
vec_t cy = cos(yaw), sy = sin(yaw);
vec3_t tleft, tup;
tleft[0] = -sy;
tleft[1] = cy;
tleft[2] = 0;
tup[0] = sp*cy;
tup[1] = sp*sy;
tup[2] = cp;
roll = -atan2(DotProduct(up, tleft), DotProduct(up, tup));
}
else
roll = 0;
}
pitch *= -180 / M_PI;
yaw *= 180 / M_PI;
roll *= 180 / M_PI;
if (pitch < 0)
pitch += 360;
if (yaw < 0)
yaw += 360;
if (roll < 0)
roll += 360;
G_FLOAT(OFS_RETURN+0) = pitch;
G_FLOAT(OFS_RETURN+1) = yaw;
G_FLOAT(OFS_RETURN+2) = roll;
} }
//vector normalize(vector) //vector normalize(vector)

View file

@ -176,9 +176,22 @@ void PR_AutoCvar(progfuncs_t *prinst, cvar_t *var);
void QCBUILTIN PF_skel_create (progfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_skel_build (progfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_skel_get_numbones (progfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_skel_get_bonename (progfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_skel_get_boneparent (progfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_skel_find_bone (progfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_skel_get_bonerel (progfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_skel_get_boneabs (progfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_skel_set_bone (progfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_skel_mul_bone (progfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_skel_mul_bones (progfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_skel_copybones (progfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_skel_delete (progfuncs_t *prinst, struct globalvars_s *pr_globals);
void skel_lookup(progfuncs_t *prinst, int skelidx, framestate_t *out);
void skel_dodelete(progfuncs_t *prinst);
void skel_reset(progfuncs_t *prinst);
//pr_cmds.c builtins that need to be moved to a common. //pr_cmds.c builtins that need to be moved to a common.
void VARGS PR_BIError(progfuncs_t *progfuncs, char *format, ...) LIKEPRINTF(2); void VARGS PR_BIError(progfuncs_t *progfuncs, char *format, ...) LIKEPRINTF(2);

View file

@ -736,11 +736,11 @@ typedef struct entity_state_s
{ {
unsigned short number; // edict index unsigned short number; // edict index
unsigned short modelindex; unsigned short modelindex;
int bitmask; // for dp ents, so lost state can be repeated in replacement packets. unsigned int bitmask; // for dp ents, so lost state can be repeated in replacement packets.
int flags; // nolerp, etc unsigned int flags; // nolerp, etc
int effects; unsigned int effects;
vec3_t origin; vec3_t origin;
vec3_t angles; vec3_t angles;

View file

@ -122,7 +122,8 @@ struct world_s
void (*Event_Touch)(struct world_s *w, wedict_t *s, wedict_t *o); void (*Event_Touch)(struct world_s *w, wedict_t *s, wedict_t *o);
void (*Event_Think)(struct world_s *w, wedict_t *s); void (*Event_Think)(struct world_s *w, wedict_t *s);
void (*Event_Sound) (wedict_t *entity, int channel, char *sample, int volume, float attenuation, int pitchadj); void (*Event_Sound) (wedict_t *entity, int channel, char *sample, int volume, float attenuation, int pitchadj);
model_t *(*GetCModel)(struct world_s *w, int modelindex); model_t *(*Get_CModel)(struct world_s *w, int modelindex);
void (*Get_FrameState)(struct world_s *w, wedict_t *s, framestate_t *fstate);
unsigned int max_edicts; //limiting factor... 1024 fields*4*MAX_EDICTS == a heck of a lot. unsigned int max_edicts; //limiting factor... 1024 fields*4*MAX_EDICTS == a heck of a lot.
unsigned int num_edicts; // increases towards MAX_EDICTS unsigned int num_edicts; // increases towards MAX_EDICTS
@ -149,6 +150,10 @@ struct world_s
float *time; float *time;
float *frametime; float *frametime;
float *force_retouch; float *force_retouch;
float *physics_mode;
float *v_forward;
float *v_right;
float *v_up;
} g; } g;
#ifdef USEODE #ifdef USEODE

View file

@ -1,5 +1,6 @@
#include "quakedef.h" #include "quakedef.h"
#include "glquake.h" #include "glquake.h"
#include "gl_draw.h"
#ifdef D3DQUAKE #ifdef D3DQUAKE
#include "shader.h" #include "shader.h"
#if !defined(HMONITOR_DECLARED) && (WINVER < 0x0500) #if !defined(HMONITOR_DECLARED) && (WINVER < 0x0500)
@ -523,6 +524,8 @@ void D3DBE_Init(void)
shaderstate.dynidx_size = sizeof(index_t) * DYNIBUFFSIZE; shaderstate.dynidx_size = sizeof(index_t) * DYNIBUFFSIZE;
D3DBE_Reset(false); D3DBE_Reset(false);
R_InitFlashblends();
} }
static void allocvertexbuffer(IDirect3DVertexBuffer9 *buff, unsigned int bmaxsize, unsigned int *offset, void **data, unsigned int bytes) static void allocvertexbuffer(IDirect3DVertexBuffer9 *buff, unsigned int bmaxsize, unsigned int *offset, void **data, unsigned int bytes)
@ -744,15 +747,15 @@ static void colourgenbyte(const shaderpass_t *pass, int cnt, byte_vec4_t *src, b
((D3DCOLOR*)dst)[cnt] = block; ((D3DCOLOR*)dst)[cnt] = block;
} }
break; break;
case RGB_GEN_VERTEX: case RGB_GEN_VERTEX_LIGHTING:
case RGB_GEN_EXACT_VERTEX: case RGB_GEN_VERTEX_EXACT:
if (!src) if (!src)
{ {
while((cnt)--) while((cnt)--)
{ {
dst[cnt][0] = 255;//shaderstate.identitylighting; dst[cnt][0] = 255;
dst[cnt][1] = 255;//shaderstate.identitylighting; dst[cnt][1] = 255;
dst[cnt][2] = 255;//shaderstate.identitylighting; dst[cnt][2] = 255;
} }
} }
else else
@ -839,8 +842,8 @@ static void colourgenbyte(const shaderpass_t *pass, int cnt, byte_vec4_t *src, b
case RGB_GEN_TOPCOLOR: case RGB_GEN_TOPCOLOR:
case RGB_GEN_BOTTOMCOLOR: case RGB_GEN_BOTTOMCOLOR:
#ifdef _MSC_VER #ifdef warningmsg
#pragma message("fix 24bit player colours") #pragma warningmsg("fix 24bit player colours")
#endif #endif
block = D3DCOLOR_RGBA(255, 255, 255, 255); block = D3DCOLOR_RGBA(255, 255, 255, 255);
while((cnt)--) while((cnt)--)
@ -999,8 +1002,8 @@ static unsigned int BE_GenerateColourMods(unsigned int vertcount, const shaderpa
} }
} }
else if (m->colors4f_array && else if (m->colors4f_array &&
((pass->rgbgen == RGB_GEN_VERTEX) || ((pass->rgbgen == RGB_GEN_VERTEX_LIGHTING) ||
(pass->rgbgen == RGB_GEN_EXACT_VERTEX) || (pass->rgbgen == RGB_GEN_VERTEX_EXACT) ||
(pass->rgbgen == RGB_GEN_ONE_MINUS_VERTEX) || (pass->rgbgen == RGB_GEN_ONE_MINUS_VERTEX) ||
(pass->alphagen == ALPHA_GEN_VERTEX))) (pass->alphagen == ALPHA_GEN_VERTEX)))
{ {
@ -2060,27 +2063,30 @@ void BE_UploadLightmaps(qboolean force)
RECT rect; RECT rect;
glRect_t *theRect = &lightmap[i]->rectchange; glRect_t *theRect = &lightmap[i]->rectchange;
int r; int r;
if (tex) if (!tex)
{ {
lightmap[i]->modified = 0; lightmap_textures[i] = R_AllocNewTexture("***lightmap***", LMBLOCK_WIDTH, LMBLOCK_HEIGHT);
rect.left = theRect->l; tex = lightmap_textures[i].ptr;
rect.right = theRect->l + theRect->w; if (!tex)
rect.top = theRect->t; continue;
rect.bottom = theRect->t + theRect->h;
IDirect3DTexture9_LockRect(tex, 0, &lock, &rect, 0);
for (r = 0; r < lightmap[i]->rectchange.h; r++)
{
memcpy((char*)lock.pBits + r*lock.Pitch, lightmap[i]->lightmaps+(theRect->l+((r+theRect->t)*LMBLOCK_WIDTH))*lightmap_bytes, lightmap[i]->rectchange.w*lightmap_bytes);
}
IDirect3DTexture9_UnlockRect(tex, 0);
theRect->l = LMBLOCK_WIDTH;
theRect->t = LMBLOCK_HEIGHT;
theRect->h = 0;
theRect->w = 0;
} }
else
lightmap_textures[i] = R_AllocNewTexture(LMBLOCK_WIDTH, LMBLOCK_HEIGHT); lightmap[i]->modified = 0;
rect.left = theRect->l;
rect.right = theRect->l + theRect->w;
rect.top = theRect->t;
rect.bottom = theRect->t + theRect->h;
IDirect3DTexture9_LockRect(tex, 0, &lock, &rect, 0);
for (r = 0; r < lightmap[i]->rectchange.h; r++)
{
memcpy((char*)lock.pBits + r*lock.Pitch, lightmap[i]->lightmaps+(theRect->l+((r+theRect->t)*LMBLOCK_WIDTH))*lightmap_bytes, lightmap[i]->rectchange.w*lightmap_bytes);
}
IDirect3DTexture9_UnlockRect(tex, 0);
theRect->l = LMBLOCK_WIDTH;
theRect->t = LMBLOCK_HEIGHT;
theRect->h = 0;
theRect->w = 0;
} }
} }
} }
@ -2656,7 +2662,7 @@ void D3DBE_DrawWorld (qbyte *vis)
RSpeedEnd(RSPEED_DRAWENTITIES); RSpeedEnd(RSPEED_DRAWENTITIES);
} }
GLR_RenderDlights (); R_RenderDlights ();
BE_RotateForEntity(&r_worldentity, NULL); BE_RotateForEntity(&r_worldentity, NULL);
} }

View file

@ -9,33 +9,39 @@ extern LPDIRECT3DDEVICE9 pD3DDev9;
typedef struct d3dtexture_s typedef struct d3dtexture_s
{ {
texcom_t com;
struct d3dtexture_s *next; struct d3dtexture_s *next;
texid_t tex; texid_t tex;
qboolean loaded;
char name[1]; char name[1];
} d3dtexture_t; } d3dtexture_t;
static d3dtexture_t *d3dtextures; static d3dtexture_t *d3dtextures;
void D3D_Image_Shutdown(void)
{
LPDIRECT3DTEXTURE9 tx;
while(d3dtextures)
{
d3dtexture_t *t = d3dtextures;
d3dtextures = t->next;
tx = t->tex.ptr;
if (tx)
IDirect3DTexture9_Release(tx);
}
}
static d3dtexture_t *d3d_lookup_texture(char *ident) static d3dtexture_t *d3d_lookup_texture(char *ident)
{ {
d3dtexture_t *tex; d3dtexture_t *tex;
if (ident && *ident) for (tex = d3dtextures; tex; tex = tex->next)
{ if (!strcmp(tex->name, ident))
for (tex = d3dtextures; tex; tex = tex->next) return tex;
if (!strcmp(tex->name, ident))
return tex;
tex = malloc(sizeof(*tex)+strlen(ident)); tex = calloc(1, sizeof(*tex)+strlen(ident));
strcpy(tex->name, ident); strcpy(tex->name, ident);
}
else
{
tex = malloc(sizeof(*tex));
tex->name[0] = '\0';
}
tex->loaded = false;
tex->tex.ptr = NULL; tex->tex.ptr = NULL;
tex->tex.ref = &tex->com;
tex->next = d3dtextures; tex->next = d3dtextures;
d3dtextures = tex; d3dtextures = tex;
@ -45,7 +51,7 @@ static d3dtexture_t *d3d_lookup_texture(char *ident)
extern cvar_t gl_picmip; extern cvar_t gl_picmip;
extern cvar_t gl_picmip2d; extern cvar_t gl_picmip2d;
texid_t D3D9_AllocNewTexture(int width, int height) texid_t D3D9_AllocNewTexture(char *ident, int width, int height)
{ {
IDirect3DTexture9 *tx; IDirect3DTexture9 *tx;
texid_t ret = r_nulltex; texid_t ret = r_nulltex;
@ -57,7 +63,8 @@ texid_t D3D9_AllocNewTexture(int width, int height)
void D3D9_DestroyTexture (texid_t tex) void D3D9_DestroyTexture (texid_t tex)
{ {
IDirect3DTexture9 *tx = tex.ptr; IDirect3DTexture9 *tx = tex.ptr;
IDirect3DTexture9_Release(tx); if (tx)
IDirect3DTexture9_Release(tx);
} }
static void D3D9_RoundDimensions(int *scaled_width, int *scaled_height, qboolean mipmap) static void D3D9_RoundDimensions(int *scaled_width, int *scaled_height, qboolean mipmap)
@ -197,11 +204,10 @@ static void Upload_Texture_32(LPDIRECT3DTEXTURE9 tex, unsigned int *data, int wi
} }
//create a basic shader from a 32bit image //create a basic shader from a 32bit image
static LPDIRECT3DBASETEXTURE9 D3D9_LoadTexture_32(d3dtexture_t *tex, unsigned int *data, int width, int height, int flags) static void D3D9_LoadTexture_32(d3dtexture_t *tex, unsigned int *data, int width, int height, int flags)
{ {
int nwidth, nheight; int nwidth, nheight;
LPDIRECT3DTEXTURE9 newsurf;
/* /*
if (!(flags & TF_MANDATORY)) if (!(flags & TF_MANDATORY))
{ {
@ -214,21 +220,19 @@ static LPDIRECT3DBASETEXTURE9 D3D9_LoadTexture_32(d3dtexture_t *tex, unsigned in
nheight = height; nheight = height;
D3D9_RoundDimensions(&nwidth, &nheight, !(flags & IF_NOMIPMAP)); D3D9_RoundDimensions(&nwidth, &nheight, !(flags & IF_NOMIPMAP));
newsurf = tex->tex.ptr; if (!tex->tex.ptr)
if (!newsurf) {
LPDIRECT3DTEXTURE9 newsurf;
IDirect3DDevice9_CreateTexture(pD3DDev9, nwidth, nheight, (flags & IF_NOMIPMAP)?1:0, ((flags & IF_NOMIPMAP)?0:D3DUSAGE_AUTOGENMIPMAP), D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &newsurf, NULL); IDirect3DDevice9_CreateTexture(pD3DDev9, nwidth, nheight, (flags & IF_NOMIPMAP)?1:0, ((flags & IF_NOMIPMAP)?0:D3DUSAGE_AUTOGENMIPMAP), D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &newsurf, NULL);
if (!newsurf)
return;
tex->tex.ptr = newsurf;
}
if (!newsurf) Upload_Texture_32(tex->tex.ptr, data, width, height, flags);
return NULL;
Upload_Texture_32(newsurf, data, width, height, flags);
tex->loaded = true;
return (LPDIRECT3DBASETEXTURE9)newsurf;
} }
static LPDIRECT3DBASETEXTURE9 D3D9_LoadTexture_8(d3dtexture_t *tex, unsigned char *data, unsigned int *pal32, int width, int height, int flags, enum uploadfmt fmt) static void D3D9_LoadTexture_8(d3dtexture_t *tex, unsigned char *data, unsigned int *pal32, int width, int height, int flags, enum uploadfmt fmt)
{ {
static unsigned trans[1024*1024]; static unsigned trans[1024*1024];
int i, s; int i, s;
@ -331,7 +335,7 @@ static LPDIRECT3DBASETEXTURE9 D3D9_LoadTexture_8(d3dtexture_t *tex, unsigned cha
trans[i] = pal32[data[i]]; trans[i] = pal32[data[i]];
} }
} }
return D3D9_LoadTexture_32(tex, trans, width, height, flags); D3D9_LoadTexture_32(tex, trans, width, height, flags);
} }
void D3D9_Upload (texid_t tex, char *name, enum uploadfmt fmt, void *data, void *palette, int width, int height, unsigned int flags) void D3D9_Upload (texid_t tex, char *name, enum uploadfmt fmt, void *data, void *palette, int width, int height, unsigned int flags)
@ -352,7 +356,6 @@ void D3D9_Upload (texid_t tex, char *name, enum uploadfmt fmt, void *data, vo
texid_t D3D9_LoadTexture (char *identifier, int width, int height, enum uploadfmt fmt, void *data, unsigned int flags) texid_t D3D9_LoadTexture (char *identifier, int width, int height, enum uploadfmt fmt, void *data, unsigned int flags)
{ {
texid_t tid;
d3dtexture_t *tex; d3dtexture_t *tex;
switch (fmt) switch (fmt)
{ {
@ -399,13 +402,13 @@ texid_t D3D9_LoadTexture (char *identifier, int width, int height, enum uploadfm
case TF_H2_TRANS8_0: case TF_H2_TRANS8_0:
case TF_H2_T4A4: case TF_H2_T4A4:
case TF_TRANS8_FULLBRIGHT: case TF_TRANS8_FULLBRIGHT:
tid.ptr = D3D9_LoadTexture_8(tex, data, d_8to24rgbtable, width, height, flags, fmt); D3D9_LoadTexture_8(tex, data, d_8to24rgbtable, width, height, flags, fmt);
return tid; return tex->tex;
case TF_RGBX32: case TF_RGBX32:
flags |= IF_NOALPHA; flags |= IF_NOALPHA;
case TF_RGBA32: case TF_RGBA32:
tid.ptr = D3D9_LoadTexture_32(tex, data, width, height, flags); D3D9_LoadTexture_32(tex, data, width, height, flags);
return tid; return tex->tex;
default: default:
OutputDebugString(va("D3D_LoadTexture doesn't support fmt %i", fmt)); OutputDebugString(va("D3D_LoadTexture doesn't support fmt %i", fmt));
return r_nulltex; return r_nulltex;
@ -420,13 +423,15 @@ texid_t D3D9_LoadCompressed (char *name)
texid_t D3D9_FindTexture (char *identifier) texid_t D3D9_FindTexture (char *identifier)
{ {
d3dtexture_t *tex = d3d_lookup_texture(identifier); d3dtexture_t *tex = d3d_lookup_texture(identifier);
return tex->tex; if (tex->tex.ptr)
return tex->tex;
return r_nulltex;
} }
texid_t D3D9_LoadTexture8Pal32 (char *identifier, int width, int height, qbyte *data, qbyte *palette32, unsigned int flags) texid_t D3D9_LoadTexture8Pal32 (char *identifier, int width, int height, qbyte *data, qbyte *palette32, unsigned int flags)
{ {
d3dtexture_t *tex = d3d_lookup_texture(identifier); d3dtexture_t *tex = d3d_lookup_texture(identifier);
tex->tex.ptr = D3D9_LoadTexture_8(tex, data, (unsigned int *)palette32, width, height, flags, TF_SOLID8); D3D9_LoadTexture_8(tex, data, (unsigned int *)palette32, width, height, flags, TF_SOLID8);
return tex->tex; return tex->tex;
} }
texid_t D3D9_LoadTexture8Pal24 (char *identifier, int width, int height, qbyte *data, qbyte *palette24, unsigned int flags) texid_t D3D9_LoadTexture8Pal24 (char *identifier, int width, int height, qbyte *data, qbyte *palette24, unsigned int flags)

View file

@ -50,9 +50,6 @@
#define WM_INPUT 255 #define WM_INPUT 255
#endif #endif
int gl_bumpmappingpossible;
//static void D3D9_GetBufferSize(int *width, int *height); //not defined //static void D3D9_GetBufferSize(int *width, int *height); //not defined
static void resetD3D9(void); static void resetD3D9(void);
static LPDIRECT3D9 pD3D; static LPDIRECT3D9 pD3D;
@ -1082,8 +1079,8 @@ static void (D3D9_SCR_UpdateScreen) (void)
RSpeedEnd(RSPEED_TOTALREFRESH); RSpeedEnd(RSPEED_TOTALREFRESH);
RSpeedShow(); RSpeedShow();
#ifdef _MSC_VER #ifdef warningmsg
#pragma message("Fixme: ... to here") #pragma warningmsg("Fixme: ... to here")
#endif #endif
@ -1119,6 +1116,8 @@ static void (D3D9_R_Init) (void)
static void (D3D9_R_DeInit) (void) static void (D3D9_R_DeInit) (void)
{ {
Surf_DeInit(); Surf_DeInit();
Shader_Shutdown();
D3D_Image_Shutdown();
} }
@ -1297,6 +1296,7 @@ rendererinfo_t d3drendererinfo =
D3DBE_ClearVBO, D3DBE_ClearVBO,
D3DBE_UploadAllLightmaps, D3DBE_UploadAllLightmaps,
NULL, NULL,
NULL,
D3DBE_LightCullModel, D3DBE_LightCullModel,
"no more" "no more"

File diff suppressed because it is too large Load diff

View file

@ -31,6 +31,9 @@
/> />
<Tool <Tool
Name="VCCustomBuildTool" Name="VCCustomBuildTool"
Description="Registering ActiveX Control..."
CommandLine="regsvr32 /s /c &quot;$(TargetPath)&quot;&#x0D;&#x0A;echo regsvr32 exec. time &gt; &quot;$(OutDir)\regsvr32.trg&quot;&#x0D;&#x0A;"
Outputs="$(OutDir)\regsvr32.trg"
/> />
<Tool <Tool
Name="VCXMLDataGeneratorTool" Name="VCXMLDataGeneratorTool"
@ -447,6 +450,18 @@
RelativePath="..\ftequake\npplug.rc" RelativePath="..\ftequake\npplug.rc"
> >
</File> </File>
<File
RelativePath="..\client\sys_axfte.cpp"
>
<FileConfiguration
Name="GLDebug|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="0"
/>
</FileConfiguration>
</File>
<File <File
RelativePath="..\client\sys_npfte.c" RelativePath="..\client\sys_npfte.c"
> >
@ -11112,6 +11127,10 @@
/> />
</FileConfiguration> </FileConfiguration>
</File> </File>
<File
RelativePath="..\client\pr_skelobj.c"
>
</File>
<File <File
RelativePath="..\client\r_part.c" RelativePath="..\client\r_part.c"
> >

View file

@ -1,7 +1,17 @@
LIBRARY npfte.dll
EXPORTS EXPORTS
;npapi
NP_GetEntryPoints NP_GetEntryPoints
NP_GetMIMEDescription NP_GetMIMEDescription
NP_Initialize NP_Initialize
NP_Shutdown NP_Shutdown
;activex
DllCanUnloadNow PRIVATE
DllGetClassObject PRIVATE
DllRegisterServer PRIVATE
DllUnregisterServer PRIVATE
;fte-specific
Plug_GetFuncs Plug_GetFuncs

View file

@ -514,12 +514,12 @@ static texnums_t *GL_ChooseSkin(galiasinfo_t *inf, model_t *model, int surfnum,
} }
if (qrenderer == QR_OPENGL) if (qrenderer == QR_OPENGL)
{ {
texnums->base = R_AllocNewTexture(scaled_width, scaled_height); texnums->base = R_AllocNewTexture(cm->name, scaled_width, scaled_height);
R_Upload(texnums->base, "", h2playertranslations?TF_RGBA32:TF_RGBX32, pixels, NULL, scaled_width, scaled_height, IF_NOMIPMAP); R_Upload(texnums->base, cm->name, h2playertranslations?TF_RGBA32:TF_RGBX32, pixels, NULL, scaled_width, scaled_height, IF_NOMIPMAP);
} }
else else
{ {
texnums->base = R_LoadTexture(NULL, scaled_width, scaled_height, h2playertranslations?TF_RGBA32:TF_RGBX32, pixels, 0); texnums->base = R_LoadTexture(cm->name, scaled_width, scaled_height, h2playertranslations?TF_RGBA32:TF_RGBX32, pixels, 0);
} }
if (!h2playertranslations) if (!h2playertranslations)
@ -540,12 +540,12 @@ static texnums_t *GL_ChooseSkin(galiasinfo_t *inf, model_t *model, int surfnum,
} }
if (qrenderer == QR_OPENGL) if (qrenderer == QR_OPENGL)
{ {
texnums->fullbright = R_AllocNewTexture(scaled_width, scaled_height); texnums->fullbright = R_AllocNewTexture(cm->name, scaled_width, scaled_height);
R_Upload(texnums->fullbright, "", TF_RGBA32, pixels, NULL, scaled_width, scaled_height, IF_NOMIPMAP); R_Upload(texnums->fullbright, cm->name, TF_RGBA32, pixels, NULL, scaled_width, scaled_height, IF_NOMIPMAP);
} }
else else
{ {
texnums->fullbright = R_LoadTexture(NULL, scaled_width, scaled_height, h2playertranslations?TF_RGBA32:TF_RGBX32, pixels, 0); texnums->fullbright = R_LoadTexture(cm->name, scaled_width, scaled_height, h2playertranslations?TF_RGBA32:TF_RGBX32, pixels, 0);
} }
} }
} }
@ -783,7 +783,8 @@ static qboolean R_CalcModelLighting(entity_t *e, model_t *clmodel)
dist); dist);
add = cl_dlights[i].radius - Length(dist); add = cl_dlights[i].radius - Length(dist);
if (add > 0) { if (add > 0)
{
add*=5; add*=5;
ambientlight[0] += add * cl_dlights[i].color[0]; ambientlight[0] += add * cl_dlights[i].color[0];
ambientlight[1] += add * cl_dlights[i].color[1]; ambientlight[1] += add * cl_dlights[i].color[1];
@ -853,7 +854,7 @@ static qboolean R_CalcModelLighting(entity_t *e, model_t *clmodel)
ambientlight[i] /= 200.0/255; ambientlight[i] /= 200.0/255;
} }
if ((e->model->flags & EF_ROTATE) && cl.hexen2pickups) if ((e->model->flags & MF_ROTATE) && cl.hexen2pickups)
{ {
shadelight[0] = shadelight[1] = shadelight[2] = shadelight[0] = shadelight[1] = shadelight[2] =
ambientlight[0] = ambientlight[1] = ambientlight[2] = 128+sin(cl.servertime*4)*64; ambientlight[0] = ambientlight[1] = ambientlight[2] = 128+sin(cl.servertime*4)*64;

View file

@ -4,7 +4,7 @@
//FIXME: this shouldn't be defined //FIXME: this shouldn't be defined
#define FORCESTATE #define FORCESTATE
#else #else
//#define FORCESTATE #define FORCESTATE
#endif #endif
//#define WIREFRAME //#define WIREFRAME
@ -34,37 +34,35 @@ uniform mat4 entmatrix;\n\
#define LIGHTPASS_GLSL_VERTEX "\ #define LIGHTPASS_GLSL_VERTEX "\
#ifdef VERTEX_SHADER\n\ #ifdef VERTEX_SHADER\n\
#include \"sys/skeletal.h\"\n\
\ \
uniform vec3 l_lightposition;\n\ uniform vec3 l_lightposition;\n\
attribute vec2 v_texcoord;\n\
\ \
#if defined(SPECULAR) || defined(OFFSETMAPPING)\n\ #if defined(SPECULAR) || defined(OFFSETMAPPING)\n\
uniform vec3 eyeposition;\n\ uniform vec3 e_eyepos;\n\
#endif\n\ #endif\n\
\ \
attribute vec2 v_texcoord;\n\ void main ()\n\
attribute vec3 v_normal;\n\
attribute vec3 v_svector;\n\
attribute vec3 v_tvector;\n\
\
void main (void)\n\
{\n\ {\n\
gl_Position = ftetransform();\n\ vec3 n, s, t, w;\n\
gl_Position = skeletaltransform_wnst(w,n,s,t);\n\
\ \
tcbase = v_texcoord; //pass the texture coords straight through\n\ tcbase = v_texcoord; //pass the texture coords straight through\n\
\ \
vec3 lightminusvertex = l_lightposition - v_position.xyz;\n\ vec3 lightminusvertex = l_lightposition - w.xyz;\n\
lightvector.x = dot(lightminusvertex, v_svector.xyz);\n\ lightvector.x = dot(lightminusvertex, s.xyz);\n\
lightvector.y = dot(lightminusvertex, v_tvector.xyz);\n\ lightvector.y = dot(lightminusvertex, t.xyz);\n\
lightvector.z = dot(lightminusvertex, v_normal.xyz);\n\ lightvector.z = dot(lightminusvertex, n.xyz);\n\
\ \
#if defined(SPECULAR)||defined(OFFSETMAPPING)\n\ #if defined(SPECULAR)||defined(OFFSETMAPPING)\n\
vec3 eyeminusvertex = eyeposition - v_position.xyz;\n\ vec3 eyeminusvertex = e_eyepos - w.xyz;\n\
eyevector.x = dot(eyeminusvertex, v_svector.xyz);\n\ eyevector.x = dot(eyeminusvertex, s.xyz);\n\
eyevector.y = -dot(eyeminusvertex, v_tvector.xyz);\n\ eyevector.y = -dot(eyeminusvertex, t.xyz);\n\
eyevector.z = dot(eyeminusvertex, v_normal.xyz);\n\ eyevector.z = dot(eyeminusvertex, n.xyz);\n\
#endif\n\ #endif\n\
#if defined(PCF) || defined(SPOT) || defined(PROJECTION)\n\ #if defined(PCF) || defined(SPOT) || defined(PROJECTION)\n\
vshadowcoord = gl_TextureMatrix[7] * (entmatrix*vec4(v_position.xyz, 1.0));\n\ vshadowcoord = gl_TextureMatrix[7] * (entmatrix*vec4(w.xyz, 1.0));\n\
#endif\n\ #endif\n\
}\n\ }\n\
#endif\n\ #endif\n\
@ -76,25 +74,25 @@ void main (void)\n\
float xPixelOffset = (1.0+shadowcoord.b/l_lightradius)/texx;\ float xPixelOffset = (1.0+shadowcoord.b/l_lightradius)/texx;\
float yPixelOffset = (1.0+shadowcoord.b/l_lightradius)/texy;\ float yPixelOffset = (1.0+shadowcoord.b/l_lightradius)/texy;\
float s = 0.0;\n\ float s = 0.0;\n\
s += "f"Proj(shadowmap, shadowcoord + vec4(-1.5 * xPixelOffset * shadowcoord.w, -1.5 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ s += "f"Proj(s_t7, shadowcoord + vec4(-1.5 * xPixelOffset * shadowcoord.w, -1.5 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\
s += "f"Proj(shadowmap, shadowcoord + vec4(-1.5 * xPixelOffset * shadowcoord.w, -0.5 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ s += "f"Proj(s_t7, shadowcoord + vec4(-1.5 * xPixelOffset * shadowcoord.w, -0.5 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\
s += "f"Proj(shadowmap, shadowcoord + vec4(-1.5 * xPixelOffset * shadowcoord.w, 0.5 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ s += "f"Proj(s_t7, shadowcoord + vec4(-1.5 * xPixelOffset * shadowcoord.w, 0.5 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\
s += "f"Proj(shadowmap, shadowcoord + vec4(-1.5 * xPixelOffset * shadowcoord.w, 1.1 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ s += "f"Proj(s_t7, shadowcoord + vec4(-1.5 * xPixelOffset * shadowcoord.w, 1.1 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\
\ \
s += "f"Proj(shadowmap, shadowcoord + vec4(-0.5 * xPixelOffset * shadowcoord.w, -1.5 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ s += "f"Proj(s_t7, shadowcoord + vec4(-0.5 * xPixelOffset * shadowcoord.w, -1.5 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\
s += "f"Proj(shadowmap, shadowcoord + vec4(-0.5 * xPixelOffset * shadowcoord.w, -0.5 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ s += "f"Proj(s_t7, shadowcoord + vec4(-0.5 * xPixelOffset * shadowcoord.w, -0.5 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\
s += "f"Proj(shadowmap, shadowcoord + vec4(-0.5 * xPixelOffset * shadowcoord.w, 0.5 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ s += "f"Proj(s_t7, shadowcoord + vec4(-0.5 * xPixelOffset * shadowcoord.w, 0.5 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\
s += "f"Proj(shadowmap, shadowcoord + vec4(-0.5 * xPixelOffset * shadowcoord.w, 1.1 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ s += "f"Proj(s_t7, shadowcoord + vec4(-0.5 * xPixelOffset * shadowcoord.w, 1.1 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\
\ \
s += "f"Proj(shadowmap, shadowcoord + vec4(0.5 * xPixelOffset * shadowcoord.w, -1.5 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ s += "f"Proj(s_t7, shadowcoord + vec4(0.5 * xPixelOffset * shadowcoord.w, -1.5 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\
s += "f"Proj(shadowmap, shadowcoord + vec4(0.5 * xPixelOffset * shadowcoord.w, -0.5 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ s += "f"Proj(s_t7, shadowcoord + vec4(0.5 * xPixelOffset * shadowcoord.w, -0.5 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\
s += "f"Proj(shadowmap, shadowcoord + vec4(0.5 * xPixelOffset * shadowcoord.w, 0.5 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ s += "f"Proj(s_t7, shadowcoord + vec4(0.5 * xPixelOffset * shadowcoord.w, 0.5 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\
s += "f"Proj(shadowmap, shadowcoord + vec4(0.5 * xPixelOffset * shadowcoord.w, 1.1 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ s += "f"Proj(s_t7, shadowcoord + vec4(0.5 * xPixelOffset * shadowcoord.w, 1.1 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\
\ \
s += "f"Proj(shadowmap, shadowcoord + vec4(1.5 * xPixelOffset * shadowcoord.w, -1.5 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ s += "f"Proj(s_t7, shadowcoord + vec4(1.5 * xPixelOffset * shadowcoord.w, -1.5 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\
s += "f"Proj(shadowmap, shadowcoord + vec4(1.5 * xPixelOffset * shadowcoord.w, -0.5 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ s += "f"Proj(s_t7, shadowcoord + vec4(1.5 * xPixelOffset * shadowcoord.w, -0.5 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\
s += "f"Proj(shadowmap, shadowcoord + vec4(1.5 * xPixelOffset * shadowcoord.w, 0.5 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ s += "f"Proj(s_t7, shadowcoord + vec4(1.5 * xPixelOffset * shadowcoord.w, 0.5 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\
s += "f"Proj(shadowmap, shadowcoord + vec4(1.5 * xPixelOffset * shadowcoord.w, 1.1 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ s += "f"Proj(s_t7, shadowcoord + vec4(1.5 * xPixelOffset * shadowcoord.w, 1.1 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\
\ \
colorscale *= s/5.0;\n\ colorscale *= s/5.0;\n\
" "
@ -105,17 +103,17 @@ void main (void)\n\
const float xPixelOffset = 1.0/texx;\ const float xPixelOffset = 1.0/texx;\
const float yPixelOffset = 1.0/texy;\ const float yPixelOffset = 1.0/texy;\
float s = 0.0;\n\ float s = 0.0;\n\
s += "f"Proj(shadowmap, shadowcoord + vec4(-1.0 * xPixelOffset * shadowcoord.w, -1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ s += "f"Proj(s_t7, shadowcoord + vec4(-1.0 * xPixelOffset * shadowcoord.w, -1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\
s += "f"Proj(shadowmap, shadowcoord + vec4(-1.0 * xPixelOffset * shadowcoord.w, 0.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ s += "f"Proj(s_t7, shadowcoord + vec4(-1.0 * xPixelOffset * shadowcoord.w, 0.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\
s += "f"Proj(shadowmap, shadowcoord + vec4(-1.0 * xPixelOffset * shadowcoord.w, 1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ s += "f"Proj(s_t7, shadowcoord + vec4(-1.0 * xPixelOffset * shadowcoord.w, 1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\
\ \
s += "f"Proj(shadowmap, shadowcoord + vec4(0.0 * xPixelOffset * shadowcoord.w, -1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ s += "f"Proj(s_t7, shadowcoord + vec4(0.0 * xPixelOffset * shadowcoord.w, -1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\
s += "f"Proj(shadowmap, shadowcoord + vec4(0.0 * xPixelOffset * shadowcoord.w, 0.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ s += "f"Proj(s_t7, shadowcoord + vec4(0.0 * xPixelOffset * shadowcoord.w, 0.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\
s += "f"Proj(shadowmap, shadowcoord + vec4(0.0 * xPixelOffset * shadowcoord.w, 1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ s += "f"Proj(s_t7, shadowcoord + vec4(0.0 * xPixelOffset * shadowcoord.w, 1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\
\ \
s += "f"Proj(shadowmap, shadowcoord + vec4(1.0 * xPixelOffset * shadowcoord.w, -1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ s += "f"Proj(s_t7, shadowcoord + vec4(1.0 * xPixelOffset * shadowcoord.w, -1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\
s += "f"Proj(shadowmap, shadowcoord + vec4(1.0 * xPixelOffset * shadowcoord.w, 0.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ s += "f"Proj(s_t7, shadowcoord + vec4(1.0 * xPixelOffset * shadowcoord.w, 0.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\
s += "f"Proj(shadowmap, shadowcoord + vec4(1.0 * xPixelOffset * shadowcoord.w, 1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ s += "f"Proj(s_t7, shadowcoord + vec4(1.0 * xPixelOffset * shadowcoord.w, 1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\
colorscale *= s/9.0;\n\ colorscale *= s/9.0;\n\
" "
@ -125,11 +123,11 @@ void main (void)\n\
float xPixelOffset = 1.0/texx;\ float xPixelOffset = 1.0/texx;\
float yPixelOffset = 1.0/texy;\ float yPixelOffset = 1.0/texy;\
float s = 0.0;\n\ float s = 0.0;\n\
s += "f"Proj(shadowmap, shadowcoord + vec4(-1.0 * xPixelOffset * shadowcoord.w, -1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ s += "f"Proj(s_t7, shadowcoord + vec4(-1.0 * xPixelOffset * shadowcoord.w, -1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\
s += "f"Proj(shadowmap, shadowcoord + vec4(-1.0 * xPixelOffset * shadowcoord.w, 1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ s += "f"Proj(s_t7, shadowcoord + vec4(-1.0 * xPixelOffset * shadowcoord.w, 1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\
s += "f"Proj(shadowmap, shadowcoord + vec4(0.0 * xPixelOffset * shadowcoord.w, 0.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ s += "f"Proj(s_t7, shadowcoord + vec4(0.0 * xPixelOffset * shadowcoord.w, 0.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\
s += "f"Proj(shadowmap, shadowcoord + vec4(1.0 * xPixelOffset * shadowcoord.w, -1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ s += "f"Proj(s_t7, shadowcoord + vec4(1.0 * xPixelOffset * shadowcoord.w, -1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\
s += "f"Proj(shadowmap, shadowcoord + vec4(1.0 * xPixelOffset * shadowcoord.w, 1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ s += "f"Proj(s_t7, shadowcoord + vec4(1.0 * xPixelOffset * shadowcoord.w, 1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\
colorscale *= s/5.0;\n\ colorscale *= s/5.0;\n\
" "
@ -139,21 +137,21 @@ void main (void)\n\
#define LIGHTPASS_GLSL_FRAGMENT "\ #define LIGHTPASS_GLSL_FRAGMENT "\
#ifdef FRAGMENT_SHADER\n\ #ifdef FRAGMENT_SHADER\n\
uniform sampler2D baset;\n\ uniform sampler2D s_t0;\n"/*base texture*/"\
#if defined(BUMP) || defined(SPECULAR) || defined(OFFSETMAPPING)\n\ #if defined(BUMP) || defined(SPECULAR) || defined(OFFSETMAPPING)\n\
uniform sampler2D bumpt;\n\ uniform sampler2D s_t1;\n"/*normalmap/height texture*/"\
#endif\n\ #endif\n\
#ifdef SPECULAR\n\ #ifdef SPECULAR\n\
uniform sampler2D speculart;\n\ uniform sampler2D s_t2;\n"/*specularmap texture*/"\
#endif\n\ #endif\n\
#ifdef PROJECTION\n\ #ifdef PROJECTION\n\
uniform sampler2D projected;\n\ uniform sampler2D s_t3;\n"/*projected texture*/"\
#endif\n\ #endif\n\
#ifdef PCF\n\ #ifdef PCF\n\
#ifdef CUBE\n\ #ifdef CUBE\n\
uniform samplerCubeShadow shadowmap;\n\ uniform samplerCubeShadow s_t7;\n\
#else\n\ #else\n\
uniform sampler2DShadow shadowmap;\n\ uniform sampler2DShadow s_t7;\n\
#endif\n\ #endif\n\
#endif\n\ #endif\n\
\ \
@ -166,7 +164,7 @@ uniform float offsetmapping_scale;\n\
#endif\n\ #endif\n\
\ \
\ \
void main (void)\n\ void main ()\n\
{\n\ {\n\
#ifdef OFFSETMAPPING\n\ #ifdef OFFSETMAPPING\n\
vec2 OffsetVector = normalize(eyevector).xy * offsetmapping_scale * vec2(1, -1);\n\ vec2 OffsetVector = normalize(eyevector).xy * offsetmapping_scale * vec2(1, -1);\n\
@ -174,22 +172,22 @@ void main (void)\n\
#define tcbase foo\n\ #define tcbase foo\n\
tcbase += OffsetVector;\n\ tcbase += OffsetVector;\n\
OffsetVector *= 0.333;\n\ OffsetVector *= 0.333;\n\
tcbase -= OffsetVector * texture2D(bumpt, tcbase).w;\n\ tcbase -= OffsetVector * texture2D(s_t1, tcbase).w;\n\
tcbase -= OffsetVector * texture2D(bumpt, tcbase).w;\n\ tcbase -= OffsetVector * texture2D(s_t1, tcbase).w;\n\
tcbase -= OffsetVector * texture2D(bumpt, tcbase).w;\n\ tcbase -= OffsetVector * texture2D(s_t1, tcbase).w;\n\
#endif\n\ #endif\n\
\ \
\ \
#ifdef BUMP\n\ #ifdef BUMP\n\
vec3 bases = vec3(texture2D(baset, tcbase));\n\ vec3 bases = vec3(texture2D(s_t0, tcbase));\n\
#else\n\ #else\n\
vec3 diff = vec3(texture2D(baset, tcbase));\n\ vec3 diff = vec3(texture2D(s_t0, tcbase));\n\
#endif\n\ #endif\n\
#if defined(BUMP) || defined(SPECULAR)\n\ #if defined(BUMP) || defined(SPECULAR)\n\
vec3 bumps = vec3(texture2D(bumpt, tcbase)) * 2.0 - 1.0;\n\ vec3 bumps = vec3(texture2D(s_t1, tcbase)) * 2.0 - 1.0;\n\
#endif\n\ #endif\n\
#ifdef SPECULAR\n\ #ifdef SPECULAR\n\
vec3 specs = vec3(texture2D(speculart, tcbase));\n\ vec3 specs = vec3(texture2D(s_t2, tcbase));\n\
#endif\n\ #endif\n\
\ \
vec3 nl = normalize(lightvector);\n\ vec3 nl = normalize(lightvector);\n\
@ -229,7 +227,7 @@ if (shadowcoord.w < 0.0) discard;\n\
vec2 spot = ((shadowcoord.st)/shadowcoord.w - 0.5)*2.0;colorscale*=1.0-(dot(spot,spot));\n\ vec2 spot = ((shadowcoord.st)/shadowcoord.w - 0.5)*2.0;colorscale*=1.0-(dot(spot,spot));\n\
#endif\n\ #endif\n\
#if defined(PROJECTION)\n\ #if defined(PROJECTION)\n\
l_lightcolour *= texture2d(projected, shadowcoord);\n\ l_lightcolour *= texture2d(s_t3, shadowcoord);\n\
#endif\n\ #endif\n\
\n\ \n\
gl_FragColor.rgb = diff*colorscale*l_lightcolour;\n\ gl_FragColor.rgb = diff*colorscale*l_lightcolour;\n\
@ -257,33 +255,19 @@ static const char LIGHTPASS_SHADER[] = "\
#define LIGHTPASS\n\ #define LIGHTPASS\n\
%s\n\ %s\n\
}\n\ }\n\
\
//incoming fragment\n\
param texture 0 baset\n\
param opt texture 1 bumpt\n\
param opt texture 2 speculart\n\
\ \
param opt cvarf r_glsl_offsetmapping_bias offsetmapping_bias\n\ param opt cvarf r_glsl_offsetmapping_bias offsetmapping_bias\n\
param opt cvarf r_glsl_offsetmapping_scale offsetmapping_scale\n\ param opt cvarf r_glsl_offsetmapping_scale offsetmapping_scale\n\
\
//eye pos\n\
param opt eyepos eyeposition\n\
\ \
{\n\ {\n\
map $diffuse\n\ map $diffuse\n\
blendfunc add\n\ blendfunc add\n\
tcgen base\n\
}\n\ }\n\
{\n\ {\n\
map $normalmap\n\ map $normalmap\n\
tcgen normal\n\
}\n\ }\n\
{\n\ {\n\
map $specular\n\ map $specular\n\
tcgen svector\n\
}\n\
{\n\
tcgen tvector\n\
}\n\ }\n\
}"; }";
static const char PCFPASS_SHADER[] = "\ static const char PCFPASS_SHADER[] = "\
@ -297,33 +281,24 @@ static const char PCFPASS_SHADER[] = "\
}\n\ }\n\
\ \
//incoming fragment\n\ //incoming fragment\n\
param texture 7 shadowmap\n\
param texture 1 baset\n\
param opt texture 2 bumpt\n\
param opt texture 3 speculart\n\
\ \
param opt cvarf r_glsl_offsetmapping_scale offsetmapping_scale\n\ param opt cvarf r_glsl_offsetmapping_scale offsetmapping_scale\n\
\ \
//eye pos\n\ //eye pos\n\
param opt eyepos EyePosition\n\
param opt entmatrix entmatrix\n\ param opt entmatrix entmatrix\n\
\ \
{\n\
map $shadowmap\n\
blendfunc add\n\
tcgen base\n\
}\n\
{\n\ {\n\
map $diffuse\n\ map $diffuse\n\
tcgen normal\n\ blendfunc add\n\
}\n\ }\n\
{\n\ {\n\
map $normalmap\n\ map $normalmap\n\
tcgen svector\n\
}\n\ }\n\
{\n\ {\n\
map $specular\n\ map $specular\n\
tcgen tvector\n\ }\n\
{\n\
map $shadowmap\n\
}\n\ }\n\
}"; }";
@ -379,6 +354,7 @@ struct {
mesh_t **meshes; mesh_t **meshes;
unsigned int meshcount; unsigned int meshcount;
float modelmatrix[16];
float modelviewmatrix[16]; float modelviewmatrix[16];
int pendingvertexvbo; int pendingvertexvbo;
@ -388,7 +364,7 @@ struct {
float identitylighting; //set to how bright lightmaps should be (reduced for overbright or realtime_world_lightmaps) float identitylighting; //set to how bright lightmaps should be (reduced for overbright or realtime_world_lightmaps)
texid_t temptexture; texid_t temptexture; //$current
texid_t fogtexture; texid_t fogtexture;
float fogfar; float fogfar;
}; };
@ -424,6 +400,49 @@ struct {
int shadowsurfcount; int shadowsurfcount;
} bench; } bench;
static void BE_PolyOffset(qboolean pushdepth)
{
if (pushdepth)
{
/*some quake doors etc are flush with the walls that they're meant to be hidden behind, or plats the same height as the floor, etc
we move them back very slightly using polygonoffset to avoid really ugly z-fighting*/
extern cvar_t r_polygonoffset_submodel_offset, r_polygonoffset_submodel_factor;
polyoffset_t po;
po.factor = shaderstate.curshader->polyoffset.factor + r_polygonoffset_submodel_factor.value;
po.unit = shaderstate.curshader->polyoffset.unit + r_polygonoffset_submodel_offset.value;
#ifndef FORCESTATE
if (((int*)&shaderstate.curpolyoffset)[0] != ((int*)&po)[0] || ((int*)&shaderstate.curpolyoffset)[1] != ((int*)&po)[1])
#endif
{
shaderstate.curpolyoffset = po;
if (shaderstate.curpolyoffset.factor || shaderstate.curpolyoffset.unit)
{
qglEnable(GL_POLYGON_OFFSET_FILL);
qglPolygonOffset(shaderstate.curpolyoffset.factor, shaderstate.curpolyoffset.unit);
}
else
qglDisable(GL_POLYGON_OFFSET_FILL);
}
}
else
{
#ifndef FORCESTATE
if (*(int*)&shaderstate.curpolyoffset != *(int*)&shaderstate.curshader->polyoffset || *(int*)&shaderstate.curpolyoffset != *(int*)&shaderstate.curshader->polyoffset)
#endif
{
shaderstate.curpolyoffset = shaderstate.curshader->polyoffset;
if (shaderstate.curpolyoffset.factor || shaderstate.curpolyoffset.unit)
{
qglEnable(GL_POLYGON_OFFSET_FILL);
qglPolygonOffset(shaderstate.curpolyoffset.factor, shaderstate.curpolyoffset.unit);
}
else
qglDisable(GL_POLYGON_OFFSET_FILL);
}
}
}
void GL_TexEnv(GLenum mode) void GL_TexEnv(GLenum mode)
{ {
#ifndef FORCESTATE #ifndef FORCESTATE
@ -877,7 +896,7 @@ static void T_Gen_CurrentRender(int tmu)
} }
// copy the scene to texture // copy the scene to texture
if (!TEXVALID(shaderstate.temptexture)) if (!TEXVALID(shaderstate.temptexture))
shaderstate.temptexture = GL_AllocNewTexture(vwidth, vheight); TEXASSIGN(shaderstate.temptexture, GL_AllocNewTexture("***$currentrender***", vwidth, vheight));
GL_MTBind(tmu, GL_TEXTURE_2D, shaderstate.temptexture); GL_MTBind(tmu, GL_TEXTURE_2D, shaderstate.temptexture);
qglCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, vwidth, vheight, 0); qglCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, vwidth, vheight, 0);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
@ -886,14 +905,11 @@ static void T_Gen_CurrentRender(int tmu)
static void Shader_BindTextureForPass(int tmu, const shaderpass_t *pass, qboolean useclientarray) static void Shader_BindTextureForPass(int tmu, const shaderpass_t *pass, qboolean useclientarray)
{ {
extern texid_t scenepp_postproc_cube;
texid_t t; texid_t t;
switch(pass->texgen) switch(pass->texgen)
{ {
default: default:
case T_GEN_SKYBOX:
t = pass->anim_frames[0];
GL_LazyBind(tmu, GL_TEXTURE_CUBE_MAP_ARB, t, useclientarray);
return;
case T_GEN_SINGLEMAP: case T_GEN_SINGLEMAP:
t = pass->anim_frames[0]; t = pass->anim_frames[0];
break; break;
@ -928,6 +944,15 @@ static void Shader_BindTextureForPass(int tmu, const shaderpass_t *pass, qboolea
t = shaderstate.curshadowmap; t = shaderstate.curshadowmap;
break; break;
case T_GEN_SKYBOX:
t = pass->anim_frames[0];
GL_LazyBind(tmu, GL_TEXTURE_CUBE_MAP_ARB, t, useclientarray);
return;
case T_GEN_SOURCECUBE:
t = scenepp_postproc_cube;
GL_LazyBind(tmu, GL_TEXTURE_CUBE_MAP_ARB, t, useclientarray);
return;
case T_GEN_VIDEOMAP: case T_GEN_VIDEOMAP:
#ifdef NOMEDIA #ifdef NOMEDIA
t = shaderstate.curtexnums?shaderstate.curtexnums->base:r_nulltex; t = shaderstate.curtexnums?shaderstate.curtexnums->base:r_nulltex;
@ -1070,7 +1095,7 @@ void GenerateFogTexture(texid_t *tex, float density, float zscale)
} }
if (!TEXVALID(*tex)) if (!TEXVALID(*tex))
*tex = R_AllocNewTexture(FOGS, FOGT); *tex = R_AllocNewTexture("***fog***", FOGS, FOGT);
R_Upload(*tex, "fog", TF_RGBA32, fogdata, NULL, FOGS, FOGT, IF_CLAMP|IF_NOMIPMAP); R_Upload(*tex, "fog", TF_RGBA32, fogdata, NULL, FOGS, FOGT, IF_CLAMP|IF_NOMIPMAP);
} }
@ -1133,6 +1158,8 @@ void GLBE_Init(void)
r_worldentity.axis[0][0] = 1; r_worldentity.axis[0][0] = 1;
r_worldentity.axis[1][1] = 1; r_worldentity.axis[1][1] = 1;
r_worldentity.axis[2][2] = 1; r_worldentity.axis[2][2] = 1;
R_InitFlashblends();
} }
//end tables //end tables
@ -1428,15 +1455,35 @@ static void colourgen(const shaderpass_t *pass, int cnt, vec4_t *src, vec4_t *ds
dst[cnt][2] = 1-shaderstate.curentity->shaderRGBAf[2]; dst[cnt][2] = 1-shaderstate.curentity->shaderRGBAf[2];
} }
break; break;
case RGB_GEN_VERTEX: case RGB_GEN_VERTEX_LIGHTING:
case RGB_GEN_EXACT_VERTEX: if (shaderstate.identitylighting != 1)
{
if (!src)
{
while((cnt)--)
{
dst[cnt][0] = shaderstate.identitylighting;
dst[cnt][1] = shaderstate.identitylighting;
dst[cnt][2] = shaderstate.identitylighting;
}
break;
}
while((cnt)--)
{
dst[cnt][0] = src[cnt][0]*shaderstate.identitylighting;
dst[cnt][1] = src[cnt][1]*shaderstate.identitylighting;
dst[cnt][2] = src[cnt][2]*shaderstate.identitylighting;
}
break;
}
case RGB_GEN_VERTEX_EXACT:
if (!src) if (!src)
{ {
while((cnt)--) while((cnt)--)
{ {
dst[cnt][0] = shaderstate.identitylighting; dst[cnt][0] = 1;
dst[cnt][1] = shaderstate.identitylighting; dst[cnt][1] = 1;
dst[cnt][2] = shaderstate.identitylighting; dst[cnt][2] = 1;
} }
break; break;
} }
@ -1495,7 +1542,7 @@ static void colourgen(const shaderpass_t *pass, int cnt, vec4_t *src, vec4_t *ds
} }
else else
{ {
R_LightArrays(shaderstate.curentity, mesh->xyz_array, dst, cnt, mesh->normals_array); R_LightArrays(shaderstate.curentity, mesh->xyz_array, dst, cnt, mesh->normals_array, shaderstate.identitylighting);
} }
break; break;
case RGB_GEN_WAVE: case RGB_GEN_WAVE:
@ -1983,7 +2030,7 @@ static void GenerateColourMods(const shaderpass_t *pass)
qglShadeModel(GL_SMOOTH); qglShadeModel(GL_SMOOTH);
//if its vetex lighting, just use the vbo //if its vetex lighting, just use the vbo
if ((pass->rgbgen == RGB_GEN_VERTEX || pass->rgbgen == RGB_GEN_EXACT_VERTEX) && pass->alphagen == ALPHA_GEN_VERTEX) if (((pass->rgbgen == RGB_GEN_VERTEX_LIGHTING && shaderstate.identitylighting == 1) || pass->rgbgen == RGB_GEN_VERTEX_EXACT) && pass->alphagen == ALPHA_GEN_VERTEX)
{ {
GL_SelectVBO(shaderstate.sourcevbo->vbocolours); GL_SelectVBO(shaderstate.sourcevbo->vbocolours);
qglColorPointer(4, GL_FLOAT, 0, shaderstate.sourcevbo->colours4f); qglColorPointer(4, GL_FLOAT, 0, shaderstate.sourcevbo->colours4f);
@ -2061,8 +2108,8 @@ static void BE_SendPassBlendDepthMask(unsigned int sbits)
unsigned int delta; unsigned int delta;
/*2d mode doesn't depth test or depth write*/ /*2d mode doesn't depth test or depth write*/
#ifdef _MSC_VER #ifdef warningmsg
#pragma message("fixme: q3 doesn't seem to have this, why do we need it?") #pragma warningmsg("fixme: q3 doesn't seem to have this, why do we need it?")
#endif #endif
if (shaderstate.force2d) if (shaderstate.force2d)
{ {
@ -2441,20 +2488,7 @@ static unsigned int BE_Program_Set_Attribute(const shaderprogparm_t *p, unsigned
} }
break; break;
case SP_M_MODEL: case SP_M_MODEL:
{ qglUniformMatrix4fvARB(p->handle[perm], 1, false, shaderstate.modelmatrix);
float m16[16];
Matrix4x4_CM_ModelMatrixFromAxis(m16, shaderstate.curentity->axis[0], shaderstate.curentity->axis[1], shaderstate.curentity->axis[2], shaderstate.curentity->origin);
/* VectorCopy(shaderstate.curentity->axis[0], m16+0);
m16[3] = 0;
VectorCopy(shaderstate.curentity->axis[1], m16+1);
m16[7] = 0;
VectorCopy(shaderstate.curentity->axis[2], m16+2);
m16[11] = 0;
VectorCopy(shaderstate.curentity->origin, m16+3);
m16[15] = 1;
*/
qglUniformMatrix4fvARB(p->handle[perm], 1, false, m16);
}
break; break;
case SP_M_ENTBONES: case SP_M_ENTBONES:
{ {
@ -2532,35 +2566,21 @@ static unsigned int BE_Program_Set_Attribute(const shaderprogparm_t *p, unsigned
break; break;
case SP_E_EYEPOS: case SP_E_EYEPOS:
{ {
float m16[16]; /*eye position in model space*/
#ifdef _MSC_VER
#pragma message("is this correct?")
#endif
// vec3_t t1;
vec3_t t2; vec3_t t2;
Matrix4x4_CM_ModelMatrixFromAxis(m16, shaderstate.curentity->axis[0], shaderstate.curentity->axis[1], shaderstate.curentity->axis[2], shaderstate.curentity->origin); Matrix4x4_CM_Transform3(shaderstate.modelmatrix, r_origin, t2);
Matrix4x4_CM_Transform3(m16, r_origin, t2);
// VectorSubtract(r_origin, shaderstate.curentity->origin, t1);
// Matrix3_Multiply_Vec3(shaderstate.curentity->axis, t1, t2);
qglUniform3fvARB(p->handle[perm], 1, t2); qglUniform3fvARB(p->handle[perm], 1, t2);
} }
break; break;
case SP_LIGHTPOSITION: case SP_LIGHTPOSITION:
{ {
#ifdef _MSC_VER /*light position in model space*/
#pragma message("is this correct?")
#endif
float inv[16]; float inv[16];
float m16[16];
// vec3_t t1;
vec3_t t2; vec3_t t2;
qboolean Matrix4_Invert(const float *m, float *out); qboolean Matrix4_Invert(const float *m, float *out);
Matrix4x4_CM_ModelMatrixFromAxis(m16, shaderstate.curentity->axis[0], shaderstate.curentity->axis[1], shaderstate.curentity->axis[2], shaderstate.curentity->origin); Matrix4_Invert(shaderstate.modelmatrix, inv);
Matrix4_Invert(m16, inv);
Matrix4x4_CM_Transform3(inv, shaderstate.lightorg, t2); Matrix4x4_CM_Transform3(inv, shaderstate.lightorg, t2);
// VectorSubtract(shaderstate.lightorg, shaderstate.curentity->origin, t1);
// Matrix3_Multiply_Vec3(shaderstate.curentity->axis, t1, t2);
qglUniform3fvARB(p->handle[perm], 1, t2); qglUniform3fvARB(p->handle[perm], 1, t2);
} }
break; break;
@ -2721,7 +2741,7 @@ qboolean GLBE_LightCullModel(vec3_t org, model_t *model)
return false; return false;
} }
//Note: Be cautious about using BEM_LIGHT here. //Note: Be cautious about using BEM_LIGHT here, as it won't select the light.
void GLBE_SelectMode(backendmode_t mode) void GLBE_SelectMode(backendmode_t mode)
{ {
extern int gldepthfunc; extern int gldepthfunc;
@ -2730,10 +2750,36 @@ void GLBE_SelectMode(backendmode_t mode)
{ {
shaderstate.mode = mode; shaderstate.mode = mode;
shaderstate.flags = 0; shaderstate.flags = 0;
#ifdef RTLIGHTS switch (mode)
if (mode == BEM_STENCIL)
{ {
case BEM_DEPTHONLY:
GL_DeSelectProgram(); GL_DeSelectProgram();
/*BEM_DEPTHONLY does support mesh writing, but its not the only way its used... FIXME!*/
qglDisableClientState(GL_COLOR_ARRAY);
while(shaderstate.lastpasstmus>0)
{
GL_LazyBind(--shaderstate.lastpasstmus, 0, r_nulltex, false);
}
qglShadeModel(GL_FLAT);
//we don't write or blend anything (maybe alpha test... but mneh)
BE_SendPassBlendDepthMask(SBITS_MISC_DEPTHWRITE | SBITS_MASK_BITS);
BE_SetPassBlendMode(0, PBM_REPLACE);
GL_CullFace(SHADER_CULL_FRONT);
break;
#ifdef RTLIGHTS
case BEM_STENCIL:
GL_DeSelectProgram();
if (shaderstate.curpolyoffset.factor || shaderstate.curpolyoffset.unit)
{
shaderstate.curpolyoffset.factor = 0;
shaderstate.curpolyoffset.unit = 0;
qglDisable(GL_POLYGON_OFFSET_FILL);
}
/*BEM_STENCIL doesn't support mesh writing*/ /*BEM_STENCIL doesn't support mesh writing*/
qglDisableClientState(GL_COLOR_ARRAY); qglDisableClientState(GL_COLOR_ARRAY);
//disable all tmus //disable all tmus
@ -2751,52 +2797,33 @@ void GLBE_SelectMode(backendmode_t mode)
//don't change cull stuff, and //don't change cull stuff, and
//don't actually change stencil stuff - caller needs to be //don't actually change stencil stuff - caller needs to be
//aware of how many times stuff is drawn, so they can do that themselves. //aware of how many times stuff is drawn, so they can do that themselves.
} break;
#endif
if (mode == BEM_DEPTHONLY)
{
GL_DeSelectProgram();
/*BEM_DEPTHONLY does support mesh writing, but its not the only way its used... FIXME!*/
qglDisableClientState(GL_COLOR_ARRAY);
while(shaderstate.lastpasstmus>0)
{
GL_LazyBind(--shaderstate.lastpasstmus, 0, r_nulltex, false);
}
qglShadeModel(GL_FLAT);
//we don't write or blend anything (maybe alpha test... but mneh) case BEM_SMAPLIGHT:
BE_SendPassBlendDepthMask(SBITS_MISC_DEPTHWRITE | SBITS_MASK_BITS);
BE_SetPassBlendMode(0, PBM_REPLACE);
GL_CullFace(SHADER_CULL_FRONT);
}
#ifdef RTLIGHTS
if (mode == BEM_SMAPLIGHT)
{
if (!shaderstate.initedpcfpasses) if (!shaderstate.initedpcfpasses)
{ {
shaderstate.initedpcfpasses = true; shaderstate.initedpcfpasses = true;
shaderstate.pcfpassshader = R_RegisterCustom("lightpass_pcf", Shader_LightPass_PCF, NULL); shaderstate.pcfpassshader = R_RegisterCustom("lightpass_pcf", Shader_LightPass_PCF, NULL);
} }
} break;
if (mode == BEM_SMAPLIGHTSPOT)
{ case BEM_SMAPLIGHTSPOT:
if (!shaderstate.initedspotpasses) if (!shaderstate.initedspotpasses)
{ {
shaderstate.initedspotpasses = true; shaderstate.initedspotpasses = true;
shaderstate.spotpassshader = R_RegisterCustom("lightpass_spot", Shader_LightPass_Spot, NULL); shaderstate.spotpassshader = R_RegisterCustom("lightpass_spot", Shader_LightPass_Spot, NULL);
} }
} break;
if (mode == BEM_LIGHT)
{ case BEM_LIGHT:
if (!shaderstate.initedlightpasses) if (!shaderstate.initedlightpasses)
{ {
shaderstate.initedlightpasses = true; shaderstate.initedlightpasses = true;
shaderstate.lightpassshader = R_RegisterCustom("lightpass", Shader_LightPass_Std, NULL); shaderstate.lightpassshader = R_RegisterCustom("lightpass", Shader_LightPass_Std, NULL);
} }
} break;
if (mode == BEM_FOG) #endif
{ case BEM_FOG:
while(shaderstate.lastpasstmus>0) while(shaderstate.lastpasstmus>0)
{ {
GL_LazyBind(--shaderstate.lastpasstmus, 0, r_nulltex, false); GL_LazyBind(--shaderstate.lastpasstmus, 0, r_nulltex, false);
@ -2809,8 +2836,8 @@ void GLBE_SelectMode(backendmode_t mode)
qglShadeModel(GL_FLAT); qglShadeModel(GL_FLAT);
BE_SetPassBlendMode(0, PBM_MODULATE); BE_SetPassBlendMode(0, PBM_MODULATE);
BE_SendPassBlendDepthMask(SBITS_SRCBLEND_SRC_ALPHA | SBITS_DSTBLEND_ONE_MINUS_SRC_ALPHA | SBITS_MISC_DEPTHEQUALONLY); BE_SendPassBlendDepthMask(SBITS_SRCBLEND_SRC_ALPHA | SBITS_DSTBLEND_ONE_MINUS_SRC_ALPHA | SBITS_MISC_DEPTHEQUALONLY);
break;
} }
#endif
} }
} }
@ -2820,7 +2847,7 @@ void GLBE_SelectEntity(entity_t *ent)
qglDepthRange (gldepthmin, gldepthmax); qglDepthRange (gldepthmin, gldepthmax);
shaderstate.curentity = ent; shaderstate.curentity = ent;
currententity = ent; currententity = ent;
R_RotateForEntity(shaderstate.modelviewmatrix, shaderstate.curentity, shaderstate.curentity->model); R_RotateForEntity(shaderstate.modelmatrix, shaderstate.modelviewmatrix, shaderstate.curentity, shaderstate.curentity->model);
if (qglLoadMatrixf) if (qglLoadMatrixf)
qglLoadMatrixf(shaderstate.modelviewmatrix); qglLoadMatrixf(shaderstate.modelviewmatrix);
if (shaderstate.curentity->flags & Q2RF_DEPTHHACK && qglDepthRange) if (shaderstate.curentity->flags & Q2RF_DEPTHHACK && qglDepthRange)
@ -2840,7 +2867,7 @@ void BE_SelectFog(vec3_t colour, float alpha, float density)
qglColor4f(colour[0], colour[1], colour[2], alpha); qglColor4f(colour[0], colour[1], colour[2], alpha);
} }
void BE_SelectDLight(dlight_t *dl, vec3_t colour) void GLBE_SelectDLight(dlight_t *dl, vec3_t colour)
{ {
shaderstate.lightradius = dl->radius; shaderstate.lightradius = dl->radius;
VectorCopy(dl->origin, shaderstate.lightorg); VectorCopy(dl->origin, shaderstate.lightorg);
@ -2893,49 +2920,6 @@ void BE_PushOffsetShadow(qboolean pushdepth)
} }
} }
void BE_PolyOffset(qboolean pushdepth)
{
if (pushdepth)
{
/*some quake doors etc are flush with the walls that they're meant to be hidden behind, or plats the same height as the floor, etc
we move them back very slightly using polygonoffset to avoid really ugly z-fighting*/
extern cvar_t r_polygonoffset_submodel_offset, r_polygonoffset_submodel_factor;
polyoffset_t po;
po.factor = shaderstate.curshader->polyoffset.factor + r_polygonoffset_submodel_factor.value;
po.unit = shaderstate.curshader->polyoffset.unit + r_polygonoffset_submodel_offset.value;
#ifndef FORCESTATE
if (((int*)&shaderstate.curpolyoffset)[0] != ((int*)&po)[0] || ((int*)&shaderstate.curpolyoffset)[1] != ((int*)&po)[1])
#endif
{
shaderstate.curpolyoffset = po;
if (shaderstate.curpolyoffset.factor || shaderstate.curpolyoffset.unit)
{
qglEnable(GL_POLYGON_OFFSET_FILL);
qglPolygonOffset(shaderstate.curpolyoffset.factor, shaderstate.curpolyoffset.unit);
}
else
qglDisable(GL_POLYGON_OFFSET_FILL);
}
}
else
{
#ifndef FORCESTATE
if (*(int*)&shaderstate.curpolyoffset != *(int*)&shaderstate.curshader->polyoffset || *(int*)&shaderstate.curpolyoffset != *(int*)&shaderstate.curshader->polyoffset)
#endif
{
shaderstate.curpolyoffset = shaderstate.curshader->polyoffset;
if (shaderstate.curpolyoffset.factor || shaderstate.curpolyoffset.unit)
{
qglEnable(GL_POLYGON_OFFSET_FILL);
qglPolygonOffset(shaderstate.curpolyoffset.factor, shaderstate.curpolyoffset.unit);
}
else
qglDisable(GL_POLYGON_OFFSET_FILL);
}
}
}
static void DrawMeshes(void) static void DrawMeshes(void)
{ {
const shaderpass_t *p; const shaderpass_t *p;
@ -3007,8 +2991,8 @@ static void DrawMeshes(void)
#endif #endif
case BEM_DEPTHONLY: case BEM_DEPTHONLY:
GL_DeSelectProgram(); GL_DeSelectProgram();
#ifdef _MSC_VER #ifdef warningmsg
#pragma message("fixme: support alpha test") #pragma warningmsg("fixme: support alpha test")
#endif #endif
GL_ApplyVertexPointer(); GL_ApplyVertexPointer();
BE_SubmitMeshChain(); BE_SubmitMeshChain();
@ -3273,7 +3257,7 @@ static void BE_SubmitMeshesSortList(batch_t *sortlist)
continue; continue;
if (batch->shader->flags & SHADER_SKY) if (batch->shader->flags & SHADER_SKY)
{ {
if (shaderstate.mode == BEM_STANDARD) if (shaderstate.mode == BEM_STANDARD || shaderstate.mode == BEM_DEPTHDARK)
{ {
if (!batch->shader->prog) if (!batch->shader->prog)
{ {
@ -3381,7 +3365,7 @@ void BE_BaseEntTextures(void)
{ {
batch_t *batches[SHADER_SORT_COUNT]; batch_t *batches[SHADER_SORT_COUNT];
BE_GenModelBatches(batches); BE_GenModelBatches(batches);
GLBE_SubmitMeshes(false, batches, SHADER_SORT_PORTAL, SHADER_SORT_NEAREST); GLBE_SubmitMeshes(false, batches, SHADER_SORT_PORTAL, SHADER_SORT_DECAL);
BE_SelectEntity(&r_worldentity); BE_SelectEntity(&r_worldentity);
} }
#endif #endif
@ -3423,7 +3407,7 @@ void GLBE_DrawLightPrePass(qbyte *vis, batch_t **batches)
#define GL_RGBA32F_ARB 0x8814 #define GL_RGBA32F_ARB 0x8814
if (!TEXVALID(shaderstate.tex_normals)) if (!TEXVALID(shaderstate.tex_normals))
{ {
shaderstate.tex_normals = GL_AllocNewTexture(vid.pixelwidth, vid.pixelheight); shaderstate.tex_normals = GL_AllocNewTexture("***prepass normals***", vid.pixelwidth, vid.pixelheight);
r_lightprepass.modified = true; r_lightprepass.modified = true;
} }
if (r_lightprepass.modified) if (r_lightprepass.modified)
@ -3439,7 +3423,7 @@ void GLBE_DrawLightPrePass(qbyte *vis, batch_t **batches)
{ {
int drb; int drb;
shaderstate.tex_diffuse = GL_AllocNewTexture(vid.pixelwidth, vid.pixelheight); shaderstate.tex_diffuse = GL_AllocNewTexture("***prepass diffuse***", vid.pixelwidth, vid.pixelheight);
GL_MTBind(0, GL_TEXTURE_2D, shaderstate.tex_diffuse); GL_MTBind(0, GL_TEXTURE_2D, shaderstate.tex_diffuse);
qglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, vid.pixelwidth, vid.pixelheight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); qglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, vid.pixelwidth, vid.pixelheight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
@ -3469,6 +3453,7 @@ void GLBE_DrawLightPrePass(qbyte *vis, batch_t **batches)
/*set the FB up to draw surface info*/ /*set the FB up to draw surface info*/
qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, shaderstate.tex_normals.num, 0); qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, shaderstate.tex_normals.num, 0);
GL_ForceDepthWritable();
qglClear(GL_DEPTH_BUFFER_BIT); qglClear(GL_DEPTH_BUFFER_BIT);
if (GL_FRAMEBUFFER_COMPLETE_EXT != qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT)) if (GL_FRAMEBUFFER_COMPLETE_EXT != qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT))
@ -3563,7 +3548,7 @@ void GLBE_DrawWorld (qbyte *vis)
else else
#endif #endif
shaderstate.identitylighting = 1; shaderstate.identitylighting = 1;
// shaderstate.identitylighting /= 1<<gl_overbright.ival; // shaderstate.identitylighting /= 1<<gl_overbright.ival;
#ifdef RTLIGHTS #ifdef RTLIGHTS
if (r_lightprepass.ival) if (r_lightprepass.ival)
@ -3579,7 +3564,7 @@ void GLBE_DrawWorld (qbyte *vis)
BE_SelectMode(BEM_STANDARD); BE_SelectMode(BEM_STANDARD);
RSpeedRemark(); RSpeedRemark();
GLBE_SubmitMeshes(true, batches, SHADER_SORT_PORTAL, SHADER_SORT_NEAREST); GLBE_SubmitMeshes(true, batches, SHADER_SORT_PORTAL, SHADER_SORT_DECAL);
RSpeedEnd(RSPEED_WORLD); RSpeedEnd(RSPEED_WORLD);
} }
@ -3590,6 +3575,10 @@ void GLBE_DrawWorld (qbyte *vis)
RSpeedEnd(RSPEED_STENCILSHADOWS); RSpeedEnd(RSPEED_STENCILSHADOWS);
#endif #endif
shaderstate.identitylighting = 1;
GLBE_SubmitMeshes(true, batches, SHADER_SORT_DECAL, SHADER_SORT_NEAREST);
if (r_refdef.gfog_alpha) if (r_refdef.gfog_alpha)
{ {
BE_SelectMode(BEM_FOG); BE_SelectMode(BEM_FOG);
@ -3606,5 +3595,7 @@ void GLBE_DrawWorld (qbyte *vis)
shaderstate.curtime = shaderstate.updatetime = realtime; shaderstate.curtime = shaderstate.updatetime = realtime;
checkglerror(); checkglerror();
shaderstate.identitylighting = 1;
} }
#endif #endif

View file

@ -192,7 +192,7 @@ void R_Bloom_InitTextures(void)
data = Z_Malloc(size); data = Z_Malloc(size);
memset(data, 255, size); memset(data, 255, size);
if (!TEXVALID(bs.tx_screen)) if (!TEXVALID(bs.tx_screen))
bs.tx_screen = GL_AllocNewTexture(bs.scr_w, bs.scr_h); bs.tx_screen = GL_AllocNewTexture("***bloom screen***", bs.scr_w, bs.scr_h);
GL_MTBind(0, GL_TEXTURE_2D, bs.tx_screen); GL_MTBind(0, GL_TEXTURE_2D, bs.tx_screen);
qglTexImage2D (GL_TEXTURE_2D, 0, GL_RGB, bs.scr_w, bs.scr_h, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); qglTexImage2D (GL_TEXTURE_2D, 0, GL_RGB, bs.scr_w, bs.scr_h, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
@ -506,8 +506,8 @@ void R_BloomBlend (void)
return; return;
PPL_RevertToKnownState(); PPL_RevertToKnownState();
#ifdef _MSC_VER #ifdef warningmsg
#pragma message("Note: Bloom doesn't use the backend.") #pragma warningmsg("Note: Bloom doesn't use the backend.")
#endif #endif
//set up full screen workspace //set up full screen workspace

View file

@ -136,8 +136,6 @@ unsigned char *d_15to8table;
qboolean inited15to8; qboolean inited15to8;
#endif #endif
static texid_t filmtexture;
extern cvar_t gl_max_size; extern cvar_t gl_max_size;
extern cvar_t gl_picmip; extern cvar_t gl_picmip;
extern cvar_t gl_lerpimages; extern cvar_t gl_lerpimages;
@ -164,6 +162,7 @@ int gl_filter_max_2d = GL_LINEAR;
typedef struct gltexture_s typedef struct gltexture_s
{ {
texcom_t com;
texid_t texnum; texid_t texnum;
char identifier[64]; char identifier[64];
int width, height, bpp; int width, height, bpp;
@ -173,6 +172,41 @@ typedef struct gltexture_s
static gltexture_t *gltextures; static gltexture_t *gltextures;
static gltexture_t *GL_AllocNewGLTexture(char *ident, int w, int h)
{
gltexture_t *glt;
glt = BZ_Malloc(sizeof(*glt) + sizeof(bucket_t));
glt->next = gltextures;
gltextures = glt;
glt->texnum.ref = &glt->com;
Q_strncpyz (glt->identifier, ident, sizeof(glt->identifier));
glt->flags = IF_NOMIPMAP;
glt->width = w;
glt->height = h;
glt->bpp = 0;
glt->com.regsequence = r_regsequence;
qglGenTextures(1, &glt->texnum.num);
Hash_Add(&gltexturetable, glt->identifier, glt, (bucket_t*)(glt+1));
return glt;
}
texid_t GL_AllocNewTexture(char *name, int w, int h)
{
gltexture_t *glt = GL_AllocNewGLTexture(name, w, h);
return glt->texnum;
}
void GL_DestroyTexture(texid_t tex)
{
if (!tex.ref)
return;
qglDeleteTextures(1, &tex.num);
}
//============================================================================= //=============================================================================
/* Support Routines */ /* Support Routines */
@ -259,7 +293,10 @@ void GL_Texturemode_Callback (struct cvar_s *var, char *oldvalue)
{ {
GL_MTBind(0, GL_TEXTURE_2D, glt->texnum); GL_MTBind(0, GL_TEXTURE_2D, glt->texnum);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min); qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max); if (glt->flags & IF_NEAREST)
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
else
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
} }
} }
} }
@ -294,17 +331,49 @@ void GL_Texturemode2d_Callback (struct cvar_s *var, char *oldvalue)
{ {
GL_MTBind(0, GL_TEXTURE_2D, glt->texnum); GL_MTBind(0, GL_TEXTURE_2D, glt->texnum);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_max_2d); qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_max_2d);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max_2d); if (glt->flags & IF_NEAREST)
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
else
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max_2d);
} }
} }
} }
void GLDraw_ImageList_f(void)
{
int count = 0;
gltexture_t *glt;
for (glt=gltextures ; glt ; glt=glt->next)
{
count++;
Con_Printf("%s (%i*%i, seq=%i)\n", glt->identifier, glt->width, glt->height, glt->com.regsequence);
}
Con_Printf("%i images\n", count);
}
void GLDraw_FlushOldTextures(void)
{
gltexture_t **link = &gltextures, *t;
while (*link)
{
t = *link;
if (t->com.regsequence != r_regsequence)
{
qglDeleteTextures(1, &t->texnum.num);
(*link)->next = t->next;
BZ_Free(t);
}
else
link = &(*link)->next;
}
}
/* /*
=============== ===============
Draw_Init Draw_Init
=============== ===============
*/ */
void GLDraw_Init (void)
void GLDraw_ReInit (void)
{ {
char ver[40]; char ver[40];
@ -319,9 +388,6 @@ void GLDraw_ReInit (void)
memset(gltexturetablebuckets, 0, sizeof(gltexturetablebuckets)); memset(gltexturetablebuckets, 0, sizeof(gltexturetablebuckets));
Hash_InitTable(&gltexturetable, sizeof(gltexturetablebuckets)/sizeof(gltexturetablebuckets[0]), gltexturetablebuckets); Hash_InitTable(&gltexturetable, sizeof(gltexturetablebuckets)/sizeof(gltexturetablebuckets[0]), gltexturetablebuckets);
lightmap_textures=NULL;
filmtexture=r_nulltex;
GL_FlushBackEnd(); GL_FlushBackEnd();
// GL_FlushSkinCache(); // GL_FlushSkinCache();
TRACE(("dbg: GLDraw_ReInit: GL_GAliasFlushSkinCache\n")); TRACE(("dbg: GLDraw_ReInit: GL_GAliasFlushSkinCache\n"));
@ -393,18 +459,13 @@ TRACE(("dbg: GLDraw_ReInit: Allocating upload buffers\n"));
TRACE(("dbg: GLDraw_ReInit: PPL_LoadSpecularFragmentProgram\n")); TRACE(("dbg: GLDraw_ReInit: PPL_LoadSpecularFragmentProgram\n"));
GL_InitSceneProcessingShaders(); GL_InitSceneProcessingShaders();
Cmd_AddRemCommand ("r_imagelist", GLDraw_ImageList_f);
} }
void GLDraw_Init (void)
{
// memset(scrap_allocated, 0, sizeof(scrap_allocated));
// memset(scrap_texels, 255, sizeof(scrap_texels));
GLDraw_ReInit();
}
void GLDraw_DeInit (void) void GLDraw_DeInit (void)
{ {
Cmd_RemoveCommand ("gl_texture_anisotropic_filtering"); Cmd_RemoveCommand ("r_imagelist");
if (font_conchar) if (font_conchar)
Font_Free(font_conchar); Font_Free(font_conchar);
@ -434,6 +495,7 @@ void GLDraw_DeInit (void)
gltexture_t *glt; gltexture_t *glt;
glt = gltextures; glt = gltextures;
gltextures = gltextures->next; gltextures = gltextures->next;
BZ_Free(glt); BZ_Free(glt);
} }
@ -921,12 +983,18 @@ qboolean GL_UploadCompressed (qbyte *file, int *out_width, int *out_height, unsi
if (!((*out_flags) & IF_NOMIPMAP)) if (!((*out_flags) & IF_NOMIPMAP))
{ {
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min); qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max); if (*out_flags & IF_NEAREST)
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
else
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
} }
else else
{ {
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_max_2d); qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_max_2d);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max_2d); if (*out_flags & IF_NEAREST)
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
else
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max_2d);
} }
return true; return true;
} }
@ -1090,16 +1158,22 @@ void GL_Upload32_Int (char *name, unsigned *data, int width, int height, unsigne
TRACE(("dbg: GL_Upload32: GL_SGIS_generate_mipmap\n")); TRACE(("dbg: GL_Upload32: GL_SGIS_generate_mipmap\n"));
qglTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, GL_TRUE); qglTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, GL_TRUE);
} }
if (!(flags&IF_NOMIPMAP)) if (!(flags&IF_NOMIPMAP))
{ {
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min); qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max); if (flags & IF_NEAREST)
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
else
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
} }
else else
{ {
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_max_2d); qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_max_2d);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max_2d); if (flags & IF_NEAREST)
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
else
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max_2d);
} }
if (flags&IF_CLAMP) if (flags&IF_CLAMP)
@ -1430,12 +1504,18 @@ done: ;
if (!(flags&IF_NOMIPMAP)) if (!(flags&IF_NOMIPMAP))
{ {
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min); qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max); if (flags & IF_NEAREST)
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
else
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
} }
else else
{ {
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_max_2d); qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_max_2d);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max_2d); if (flags & IF_NEAREST)
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
else
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max_2d);
} }
} }
@ -1623,12 +1703,18 @@ void GL_UploadBump(qbyte *data, int width, int height, qboolean mipmap, float bu
if (mipmap) if (mipmap)
{ {
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min); qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max); if (0 & IF_NEAREST)
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
else
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
} }
else else
{ {
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_max_2d); qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_max_2d);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max_2d); if (0 & IF_NEAREST)
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
else
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max_2d);
} }
// if (gl_texturefilteranisotropic) // if (gl_texturefilteranisotropic)
@ -1713,12 +1799,18 @@ done: ;
if (mipmap) if (mipmap)
{ {
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max); if (flags & IF_NEAREST)
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
else
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
} }
else else
{ {
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_max_2d); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_max_2d);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max_2d); if (flags & IF_NEAREST)
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
else
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max_2d);
} }
} }
#endif #endif
@ -1993,18 +2085,10 @@ TRACE(("dbg: GL_LoadTexture: duplicate %s\n", identifier));
TRACE(("dbg: GL_LoadTexture: new %s\n", identifier)); TRACE(("dbg: GL_LoadTexture: new %s\n", identifier));
glt = BZ_Malloc(sizeof(*glt)+sizeof(bucket_t)); glt = GL_AllocNewGLTexture(identifier, width, height);
glt->next = gltextures;
gltextures = glt;
strcpy (glt->identifier, identifier);
glt->texnum = GL_AllocNewTexture(width, height);
glt->width = width;
glt->height = height;
glt->bpp = 8; glt->bpp = 8;
glt->flags = flags; glt->flags = flags;
Hash_Add(&gltexturetable, glt->identifier, glt, (bucket_t*)(glt+1));
checkglerror(); checkglerror();
GL_MTBind(0, GL_TEXTURE_2D, glt->texnum); GL_MTBind(0, GL_TEXTURE_2D, glt->texnum);
@ -2033,19 +2117,10 @@ texid_t GL_LoadTextureFB (char *identifier, int width, int height, qbyte *data,
if (i == width*height) if (i == width*height)
return r_nulltex; //none found, don't bother uploading. return r_nulltex; //none found, don't bother uploading.
glt = BZ_Malloc(sizeof(*glt)+sizeof(bucket_t)); glt = GL_AllocNewGLTexture(identifier, width, height);
glt->next = gltextures;
gltextures = glt;
strcpy (glt->identifier, identifier);
glt->texnum = GL_AllocNewTexture(width, height);
glt->width = width;
glt->height = height;
glt->bpp = 8; glt->bpp = 8;
glt->flags = flags; glt->flags = flags;
Hash_Add(&gltexturetable, glt->identifier, glt, (bucket_t*)(glt+1));
GL_MTBind(0, GL_TEXTURE_2D, glt->texnum); GL_MTBind(0, GL_TEXTURE_2D, glt->texnum);
GL_Upload8FB (data, width, height, flags); GL_Upload8FB (data, width, height, flags);
@ -2065,20 +2140,10 @@ texid_t GL_LoadTexture8Pal24 (char *identifier, int width, int height, qbyte *da
return glt->texnum; return glt->texnum;
} }
glt = BZ_Malloc(sizeof(*glt)+sizeof(bucket_t)); glt = GL_AllocNewGLTexture(identifier, width, height);
glt->next = gltextures;
gltextures = glt;
strcpy (glt->identifier, identifier);
glt->texnum = GL_AllocNewTexture(width, height);
glt->width = width;
glt->height = height;
glt->bpp = 24; glt->bpp = 24;
glt->flags = flags; glt->flags = flags;
Hash_Add(&gltexturetable, glt->identifier, glt, (bucket_t*)(glt+1));
GL_MTBind(0, GL_TEXTURE_2D, glt->texnum); GL_MTBind(0, GL_TEXTURE_2D, glt->texnum);
GL_Upload8Pal24 (data, palette24, width, height, flags); GL_Upload8Pal24 (data, palette24, width, height, flags);
@ -2097,20 +2162,10 @@ texid_t GL_LoadTexture8Pal32 (char *identifier, int width, int height, qbyte *da
return glt->texnum; return glt->texnum;
} }
glt = BZ_Malloc(sizeof(*glt)+sizeof(bucket_t)); glt = GL_AllocNewGLTexture(identifier, width, height);
glt->next = gltextures;
gltextures = glt;
strcpy (glt->identifier, identifier);
glt->texnum = GL_AllocNewTexture(width, height);
glt->width = width;
glt->height = height;
glt->bpp = 32; glt->bpp = 32;
glt->flags = flags; glt->flags = flags;
Hash_Add(&gltexturetable, glt->identifier, glt, (bucket_t*)(glt+1));
GL_MTBind(0, GL_TEXTURE_2D, glt->texnum); GL_MTBind(0, GL_TEXTURE_2D, glt->texnum);
GL_Upload8Pal32 (data, palette32, width, height, flags); GL_Upload8Pal32 (data, palette32, width, height, flags);
@ -2132,19 +2187,10 @@ texid_t GL_LoadTexture32 (char *identifier, int width, int height, void *data, u
return glt->texnum; return glt->texnum;
} }
glt = BZ_Malloc(sizeof(*glt)+sizeof(bucket_t)); glt = GL_AllocNewGLTexture(identifier, width, height);
glt->next = gltextures;
gltextures = glt;
strcpy (glt->identifier, identifier);
glt->texnum = GL_AllocNewTexture(width, height);
glt->width = width;
glt->height = height;
glt->bpp = 32; glt->bpp = 32;
glt->flags = flags; glt->flags = flags;
Hash_Add(&gltexturetable, glt->identifier, glt, (bucket_t*)(glt+1));
GL_MTBind(0, GL_TEXTURE_2D, glt->texnum); GL_MTBind(0, GL_TEXTURE_2D, glt->texnum);
GL_Upload32 (identifier, data, width, height, flags); GL_Upload32 (identifier, data, width, height, flags);
@ -2166,19 +2212,10 @@ texid_t GL_LoadTexture32_BGRA (char *identifier, int width, int height, unsigned
return glt->texnum; return glt->texnum;
} }
glt = BZ_Malloc(sizeof(*glt)+sizeof(bucket_t)); glt = GL_AllocNewGLTexture(identifier, width, height);
glt->next = gltextures;
gltextures = glt;
strcpy (glt->identifier, identifier);
glt->texnum = GL_AllocNewTexture(width, height);
glt->width = width;
glt->height = height;
glt->bpp = 32; glt->bpp = 32;
glt->flags = flags; glt->flags = flags;
Hash_Add(&gltexturetable, glt->identifier, glt, (bucket_t*)(glt+1));
GL_MTBind(0, GL_TEXTURE_2D, glt->texnum); GL_MTBind(0, GL_TEXTURE_2D, glt->texnum);
GL_Upload32_BGRA (identifier, data, width, height, flags); GL_Upload32_BGRA (identifier, data, width, height, flags);
@ -2212,17 +2249,10 @@ texid_t GL_LoadCompressed(char *name)
if (!file) if (!file)
return r_nulltex; return r_nulltex;
glt = BZ_Malloc(sizeof(*glt)+sizeof(bucket_t)); glt = GL_AllocNewGLTexture(name, 0, 0);
glt->next = gltextures;
gltextures = glt;
strcpy (glt->identifier, name);
glt->texnum = GL_AllocNewTexture(0, 0);
glt->bpp = 32; glt->bpp = 32;
glt->flags = 0; glt->flags = 0;
Hash_Add(&gltexturetable, glt->identifier, glt, (bucket_t*)(glt+1));
GL_MTBind(0, GL_TEXTURE_2D, glt->texnum); GL_MTBind(0, GL_TEXTURE_2D, glt->texnum);
if (!GL_UploadCompressed(file, &glt->width, &glt->height, (unsigned int *)&glt->flags)) if (!GL_UploadCompressed(file, &glt->width, &glt->height, (unsigned int *)&glt->flags))
@ -2247,19 +2277,10 @@ texid_t GL_LoadTexture8Grey (char *identifier, int width, int height, unsigned c
flags |= IF_NOALPHA; flags |= IF_NOALPHA;
glt = BZ_Malloc(sizeof(*glt)+sizeof(bucket_t)); glt = GL_AllocNewGLTexture(identifier, width, height);
glt->next = gltextures;
gltextures = glt;
strcpy (glt->identifier, identifier);
glt->texnum = GL_AllocNewTexture(width, height);
glt->width = width;
glt->height = height;
glt->bpp = 8; glt->bpp = 8;
glt->flags = flags; glt->flags = flags;
Hash_Add(&gltexturetable, glt->identifier, glt, (bucket_t*)(glt+1));
GL_MTBind(0, GL_TEXTURE_2D, glt->texnum); GL_MTBind(0, GL_TEXTURE_2D, glt->texnum);
GL_Upload8Grey (data, width, height, flags); GL_Upload8Grey (data, width, height, flags);
@ -2286,19 +2307,10 @@ texid_t GL_LoadTexture8Bump (char *identifier, int width, int height, unsigned c
TRACE(("dbg: GL_LoadTexture8Bump: new %s\n", identifier)); TRACE(("dbg: GL_LoadTexture8Bump: new %s\n", identifier));
glt = BZ_Malloc(sizeof(*glt)+sizeof(bucket_t)); glt = GL_AllocNewGLTexture(identifier, width, height);
glt->next = gltextures;
gltextures = glt;
strcpy (glt->identifier, identifier);
glt->texnum = GL_AllocNewTexture(width, height);
glt->width = width;
glt->height = height;
glt->bpp = 8; glt->bpp = 8;
glt->flags = flags; glt->flags = flags;
Hash_Add(&gltexturetable, glt->identifier, glt, (bucket_t*)(glt+1));
GL_MTBind(0, GL_TEXTURE_2D, glt->texnum); GL_MTBind(0, GL_TEXTURE_2D, glt->texnum);
GL_UploadBump (data, width, height, flags, bumpscale); GL_UploadBump (data, width, height, flags, bumpscale);

View file

@ -22,7 +22,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
// to touch the vid buffer // to touch the vid buffer
void GLDraw_Init (void); void GLDraw_Init (void);
void GLDraw_ReInit (void);
void GLDraw_DeInit (void); void GLDraw_DeInit (void);
void Surf_DeInit (void); void Surf_DeInit (void);

View file

@ -228,7 +228,7 @@ static struct font_s *curfont;
void Font_Init(void) void Font_Init(void)
{ {
int i; int i;
fontplanes.defaultfont = r_nulltex; TEXASSIGN(fontplanes.defaultfont, r_nulltex);
font_foremesh.indexes = font_indicies; font_foremesh.indexes = font_indicies;
font_foremesh.xyz_array = font_coord; font_foremesh.xyz_array = font_coord;
@ -252,7 +252,7 @@ void Font_Init(void)
for (i = 0; i < FONTPLANES; i++) for (i = 0; i < FONTPLANES; i++)
{ {
fontplanes.texnum[i] = R_AllocNewTexture(PLANEWIDTH, PLANEHEIGHT); TEXASSIGN(fontplanes.texnum[i], R_AllocNewTexture("***fontplane***", PLANEWIDTH, PLANEHEIGHT));
} }
fontplanes.shader = R_RegisterShader("ftefont", fontplanes.shader = R_RegisterShader("ftefont",
@ -293,7 +293,7 @@ static void Font_Flush(void)
return; return;
if (fontplanes.planechanged) if (fontplanes.planechanged)
{ {
R_Upload(fontplanes.texnum[fontplanes.activeplane], NULL, TF_RGBA32, (void*)fontplanes.plane, NULL, PLANEWIDTH, PLANEHEIGHT, IF_NOPICMIP|IF_NOMIPMAP|IF_NOGAMMA); R_Upload(fontplanes.texnum[fontplanes.activeplane], NULL, TF_RGBA32, (void*)fontplanes.plane, NULL, PLANEWIDTH, PLANEHEIGHT, IF_NEAREST|IF_NOPICMIP|IF_NOMIPMAP|IF_NOGAMMA);
fontplanes.planechanged = false; fontplanes.planechanged = false;
} }
@ -306,7 +306,7 @@ static void Font_Flush(void)
BE_DrawMesh_Single(fontplanes.backshader, &font_backmesh, NULL, &fontplanes.backshader->defaulttextures, 0); BE_DrawMesh_Single(fontplanes.backshader, &font_backmesh, NULL, &fontplanes.backshader->defaulttextures, 0);
} }
fontplanes.shader->defaulttextures.base = font_texture; TEXASSIGN(fontplanes.shader->defaulttextures.base, font_texture);
BE_DrawMesh_Single(fontplanes.shader, &font_foremesh, NULL, &fontplanes.shader->defaulttextures, 0); BE_DrawMesh_Single(fontplanes.shader, &font_foremesh, NULL, &fontplanes.shader->defaulttextures, 0);
font_foremesh.numindexes = 0; font_foremesh.numindexes = 0;
font_foremesh.numvertexes = 0; font_foremesh.numvertexes = 0;
@ -319,7 +319,7 @@ static int Font_BeginChar(texid_t tex)
if (font_foremesh.numindexes == FONT_CHAR_BUFFER*6 || memcmp(&font_texture,&tex, sizeof(texid_t))) if (font_foremesh.numindexes == FONT_CHAR_BUFFER*6 || memcmp(&font_texture,&tex, sizeof(texid_t)))
{ {
Font_Flush(); Font_Flush();
font_texture = tex; TEXASSIGNF(font_texture, tex);
} }
fvert = font_foremesh.numvertexes; fvert = font_foremesh.numvertexes;
@ -336,7 +336,7 @@ void Font_Shutdown(void)
int i; int i;
for (i = 0; i < FONTPLANES; i++) for (i = 0; i < FONTPLANES; i++)
fontplanes.texnum[i] = r_nulltex; TEXASSIGN(fontplanes.texnum[i], r_nulltex);
fontplanes.activeplane = 0; fontplanes.activeplane = 0;
fontplanes.oldestchar = NULL; fontplanes.oldestchar = NULL;
fontplanes.newestchar = NULL; fontplanes.newestchar = NULL;

View file

@ -126,9 +126,11 @@ qboolean Mod_LoadHLModel (model_t *mod, void *buffer)
#if defined(HLSERVER) && (defined(__powerpc__) || defined(__ppc__)) #if defined(HLSERVER) && (defined(__powerpc__) || defined(__ppc__))
//this is to let bigfoot know when he comes to port it all... And I'm lazy. //this is to let bigfoot know when he comes to port it all... And I'm lazy.
#warning "-----------------------------------------" #ifdef warningmsg
#warning "FIXME: No byteswapping on halflife models" #pragma warningmsg("-----------------------------------------")
#warning "-----------------------------------------" #pragma warningmsg("FIXME: No byteswapping on halflife models")
#pragma warningmsg("-----------------------------------------")
#endif
#endif #endif
if (header->version != 10) if (header->version != 10)
@ -566,7 +568,7 @@ void R_DrawHLModel(entity_t *curent)
int b, m, v; int b, m, v;
short *skins; short *skins;
int bgroup, cbone, lastbone; int bgroup, cbone, lastbone;
float mat[16]; float mmat[16], mvmat[16];
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
//general model //general model
@ -610,8 +612,8 @@ void R_DrawHLModel(entity_t *curent)
qglColor4f(difuse[0]/255+ambient[0]/255, difuse[1]/255+ambient[1]/255, difuse[2]/255+ambient[2]/255, curent->shaderRGBAf[3]); qglColor4f(difuse[0]/255+ambient[0]/255, difuse[1]/255+ambient[1]/255, difuse[2]/255+ambient[2]/255, curent->shaderRGBAf[3]);
} }
R_RotateForEntity (mat, curent, curent->model); R_RotateForEntity (mmat, mvmat, curent, curent->model);
qglLoadMatrixf(mat); qglLoadMatrixf(mvmat);
cbone = 0; cbone = 0;
for (bgroup = 0; bgroup < FS_COUNT; bgroup++) for (bgroup = 0; bgroup < FS_COUNT; bgroup++)

View file

@ -31,9 +31,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
extern cvar_t r_shadow_bumpscale_basetexture; extern cvar_t r_shadow_bumpscale_basetexture;
extern cvar_t r_replacemodels; extern cvar_t r_replacemodels;
extern cvar_t r_deluxemapping;
extern int gl_bumpmappingpossible;
qboolean isnotmap = true; //used to not warp ammo models. qboolean isnotmap = true; //used to not warp ammo models.
model_t *loadmodel; model_t *loadmodel;
@ -140,7 +138,6 @@ void RMod_BlockTextureColour_f (void)
int i, m; int i, m;
unsigned int colour[8*8]; unsigned int colour[8*8];
unsigned int rgba; unsigned int rgba;
texnums_t tn;
((char *)&rgba)[0] = atoi(Cmd_Argv(2)); ((char *)&rgba)[0] = atoi(Cmd_Argv(2));
((char *)&rgba)[1] = atoi(Cmd_Argv(3)); ((char *)&rgba)[1] = atoi(Cmd_Argv(3));
@ -152,8 +149,6 @@ void RMod_BlockTextureColour_f (void)
s = R_RegisterCustom(Cmd_Argv(2), NULL, NULL); s = R_RegisterCustom(Cmd_Argv(2), NULL, NULL);
if (!s) if (!s)
{ {
memset(&tn, 0, sizeof(tn));
tn.base = R_LoadTexture32(texname, 8, 8, colour, IF_NOALPHA|IF_NOGAMMA);
s = R_RegisterCustom (texname, Shader_DefaultBSPQ1, NULL); s = R_RegisterCustom (texname, Shader_DefaultBSPQ1, NULL);
} }
@ -1183,10 +1178,9 @@ TRACE(("dbg: RMod_LoadTextures: inittexturedescs\n"));
} }
tn.bump = r_nulltex; tn.bump = r_nulltex;
if (gl_bumpmappingpossible && cls.allow_bump) if (r_loadbumpmapping)
{ {
extern cvar_t gl_bump; if (r_loadbumpmapping)
if (gl_bump.ival<2) //set to 2 to have faster loading.
{ {
snprintf(altname, sizeof(altname)-1, "%s_norm", mt->name); snprintf(altname, sizeof(altname)-1, "%s_norm", mt->name);
tn.bump = R_LoadReplacementTexture(altname, loadname, IF_NOGAMMA|IF_SUBDIRONLY); tn.bump = R_LoadReplacementTexture(altname, loadname, IF_NOGAMMA|IF_SUBDIRONLY);
@ -1373,7 +1367,7 @@ void RMod_NowLoadExternal(void)
tn.base = R_LoadReplacementTexture("light1_4", NULL, IF_NOALPHA); //a fallback. :/ tn.base = R_LoadReplacementTexture("light1_4", NULL, IF_NOALPHA); //a fallback. :/
} }
} }
if (!TEXVALID(tn.bump) && *tx->name != '{' && gl_bumpmappingpossible && cls.allow_bump) if (!TEXVALID(tn.bump) && *tx->name != '{' && r_loadbumpmapping)
{ {
tn.bump = R_LoadBumpmapTexture(va("%s_bump", tx->name), loadname); tn.bump = R_LoadBumpmapTexture(va("%s_bump", tx->name), loadname);
if (!TEXVALID(tn.bump)) if (!TEXVALID(tn.bump))
@ -1442,8 +1436,17 @@ void RMod_LoadLighting (lump_t *l)
{ {
qbyte *luxdata = NULL; qbyte *luxdata = NULL;
int mapcomeswith24bitcolouredlighting = false; int mapcomeswith24bitcolouredlighting = false;
extern cvar_t gl_overbright;
loadmodel->engineflags &= ~MDLF_RGBLIGHTING; loadmodel->engineflags &= ~MDLF_RGBLIGHTING;
//q3 maps have built in 4-fold overbright.
//if we're not rendering with that, we need to brighten the lightmaps in order to keep the darker parts the same brightness. we loose the 2 upper bits. those bright areas become uniform and indistinct.
if (loadmodel->fromgame == fg_quake3)
{
gl_overbright.flags |= CVAR_LATCH;
BuildLightMapGammaTable(1, (1<<(2-gl_overbright.ival)));
}
else
//lit file light intensity is made to match the world's light intensity. //lit file light intensity is made to match the world's light intensity.
// if (cls.allow_lightmapgamma) // if (cls.allow_lightmapgamma)
// BuildLightMapGammaTable(0.6, 2); // BuildLightMapGammaTable(0.6, 2);
@ -1460,7 +1463,7 @@ void RMod_LoadLighting (lump_t *l)
if (loadmodel->fromgame == fg_halflife || loadmodel->fromgame == fg_quake2 || loadmodel->fromgame == fg_quake3) if (loadmodel->fromgame == fg_halflife || loadmodel->fromgame == fg_quake2 || loadmodel->fromgame == fg_quake3)
mapcomeswith24bitcolouredlighting = true; mapcomeswith24bitcolouredlighting = true;
if (!mapcomeswith24bitcolouredlighting && r_loadlits.ival && gl_bumpmappingpossible && r_deluxemapping.ival) //fixme: adjust the light intensities. if (!mapcomeswith24bitcolouredlighting && r_loadlits.ival && r_deluxemapping.ival) //fixme: adjust the light intensities.
{ //the map util has a '-scalecos X' parameter. use 0 if you're going to use only just lux. without lux scalecos 0 is hideous. { //the map util has a '-scalecos X' parameter. use 0 if you're going to use only just lux. without lux scalecos 0 is hideous.
char luxname[MAX_QPATH]; char luxname[MAX_QPATH];
if (!luxdata) if (!luxdata)
@ -1601,7 +1604,7 @@ void RMod_LoadLighting (lump_t *l)
loadmodel->engineflags |= MDLF_RGBLIGHTING; loadmodel->engineflags |= MDLF_RGBLIGHTING;
#ifdef RUNTIMELIGHTING #ifdef RUNTIMELIGHTING
else if (r_loadlits.value == 2 && !lightmodel && (!(loadmodel->engineflags & MDLF_RGBLIGHTING) || (!luxdata && gl_bumpmappingpossible))) else if (r_loadlits.value == 2 && !lightmodel && (!(loadmodel->engineflags & MDLF_RGBLIGHTING) || (!luxdata && r_deluxemapping.ival)))
{ {
qbyte *litdata = NULL; qbyte *litdata = NULL;
int i; int i;
@ -1623,7 +1626,7 @@ void RMod_LoadLighting (lump_t *l)
normal++; normal++;
} }
if (gl_bumpmappingpossible) if (r_deluxemapping.ival)
{ {
loadmodel->deluxdata = Hunk_AllocName ( l->filelen*3+8, loadname); loadmodel->deluxdata = Hunk_AllocName ( l->filelen*3+8, loadname);
strcpy(loadmodel->deluxdata, "QLIT"); strcpy(loadmodel->deluxdata, "QLIT");
@ -1846,28 +1849,50 @@ qboolean RMod_LoadSubmodels (lump_t *l)
Mod_LoadEdges Mod_LoadEdges
================= =================
*/ */
qboolean RMod_LoadEdges (lump_t *l) qboolean RMod_LoadEdges (lump_t *l, qboolean lm)
{ {
dedge_t *in;
medge_t *out; medge_t *out;
int i, count; int i, count;
in = (void *)(mod_base + l->fileofs); if (lm)
if (l->filelen % sizeof(*in))
{ {
Con_Printf ("MOD_LoadBmodel: funny lump size in %s\n", loadmodel->name); dledge_t *in = (void *)(mod_base + l->fileofs);
return false; if (l->filelen % sizeof(*in))
{
Con_Printf ("MOD_LoadBmodel: funny lump size in %s\n", loadmodel->name);
return false;
}
count = l->filelen / sizeof(*in);
out = Hunk_AllocName ( (count + 1) * sizeof(*out), loadname);
loadmodel->edges = out;
loadmodel->numedges = count;
for ( i=0 ; i<count ; i++, in++, out++)
{
out->v[0] = LittleLong(in->v[0]);
out->v[1] = LittleLong(in->v[1]);
}
} }
count = l->filelen / sizeof(*in); else
out = Hunk_AllocName ( (count + 1) * sizeof(*out), loadname);
loadmodel->edges = out;
loadmodel->numedges = count;
for ( i=0 ; i<count ; i++, in++, out++)
{ {
out->v[0] = (unsigned short)LittleShort(in->v[0]); dsedge_t *in = (void *)(mod_base + l->fileofs);
out->v[1] = (unsigned short)LittleShort(in->v[1]); if (l->filelen % sizeof(*in))
{
Con_Printf ("MOD_LoadBmodel: funny lump size in %s\n", loadmodel->name);
return false;
}
count = l->filelen / sizeof(*in);
out = Hunk_AllocName ( (count + 1) * sizeof(*out), loadname);
loadmodel->edges = out;
loadmodel->numedges = count;
for ( i=0 ; i<count ; i++, in++, out++)
{
out->v[0] = (unsigned short)LittleShort(in->v[0]);
out->v[1] = (unsigned short)LittleShort(in->v[1]);
}
} }
return true; return true;
@ -1923,7 +1948,10 @@ qboolean RMod_LoadTexinfo (lump_t *l)
miptex = LittleLong (in->miptex); miptex = LittleLong (in->miptex);
out->flags = LittleLong (in->flags); out->flags = LittleLong (in->flags);
out->texture = loadmodel->textures[miptex % loadmodel->numtextures]; if (loadmodel->numtextures)
out->texture = loadmodel->textures[miptex % loadmodel->numtextures];
else
out->texture = NULL;
if (!out->texture) if (!out->texture)
{ {
out->texture = r_notexture_mip; // texture not found out->texture = r_notexture_mip; // texture not found
@ -1996,56 +2024,85 @@ void CalcSurfaceExtents (msurface_t *s);
Mod_LoadFaces Mod_LoadFaces
================= =================
*/ */
qboolean RMod_LoadFaces (lump_t *l) qboolean RMod_LoadFaces (lump_t *l, qboolean lm)
{ {
dface_t *in; dsface_t *ins;
dlface_t *inl;
msurface_t *out; msurface_t *out;
int i, count, surfnum; int count, surfnum;
int planenum, side; int i, planenum, side;
int tn; int tn, lofs;
in = (void *)(mod_base + l->fileofs); if (lm)
if (l->filelen % sizeof(*in))
{ {
Con_Printf (CON_ERROR "MOD_LoadBmodel: funny lump size in %s\n",loadmodel->name); ins = NULL;
return false; inl = (void *)(mod_base + l->fileofs);
if (l->filelen % sizeof(*inl))
{
Con_Printf (CON_ERROR "MOD_LoadBmodel: funny lump size in %s\n",loadmodel->name);
return false;
}
count = l->filelen / sizeof(*inl);
}
else
{
ins = (void *)(mod_base + l->fileofs);
inl = NULL;
if (l->filelen % sizeof(*ins))
{
Con_Printf (CON_ERROR "MOD_LoadBmodel: funny lump size in %s\n",loadmodel->name);
return false;
}
count = l->filelen / sizeof(*ins);
} }
count = l->filelen / sizeof(*in);
out = Hunk_AllocName ( count*sizeof(*out), loadname); out = Hunk_AllocName ( count*sizeof(*out), loadname);
loadmodel->surfaces = out; loadmodel->surfaces = out;
loadmodel->numsurfaces = count; loadmodel->numsurfaces = count;
for ( surfnum=0 ; surfnum<count ; surfnum++, in++, out++) for ( surfnum=0 ; surfnum<count ; surfnum++, out++)
{ {
out->firstedge = LittleLong(in->firstedge); if (lm)
out->numedges = LittleShort(in->numedges); {
planenum = LittleLong(inl->planenum);
side = LittleLong(inl->side);
out->firstedge = LittleLong(inl->firstedge);
out->numedges = LittleLong(inl->numedges);
tn = LittleLong (inl->texinfo);
for (i=0 ; i<MAXLIGHTMAPS ; i++)
out->styles[i] = inl->styles[i];
lofs = LittleLong(inl->lightofs);
inl++;
}
else
{
planenum = LittleShort(ins->planenum);
side = LittleShort(ins->side);
out->firstedge = LittleLong(ins->firstedge);
out->numedges = LittleShort(ins->numedges);
tn = LittleShort (ins->texinfo);
for (i=0 ; i<MAXLIGHTMAPS ; i++)
out->styles[i] = ins->styles[i];
lofs = LittleLong(ins->lightofs);
ins++;
}
out->flags = 0; out->flags = 0;
planenum = LittleShort(in->planenum);
side = LittleShort(in->side);
if (side) if (side)
out->flags |= SURF_PLANEBACK; out->flags |= SURF_PLANEBACK;
out->plane = loadmodel->planes + planenum; out->plane = loadmodel->planes + planenum;
tn = LittleShort (in->texinfo);
if (tn < 0 || tn >= loadmodel->numtexinfo) if (tn < 0 || tn >= loadmodel->numtexinfo)
Host_EndGame("Hey! That map has texinfos out of bounds!\n"); Host_EndGame("Hey! That map has texinfos out of bounds!\n");
out->texinfo = loadmodel->texinfo + tn; out->texinfo = loadmodel->texinfo + tn;
CalcSurfaceExtents (out); CalcSurfaceExtents (out);
if (lofs == -1)
// lighting info
for (i=0 ; i<MAXLIGHTMAPS ; i++)
out->styles[i] = in->styles[i];
i = LittleLong(in->lightofs);
if (i == -1)
out->samples = NULL; out->samples = NULL;
else if ((loadmodel->engineflags & MDLF_RGBLIGHTING) && loadmodel->fromgame != fg_halflife) else if ((loadmodel->engineflags & MDLF_RGBLIGHTING) && loadmodel->fromgame != fg_halflife)
out->samples = loadmodel->lightdata + i*3; out->samples = loadmodel->lightdata + lofs*3;
else else
out->samples = loadmodel->lightdata + i; out->samples = loadmodel->lightdata + lofs;
if (!out->texinfo->texture) if (!out->texinfo->texture)
continue; continue;
@ -2113,45 +2170,87 @@ void RMod_SetParent (mnode_t *node, mnode_t *parent)
Mod_LoadNodes Mod_LoadNodes
================= =================
*/ */
qboolean RMod_LoadNodes (lump_t *l) qboolean RMod_LoadNodes (lump_t *l, qboolean lm)
{ {
int i, j, count, p; int i, j, count, p;
dnode_t *in;
mnode_t *out; mnode_t *out;
in = (void *)(mod_base + l->fileofs); if (lm)
if (l->filelen % sizeof(*in))
{ {
Con_Printf (CON_ERROR "MOD_LoadBmodel: funny lump size in %s\n",loadmodel->name); dlnode_t *in;
return false; in = (void *)(mod_base + l->fileofs);
} if (l->filelen % sizeof(*in))
count = l->filelen / sizeof(*in);
out = Hunk_AllocName ( count*sizeof(*out), loadname);
loadmodel->nodes = out;
loadmodel->numnodes = count;
for ( i=0 ; i<count ; i++, in++, out++)
{
for (j=0 ; j<3 ; j++)
{ {
out->minmaxs[j] = LittleShort (in->mins[j]); Con_Printf (CON_ERROR "MOD_LoadBmodel: funny lump size in %s\n",loadmodel->name);
out->minmaxs[3+j] = LittleShort (in->maxs[j]); return false;
} }
count = l->filelen / sizeof(*in);
p = LittleLong(in->planenum); out = Hunk_AllocName ( count*sizeof(*out), loadname);
out->plane = loadmodel->planes + p;
out->firstsurface = LittleShort (in->firstface); loadmodel->nodes = out;
out->numsurfaces = LittleShort (in->numfaces); loadmodel->numnodes = count;
for (j=0 ; j<2 ; j++) for ( i=0 ; i<count ; i++, in++, out++)
{ {
p = LittleShort (in->children[j]); for (j=0 ; j<3 ; j++)
if (p >= 0) {
out->children[j] = loadmodel->nodes + p; out->minmaxs[j] = LittleShort (in->mins[j]);
else out->minmaxs[3+j] = LittleShort (in->maxs[j]);
out->children[j] = (mnode_t *)(loadmodel->leafs + (-1 - p)); }
p = LittleLong(in->planenum);
out->plane = loadmodel->planes + p;
out->firstsurface = LittleLong (in->firstface);
out->numsurfaces = LittleLong (in->numfaces);
for (j=0 ; j<2 ; j++)
{
p = LittleShort (in->children[j]);
if (p >= 0)
out->children[j] = loadmodel->nodes + p;
else
out->children[j] = (mnode_t *)(loadmodel->leafs + (-1 - p));
}
}
}
else
{
dsnode_t *in;
in = (void *)(mod_base + l->fileofs);
if (l->filelen % sizeof(*in))
{
Con_Printf (CON_ERROR "MOD_LoadBmodel: funny lump size in %s\n",loadmodel->name);
return false;
}
count = l->filelen / sizeof(*in);
out = Hunk_AllocName ( count*sizeof(*out), loadname);
loadmodel->nodes = out;
loadmodel->numnodes = count;
for ( i=0 ; i<count ; i++, in++, out++)
{
for (j=0 ; j<3 ; j++)
{
out->minmaxs[j] = LittleShort (in->mins[j]);
out->minmaxs[3+j] = LittleShort (in->maxs[j]);
}
p = LittleLong(in->planenum);
out->plane = loadmodel->planes + p;
out->firstsurface = LittleShort (in->firstface);
out->numsurfaces = LittleShort (in->numfaces);
for (j=0 ; j<2 ; j++)
{
p = LittleShort (in->children[j]);
if (p >= 0)
out->children[j] = loadmodel->nodes + p;
else
out->children[j] = (mnode_t *)(loadmodel->leafs + (-1 - p));
}
} }
} }
@ -2164,66 +2263,125 @@ qboolean RMod_LoadNodes (lump_t *l)
Mod_LoadLeafs Mod_LoadLeafs
================= =================
*/ */
qboolean RMod_LoadLeafs (lump_t *l) qboolean RMod_LoadLeafs (lump_t *l, qboolean lm)
{ {
dleaf_t *in;
mleaf_t *out; mleaf_t *out;
int i, j, count, p; int i, j, count, p;
// char s[80];
in = (void *)(mod_base + l->fileofs); if (lm)
if (l->filelen % sizeof(*in))
{ {
Con_Printf (CON_ERROR "MOD_LoadBmodel: funny lump size in %s\n",loadmodel->name); dlleaf_t *in;
return false; in = (void *)(mod_base + l->fileofs);
if (l->filelen % sizeof(*in))
{
Con_Printf (CON_ERROR "MOD_LoadBmodel: funny lump size in %s\n",loadmodel->name);
return false;
}
count = l->filelen / sizeof(*in);
out = Hunk_AllocName ( count*sizeof(*out), loadname);
loadmodel->leafs = out;
loadmodel->numleafs = count;
for ( i=0 ; i<count ; i++, in++, out++)
{
for (j=0 ; j<3 ; j++)
{
out->minmaxs[j] = LittleShort (in->mins[j]);
out->minmaxs[3+j] = LittleShort (in->maxs[j]);
}
p = LittleLong(in->contents);
out->contents = p;
out->firstmarksurface = loadmodel->marksurfaces +
LittleLong(in->firstmarksurface);
out->nummarksurfaces = LittleLong(in->nummarksurfaces);
p = LittleLong(in->visofs);
if (p == -1)
out->compressed_vis = NULL;
else
out->compressed_vis = loadmodel->visdata + p;
for (j=0 ; j<4 ; j++)
out->ambient_sound_level[j] = in->ambient_level[j];
#ifndef CLIENTONLY
if (!isDedicated)
#endif
{
// gl underwater warp
if (out->contents != Q1CONTENTS_EMPTY)
{
for (j=0 ; j<out->nummarksurfaces ; j++)
out->firstmarksurface[j]->flags |= SURF_UNDERWATER;
}
if (isnotmap)
{
for (j=0 ; j<out->nummarksurfaces ; j++)
out->firstmarksurface[j]->flags |= SURF_DONTWARP;
}
}
}
} }
count = l->filelen / sizeof(*in); else
out = Hunk_AllocName ( count*sizeof(*out), loadname);
loadmodel->leafs = out;
loadmodel->numleafs = count;
for ( i=0 ; i<count ; i++, in++, out++)
{ {
for (j=0 ; j<3 ; j++) dsleaf_t *in;
in = (void *)(mod_base + l->fileofs);
if (l->filelen % sizeof(*in))
{ {
out->minmaxs[j] = LittleShort (in->mins[j]); Con_Printf (CON_ERROR "MOD_LoadBmodel: funny lump size in %s\n",loadmodel->name);
out->minmaxs[3+j] = LittleShort (in->maxs[j]); return false;
} }
count = l->filelen / sizeof(*in);
out = Hunk_AllocName ( count*sizeof(*out), loadname);
p = LittleLong(in->contents); loadmodel->leafs = out;
out->contents = p; loadmodel->numleafs = count;
out->firstmarksurface = loadmodel->marksurfaces + for ( i=0 ; i<count ; i++, in++, out++)
(unsigned short)LittleShort(in->firstmarksurface);
out->nummarksurfaces = (unsigned short)LittleShort(in->nummarksurfaces);
p = LittleLong(in->visofs);
if (p == -1)
out->compressed_vis = NULL;
else
out->compressed_vis = loadmodel->visdata + p;
for (j=0 ; j<4 ; j++)
out->ambient_sound_level[j] = in->ambient_level[j];
#ifndef CLIENTONLY
if (!isDedicated)
#endif
{ {
// gl underwater warp for (j=0 ; j<3 ; j++)
if (out->contents != Q1CONTENTS_EMPTY)
{ {
for (j=0 ; j<out->nummarksurfaces ; j++) out->minmaxs[j] = LittleShort (in->mins[j]);
out->firstmarksurface[j]->flags |= SURF_UNDERWATER; out->minmaxs[3+j] = LittleShort (in->maxs[j]);
} }
if (isnotmap)
p = LittleLong(in->contents);
out->contents = p;
out->firstmarksurface = loadmodel->marksurfaces +
(unsigned short)LittleShort(in->firstmarksurface);
out->nummarksurfaces = (unsigned short)LittleShort(in->nummarksurfaces);
p = LittleLong(in->visofs);
if (p == -1)
out->compressed_vis = NULL;
else
out->compressed_vis = loadmodel->visdata + p;
for (j=0 ; j<4 ; j++)
out->ambient_sound_level[j] = in->ambient_level[j];
#ifndef CLIENTONLY
if (!isDedicated)
#endif
{ {
for (j=0 ; j<out->nummarksurfaces ; j++) // gl underwater warp
out->firstmarksurface[j]->flags |= SURF_DONTWARP; if (out->contents != Q1CONTENTS_EMPTY)
{
for (j=0 ; j<out->nummarksurfaces ; j++)
out->firstmarksurface[j]->flags |= SURF_UNDERWATER;
}
if (isnotmap)
{
for (j=0 ; j<out->nummarksurfaces ; j++)
out->firstmarksurface[j]->flags |= SURF_DONTWARP;
}
} }
} }
} }
return true; return true;
} }
@ -2309,21 +2467,36 @@ void RMod_LoadCrouchHull(void)
Mod_LoadClipnodes Mod_LoadClipnodes
================= =================
*/ */
qboolean RMod_LoadClipnodes (lump_t *l) qboolean RMod_LoadClipnodes (lump_t *l, qboolean lm)
{ {
dclipnode_t *in; dsclipnode_t *ins;
dsclipnode_t *inl;
mclipnode_t *out; mclipnode_t *out;
int i, count; int i, count;
hull_t *hull; hull_t *hull;
short cn, c;
in = (void *)(mod_base + l->fileofs); if (lm)
if (l->filelen % sizeof(*in))
{ {
Con_Printf (CON_ERROR "MOD_LoadBmodel: funny lump size in %s\n",loadmodel->name); ins = NULL;
return false; inl = (void *)(mod_base + l->fileofs);
if (l->filelen % sizeof(*inl))
{
Con_Printf (CON_ERROR "MOD_LoadBmodel: funny lump size in %s\n",loadmodel->name);
return false;
}
count = l->filelen / sizeof(*inl);
}
else
{
ins = (void *)(mod_base + l->fileofs);
inl = NULL;
if (l->filelen % sizeof(*ins))
{
Con_Printf (CON_ERROR "MOD_LoadBmodel: funny lump size in %s\n",loadmodel->name);
return false;
}
count = l->filelen / sizeof(*ins);
} }
count = l->filelen / sizeof(*in);
out = Hunk_AllocName ( (count+numsuplementryclipnodes)*sizeof(*out), loadname);//space for both out = Hunk_AllocName ( (count+numsuplementryclipnodes)*sizeof(*out), loadname);//space for both
loadmodel->clipnodes = out; loadmodel->clipnodes = out;
@ -2489,33 +2662,22 @@ qboolean RMod_LoadClipnodes (lump_t *l)
hull->available = false; hull->available = false;
} }
if (count > 32767) if (lm)
{ {
/* for (i=0 ; i<count ; i++, out++, inl++)
if the map contains more than 32767 clipnodes, some of them will overflow
typically this will happen in the second hull, and you thus might not notice it.
*/
for (i=0 ; i<count ; i++, out++, in++)
{ {
out->planenum = LittleLong(in->planenum); out->planenum = LittleLong(inl->planenum);
for (c = 0; c < 2; c++) out->children[0] = LittleLong(inl->children[0]);
{ out->children[1] = LittleLong(inl->children[1]);
cn = LittleShort(in->children[c]);
if (cn < -10)
out->children[c] = (unsigned short)cn;
else
out->children[c] = cn;
}
} }
} }
else else
{ {
for (i=0 ; i<count ; i++, out++, in++) for (i=0 ; i<count ; i++, out++, ins++)
{ {
out->planenum = LittleLong(in->planenum); out->planenum = LittleLong(ins->planenum);
out->children[0] = LittleShort(in->children[0]); out->children[0] = LittleShort(ins->children[0]);
out->children[1] = LittleShort(in->children[1]); out->children[1] = LittleShort(ins->children[1]);
} }
} }
@ -2532,14 +2694,14 @@ qboolean RMod_LoadClipnodes (lump_t *l)
hull->available = true; hull->available = true;
} }
in = suplementryclipnodes; ins = suplementryclipnodes;
for (i=0 ; i<numsuplementryclipnodes ; i++, out++, in++) for (i=0 ; i<numsuplementryclipnodes ; i++, out++, ins++)
{ {
out->planenum = LittleLong(in->planenum); out->planenum = LittleLong(ins->planenum);
out->children[0] = LittleShort(in->children[0]); out->children[0] = LittleShort(ins->children[0]);
out->children[0] += out->children[0]>=0?1:0; out->children[0] += out->children[0]>=0?1:0;
out->children[1] = LittleShort(in->children[1]); out->children[1] = LittleShort(ins->children[1]);
out->children[1] += out->children[1]>=0?1:0; out->children[1] += out->children[1]>=0?1:0;
} }
} }
@ -2903,6 +3065,7 @@ qboolean RMod_LoadBrushModel (model_t *mod, void *buffer)
unsigned int chksum; unsigned int chksum;
int start; int start;
qboolean noerrors; qboolean noerrors;
qboolean longm = false;
#if (defined(ODE_STATIC) || defined(ODE_DYNAMIC)) #if (defined(ODE_STATIC) || defined(ODE_DYNAMIC))
qboolean ode = true; qboolean ode = true;
#else #else
@ -2931,6 +3094,12 @@ qboolean RMod_LoadBrushModel (model_t *mod, void *buffer)
loadmodel->fromgame = fg_quake; loadmodel->fromgame = fg_quake;
loadmodel->engineflags |= MDLF_NEEDOVERBRIGHT; loadmodel->engineflags |= MDLF_NEEDOVERBRIGHT;
} }
else if (i == BSPVERSION_LONG)
{
longm = true;
loadmodel->fromgame = fg_quake;
loadmodel->engineflags |= MDLF_NEEDOVERBRIGHT;
}
else if (i == BSPVERSIONHL) //halflife support else if (i == BSPVERSIONHL) //halflife support
loadmodel->fromgame = fg_halflife; loadmodel->fromgame = fg_halflife;
else else
@ -2998,7 +3167,7 @@ qboolean RMod_LoadBrushModel (model_t *mod, void *buffer)
if (!isDedicated || ode) if (!isDedicated || ode)
{ {
noerrors = noerrors && RMod_LoadVertexes (&header->lumps[LUMP_VERTEXES]); noerrors = noerrors && RMod_LoadVertexes (&header->lumps[LUMP_VERTEXES]);
noerrors = noerrors && RMod_LoadEdges (&header->lumps[LUMP_EDGES]); noerrors = noerrors && RMod_LoadEdges (&header->lumps[LUMP_EDGES], longm);
noerrors = noerrors && RMod_LoadSurfedges (&header->lumps[LUMP_SURFEDGES]); noerrors = noerrors && RMod_LoadSurfedges (&header->lumps[LUMP_SURFEDGES]);
} }
if (!isDedicated) if (!isDedicated)
@ -3014,15 +3183,15 @@ qboolean RMod_LoadBrushModel (model_t *mod, void *buffer)
if (!isDedicated || ode) if (!isDedicated || ode)
{ {
noerrors = noerrors && RMod_LoadTexinfo (&header->lumps[LUMP_TEXINFO]); noerrors = noerrors && RMod_LoadTexinfo (&header->lumps[LUMP_TEXINFO]);
noerrors = noerrors && RMod_LoadFaces (&header->lumps[LUMP_FACES]); noerrors = noerrors && RMod_LoadFaces (&header->lumps[LUMP_FACES], longm);
} }
if (!isDedicated) if (!isDedicated)
noerrors = noerrors && RMod_LoadMarksurfaces (&header->lumps[LUMP_MARKSURFACES]); noerrors = noerrors && RMod_LoadMarksurfaces (&header->lumps[LUMP_MARKSURFACES]);
if (noerrors) if (noerrors)
RMod_LoadVisibility (&header->lumps[LUMP_VISIBILITY]); RMod_LoadVisibility (&header->lumps[LUMP_VISIBILITY]);
noerrors = noerrors && RMod_LoadLeafs (&header->lumps[LUMP_LEAFS]); noerrors = noerrors && RMod_LoadLeafs (&header->lumps[LUMP_LEAFS], longm);
noerrors = noerrors && RMod_LoadNodes (&header->lumps[LUMP_NODES]); noerrors = noerrors && RMod_LoadNodes (&header->lumps[LUMP_NODES], longm);
noerrors = noerrors && RMod_LoadClipnodes (&header->lumps[LUMP_CLIPNODES]); noerrors = noerrors && RMod_LoadClipnodes (&header->lumps[LUMP_CLIPNODES], longm);
if (noerrors) if (noerrors)
{ {
RMod_LoadEntities (&header->lumps[LUMP_ENTITIES]); RMod_LoadEntities (&header->lumps[LUMP_ENTITIES]);
@ -3179,7 +3348,7 @@ void RMod_FloodFillSkin( qbyte *skin, int skinwidth, int skinheight )
filledcolor = 0; filledcolor = 0;
// attempt to find opaque black // attempt to find opaque black
for (i = 0; i < 256; ++i) for (i = 0; i < 256; ++i)
if (d_8to24rgbtable[i] == (255 << 0)) // alpha 1.0 if (d_8to24rgbtable[i] == (255 << 0)) // rgb 0.0, alpha 1.0
{ {
filledcolor = i; filledcolor = i;
break; break;
@ -3290,11 +3459,11 @@ void * RMod_LoadSpriteFrame (void * pin, mspriteframe_t **ppframe, int framenum,
pspriteframe->shader = R_RegisterShader(name, pspriteframe->shader = R_RegisterShader(name,
"{\n" "{\n"
"{\n" "{\n"
"map $diffuse\n" "map $diffuse\n"
"alphafunc ge128\n" "alphafunc ge128\n"
"depthwrite\n" "depthwrite\n"
"rgbgen entity\n" "rgbgen vertex\n"
"alphagen entity\n" "alphagen vertex\n"
"}\n" "}\n"
"}\n" "}\n"
); );

View file

@ -127,20 +127,41 @@ m*_t structures are in-memory
// entity effects // entity effects
#define EF_BRIGHTFIELD 1 #define EF_BRIGHTFIELD (1<<0)
#define EF_MUZZLEFLASH 2 #define EF_MUZZLEFLASH (1<<1)
#define EF_BRIGHTLIGHT 4 #define EF_BRIGHTLIGHT (1<<2)
#define EF_DIMLIGHT 8 #define EF_DIMLIGHT (1<<3)
#define QWEF_FLAG1 16 //only applies to player entities #define QWEF_FLAG1 (1<<4) //only applies to qw player entities
#define NQEF_NODRAW 16 //so packet entities are free to get this instead #define NQEF_NODRAW (1<<4) //so packet entities are free to get this instead
#define QWEF_FLAG2 32 //only applies to player entities #define QWEF_FLAG2 (1<<5) //only applies to qw player entities
#define NQEF_ADDITIVE 32 //so packet entities are free to get this instead #define NQEF_ADDITIVE (1<<5) //so packet entities are free to get this instead
#define EF_BLUE 64 #define EF_BLUE (1<<6)
#define EF_RED 128 #define EF_RED (1<<7)
#define H2EF_NODRAW (1<<7) //this is going to get complicated... emulated server side.
#define H2EF_NODRAW 128 //this is going to get complicated... emulated server side. #define _DPEF_NOGUNBOB (1<<8) //viewmodel attachment does not bob
#define EF_FULLBRIGHT (1<<9) //abslight=1
#define EF_NODEPTHTEST 8192 //shows through walls. :( #define _DPEF_FLAME (1<<10) //'onfire'
#define _DPEF_STARDUST (1<<11) //'showering sparks'
#define DPEF_NOSHADOW (1<<12) //doesn't cast a shadow
#define EF_NODEPTHTEST (1<<13) //shows through walls.
#define _DPEF_SELECTABLE (1<<14) //highlights when prydoncursored
#define _DPEF_DOUBLESIDED (1<<15) //disables culling
#define _DPEF_NOSELFSHADOW (1<<16) //doesn't cast shadows on any noselfshadow entities.
#define EF_UNUSED17 (1<<17)
#define EF_UNUSED18 (1<<18)
#define EF_UNUSED19 (1<<19)
#define _DPEF_RESTARTANIM_BIT (1<<20) //exact semantics seems odd
#define _DPEF_TELEPORT_BIT (1<<21) //disable lerping while set
#define DPEF_LOWPRECISION (1<<22) //part of the protocol/server, not the client itself.
#define _DPEF_NOMODELFLAGS (1<<23)
#define EF_MF_ROCKET (1<<24)
#define EF_MF_GRENADE (1<<25)
#define EF_MF_GIB (1<<26)
#define EF_MF_ROTATE (1<<27)
#define EF_MF_TRACER (1<<28)
#define EF_MF_ZOMGIB (1u<<29)
#define EF_MF_TRACER2 (1u<<30)
#define EF_MF_TRACER3 (1u<<31)
/* /*
============================================================================== ==============================================================================
@ -764,32 +785,32 @@ typedef struct {
typedef enum {mod_brush, mod_sprite, mod_alias, mod_dummy, mod_halflife, mod_heightmap} modtype_t; typedef enum {mod_brush, mod_sprite, mod_alias, mod_dummy, mod_halflife, mod_heightmap} modtype_t;
typedef enum {fg_quake, fg_quake2, fg_quake3, fg_halflife, fg_new, fg_doom, fg_doom3} fromgame_t; //useful when we have very similar model types. (eg quake/halflife bsps) typedef enum {fg_quake, fg_quake2, fg_quake3, fg_halflife, fg_new, fg_doom, fg_doom3} fromgame_t; //useful when we have very similar model types. (eg quake/halflife bsps)
#define EF_ROCKET 1 // leave a trail #define MF_ROCKET 1 // leave a trail
#define EF_GRENADE 2 // leave a trail #define MF_GRENADE 2 // leave a trail
#define EF_GIB 4 // leave a trail #define MF_GIB 4 // leave a trail
#define EF_ROTATE 8 // rotate (bonus items) #define MF_ROTATE 8 // rotate (bonus items)
#define EF_TRACER 16 // green split trail #define MF_TRACER 16 // green split trail
#define EF_ZOMGIB 32 // small blood trail #define MF_ZOMGIB 32 // small blood trail
#define EF_TRACER2 64 // orange split trail + rotate #define MF_TRACER2 64 // orange split trail + rotate
#define EF_TRACER3 128 // purple trail #define MF_TRACER3 128 // purple trail
//hexen2 support. //hexen2 support.
#define EFH2_FIREBALL 256 // Yellow transparent trail in all directions #define MFH2_FIREBALL 256 // Yellow transparent trail in all directions
#define EFH2_ICE 512 // Blue-white transparent trail, with gravity #define MFH2_ICE 512 // Blue-white transparent trail, with gravity
#define EFH2_MIP_MAP 1024 // This model has mip-maps #define MFH2_MIP_MAP 1024 // This model has mip-maps
#define EFH2_SPIT 2048 // Black transparent trail with negative light #define MFH2_SPIT 2048 // Black transparent trail with negative light
#define EFH2_TRANSPARENT 4096 // Transparent sprite #define MFH2_TRANSPARENT 4096 // Transparent sprite
#define EFH2_SPELL 8192 // Vertical spray of particles #define MFH2_SPELL 8192 // Vertical spray of particles
#define EFH2_HOLEY 16384 // Solid model with color 0 #define MFH2_HOLEY 16384 // Solid model with color 0
#define EFH2_SPECIAL_TRANS 32768 // Translucency through the particle table #define MFH2_SPECIAL_TRANS 32768 // Translucency through the particle table
#define EFH2_FACE_VIEW 65536 // Poly Model always faces you #define MFH2_FACE_VIEW 65536 // Poly Model always faces you
#define EFH2_VORP_MISSILE 131072 // leave a trail at top and bottom of model #define MFH2_VORP_MISSILE 131072 // leave a trail at top and bottom of model
#define EFH2_SET_STAFF 262144 // slowly move up and left/right #define MFH2_SET_STAFF 262144 // slowly move up and left/right
#define EFH2_MAGICMISSILE 524288 // a trickle of blue/white particles with gravity #define MFH2_MAGICMISSILE 524288 // a trickle of blue/white particles with gravity
#define EFH2_BONESHARD 1048576 // a trickle of brown particles with gravity #define MFH2_BONESHARD 1048576 // a trickle of brown particles with gravity
#define EFH2_SCARAB 2097152 // white transparent particles with little gravity #define MFH2_SCARAB 2097152 // white transparent particles with little gravity
#define EFH2_ACIDBALL 4194304 // Green drippy acid shit #define MFH2_ACIDBALL 4194304 // Green drippy acid shit
#define EFH2_BLOODSHOT 8388608 // Blood rain shot trail #define MFH2_BLOODSHOT 8388608 // Blood rain shot trail
typedef union { typedef union {
struct { struct {
@ -950,7 +971,7 @@ qboolean Heightmap_Edit(model_t *mod, int action, float *pos, float radius, floa
void CM_InitBoxHull (void); void CM_InitBoxHull (void);
#ifdef __cplusplus #ifdef __cplusplus
//#pragma message (" c++ stinks") //#pragma warningmsg (" c++ stinks")
#else #else
void CM_Init(void); void CM_Init(void);

View file

@ -20,12 +20,12 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
// gl_ngraph.c // gl_ngraph.c
#include "quakedef.h" #include "quakedef.h"
#ifdef GLQUAKE #include "shader.h"
#include "glquake.h"
extern qbyte *draw_chars; // 8*8 graphic characters extern qbyte *draw_chars; // 8*8 graphic characters
texid_t netgraphtexture; // netgraph texture static texid_t netgraphtexture; // netgraph texture
static shader_t *netgraphshader;
#define NET_GRAPHHEIGHT 32 #define NET_GRAPHHEIGHT 32
@ -61,13 +61,16 @@ static void R_LineGraph (int x, int h)
ngraph_texels[NET_GRAPHHEIGHT - i - 1][x] = (qbyte)0xff; ngraph_texels[NET_GRAPHHEIGHT - i - 1][x] = (qbyte)0xff;
} }
void Draw_CharToNetGraph (int x, int y, int num) static void Draw_CharToNetGraph (int x, int y, int num)
{ {
int row, col; int row, col;
qbyte *source; qbyte *source;
int drawline; int drawline;
int nx; int nx;
if (!draw_chars)
return;
row = num>>4; row = num>>4;
col = num&15; col = num&15;
source = draw_chars + (row<<10) + (col<<3); source = draw_chars + (row<<10) + (col<<3);
@ -118,30 +121,9 @@ void GLR_NetGraph (void)
Draw_FunString(8, y, st); Draw_FunString(8, y, st);
y += 8; y += 8;
#ifndef ANDROID R_Upload(netgraphtexture, "***netgraph***", TF_RGBA32, ngraph_pixels, NULL, NET_TIMINGS, NET_GRAPHHEIGHT, IF_NOMIPMAP|IF_NOPICMIP);
GL_MTBind(0, GL_TEXTURE_2D, netgraphtexture); x=8;
R2D_Image(x, y, NET_TIMINGS, NET_GRAPHHEIGHT, 0, 0, 1, 1, netgraphshader);
qglTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA,
NET_TIMINGS, NET_GRAPHHEIGHT, 0, GL_RGBA,
GL_UNSIGNED_BYTE, ngraph_pixels);
GL_TexEnv(GL_MODULATE);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
x = 8;
qglColor3f (1,1,1);
qglBegin (GL_QUADS);
qglTexCoord2f (0, 0);
qglVertex2f (x, y);
qglTexCoord2f (1, 0);
qglVertex2f (x+NET_TIMINGS, y);
qglTexCoord2f (1, 1);
qglVertex2f (x+NET_TIMINGS, y+NET_GRAPHHEIGHT);
qglTexCoord2f (0, 1);
qglVertex2f (x, y+NET_GRAPHHEIGHT);
qglEnd ();
#endif
} }
void GLR_FrameTimeGraph (int frametime) void GLR_FrameTimeGraph (int frametime)
@ -180,30 +162,21 @@ void GLR_FrameTimeGraph (int frametime)
Draw_FunString(8, y, st); Draw_FunString(8, y, st);
y += 8; y += 8;
#ifndef ANDROID R_Upload(netgraphtexture, "***netgraph***", TF_RGBA32, ngraph_pixels, NULL, NET_TIMINGS, NET_GRAPHHEIGHT, IF_NOMIPMAP|IF_NOPICMIP);
GL_MTBind(0, GL_TEXTURE_2D, netgraphtexture); x=8;
R2D_Image(x, y, NET_TIMINGS, NET_GRAPHHEIGHT, 0, 0, 1, 1, netgraphshader);
qglTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA,
NET_TIMINGS, NET_GRAPHHEIGHT, 0, GL_RGBA,
GL_UNSIGNED_BYTE, ngraph_pixels);
GL_TexEnv(GL_MODULATE);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
x = 8;
qglColor3f (1,1,1);
qglBegin (GL_QUADS);
qglTexCoord2f (0, 0);
qglVertex2f (x, y);
qglTexCoord2f (1, 0);
qglVertex2f (x+NET_TIMINGS, y);
qglTexCoord2f (1, 1);
qglVertex2f (x+NET_TIMINGS, y+NET_GRAPHHEIGHT);
qglTexCoord2f (0, 1);
qglVertex2f (x, y+NET_GRAPHHEIGHT);
qglEnd ();
#endif
} }
#endif void R_NetgraphInit(void)
{
TEXASSIGN(netgraphtexture, GL_AllocNewTexture("***netgraph***", NET_TIMINGS, NET_GRAPHHEIGHT));
netgraphshader = R_RegisterShader("netgraph",
"{\n"
"{\n"
"map $diffuse\n"
"blendfunc blend\n"
"}\n"
"}\n"
);
netgraphshader->defaulttextures.base = netgraphtexture;
}

View file

@ -24,6 +24,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "glquake.h" #include "glquake.h"
#include "shader.h" #include "shader.h"
extern cvar_t r_shadow_realtime_world, r_shadow_realtime_world_lightmaps;
int r_dlightframecount; int r_dlightframecount;
int d_lightstylevalue[256]; // 8.8 fraction of base light value int d_lightstylevalue[256]; // 8.8 fraction of base light value
@ -97,9 +99,9 @@ void AddLightBlend (float r, float g, float b, float a2)
//Con_Printf("AddLightBlend(): %4.2f %4.2f %4.2f %4.6f\n", v_blend[0], v_blend[1], v_blend[2], v_blend[3]); //Con_Printf("AddLightBlend(): %4.2f %4.2f %4.2f %4.6f\n", v_blend[0], v_blend[1], v_blend[2], v_blend[3]);
} }
float bubble_sintable[17], bubble_costable[17]; static float bubble_sintable[17], bubble_costable[17];
void R_InitBubble(void) static void R_InitBubble(void)
{ {
float a; float a;
int i; int i;
@ -157,7 +159,7 @@ void R_InitFlashblends(void)
flashblend_shader = R_RegisterShader("flashblend", flashblend_shader = R_RegisterShader("flashblend",
"{\n" "{\n"
"{\n" "{\n"
"map $whitetexture\n" "map %whiteimage\n"
"blendfunc gl_one gl_one\n" "blendfunc gl_one gl_one\n"
"rgbgen vertex\n" "rgbgen vertex\n"
"alphagen vertex\n" "alphagen vertex\n"
@ -165,6 +167,8 @@ void R_InitFlashblends(void)
"}\n" "}\n"
); );
lpplight_shader = NULL; lpplight_shader = NULL;
R_InitBubble();
} }
static qboolean R_BuildDlightMesh(dlight_t *light, float radscale, qboolean expand) static qboolean R_BuildDlightMesh(dlight_t *light, float radscale, qboolean expand)
@ -205,7 +209,7 @@ static qboolean R_BuildDlightMesh(dlight_t *light, float radscale, qboolean expa
flashblend_colours[0][3] = 1; flashblend_colours[0][3] = 1;
VectorCopy(light->origin, flashblend_vcoords[0]); VectorCopy(light->origin, flashblend_vcoords[0]);
for (i=16 ; i>0 ; i--) for (i=FLASHBLEND_VERTS ; i>0 ; i--)
{ {
for (j=0 ; j<3 ; j++) for (j=0 ; j<3 ; j++)
flashblend_vcoords[i][j] = light->origin[j] + (vright[j]*(*bub_cos) + flashblend_vcoords[i][j] = light->origin[j] + (vright[j]*(*bub_cos) +
@ -220,7 +224,7 @@ static qboolean R_BuildDlightMesh(dlight_t *light, float radscale, qboolean expa
vec3_t diff; vec3_t diff;
VectorSubtract(r_origin, light->origin, diff); VectorSubtract(r_origin, light->origin, diff);
VectorNormalize(diff); VectorNormalize(diff);
for (i=0 ; i<=16 ; i++) for (i=0 ; i<=FLASHBLEND_VERTS ; i++)
VectorMA(flashblend_vcoords[i], rad, diff, flashblend_vcoords[i]); VectorMA(flashblend_vcoords[i], rad, diff, flashblend_vcoords[i]);
} }
return true; return true;
@ -231,7 +235,7 @@ static qboolean R_BuildDlightMesh(dlight_t *light, float radscale, qboolean expa
R_RenderDlights R_RenderDlights
============= =============
*/ */
void GLR_RenderDlights (void) void R_RenderDlights (void)
{ {
int i; int i;
dlight_t *l; dlight_t *l;
@ -376,6 +380,12 @@ void R_PushDlights (void)
r_dlightframecount = r_framecount + 1; // because the count hasn't r_dlightframecount = r_framecount + 1; // because the count hasn't
// advanced yet for this frame // advanced yet for this frame
#ifdef RTLIGHTS
/*if we're doing full rtlighting only, then don't bother calculating old-style dlights as they won't be visible anyway*/
if (r_shadow_realtime_world.value && r_shadow_realtime_world_lightmaps.value < 0.1)
return;
#endif
if (!r_dynamic.ival || !cl.worldmodel) if (!r_dynamic.ival || !cl.worldmodel)
return; return;
@ -509,9 +519,14 @@ void GLQ3_LightGrid(model_t *mod, vec3_t point, vec3_t res_diffuse, vec3_t res_a
direction_uv[j] = anglemod ( direction_uv[j] ); direction_uv[j] = anglemod ( direction_uv[j] );
} }
VectorScale(ambient, 4, ambient);
VectorScale(diffuse, 4, diffuse);
/*ambient is the min level*/
/*diffuse is the max level*/
VectorCopy(ambient, res_ambient); VectorCopy(ambient, res_ambient);
if (res_diffuse) if (res_diffuse)
VectorCopy(diffuse, res_diffuse); VectorAdd(diffuse, ambient, res_diffuse);
if (res_dir) if (res_dir)
{ {
vec3_t right, left; vec3_t right, left;

View file

@ -107,93 +107,27 @@ texid_t sceneblur_texture;
texid_t scenepp_texture_warp; texid_t scenepp_texture_warp;
texid_t scenepp_texture_edge; texid_t scenepp_texture_edge;
int scenepp_mt_program; texid_t scenepp_postproc_cube;
int scenepp_mt_parm_texture0i;
int scenepp_mt_parm_colorf;
int scenepp_mt_parm_inverti;
texid_t scenepp_fisheye_texture;
int scenepp_fisheye_program;
int scenepp_fisheye_parm_fov;
int scenepp_panorama_program;
int scenepp_panorama_parm_fov;
// KrimZon - init post processing - called in GL_CheckExtensions, when they're called // KrimZon - init post processing - called in GL_CheckExtensions, when they're called
// I put it here so that only this file need be changed when messing with the post // I put it here so that only this file need be changed when messing with the post
// processing shaders // processing shaders
void GL_InitSceneProcessingShaders_WaterWarp (void) void GL_InitSceneProcessingShaders_WaterWarp (void)
{ {
/*
inputs:
texcoords: edge points
coords: vertex coords (duh)
time
ampscale (cvar = r_waterwarp)
use ifs instead of an edge map?
*/
if (gl_config.arb_shader_objects) if (gl_config.arb_shader_objects)
{ {
scenepp_waterwarp = R_RegisterShader("waterwarp", scenepp_waterwarp = R_RegisterShader("waterwarp",
"{\n" "{\n"
"glslprogram\n" "program underwaterwarp\n"
"{\n" "{\n"
"#ifdef VERTEX_SHADER\n" "map $currentrender\n"
"\ "}\n"
attribute vec2 v_texcoord;\ "{\n"
varying vec2 v_stc;\ "map $upperoverlay\n"
varying vec2 v_warp;\ "}\n"
varying vec2 v_edge;\ "{\n"
uniform float e_time;\ "map $loweroverlay\n"
void main (void)\ "}\n"
{\
gl_Position = ftetransform();\
v_stc = (1.0+(gl_Position.xy / gl_Position.w))/2.0;\
v_warp.s = e_time * 0.25 + v_texcoord.s;\
v_warp.t = e_time * 0.25 + v_texcoord.t;\
v_edge = v_texcoord.xy;\
}\
\n"
"#endif\n"
"#ifdef FRAGMENT_SHADER\n"
"\
varying vec2 v_stc;\
varying vec2 v_warp;\
varying vec2 v_edge;\
uniform sampler2D s_t0;\
uniform sampler2D s_t1;\
uniform sampler2D s_t2;\
uniform float ampscale;\
uniform vec3 rendertexturescale;\
void main (void)\
{\
float amptemp;\
vec3 edge;\
edge = texture2D( s_t2, v_edge ).rgb;\
amptemp = (0.010 / 0.625) * ampscale * edge.x;\
vec3 offset;\
offset = texture2D( s_t1, v_warp ).rgb;\
offset.x = (offset.x - 0.5) * 2.0;\
offset.y = (offset.y - 0.5) * 2.0;\
vec2 temp;\
temp.x = v_stc.x + offset.x * amptemp;\
temp.y = v_stc.y + offset.y * amptemp;\
gl_FragColor = texture2D( s_t0, temp*rendertexturescale.st );\
}\
\n"
"#endif\n"
"}\n"
"param cvarf r_waterwarp ampscale\n"
"param rendertexturescale rendertexturescale\n"
"{\n"
"map $currentrender\n"
"}\n"
"{\n"
"map $upperoverlay\n"
"}\n"
"{\n"
"map $loweroverlay\n"
"}\n"
"}\n" "}\n"
); );
scenepp_waterwarp->defaulttextures.upperoverlay = scenepp_texture_warp; scenepp_waterwarp->defaulttextures.upperoverlay = scenepp_texture_warp;
@ -201,76 +135,11 @@ void GL_InitSceneProcessingShaders_WaterWarp (void)
} }
} }
void GL_InitFisheyeFov(void)
{
char *vshader = "\
varying vec2 texcoord;\
void main(void)\
{\
texcoord = gl_MultiTexCoord0.xy;\
gl_Position = ftetransform();\
}";
char *fisheyefshader = "\
uniform samplerCube source;\
varying vec2 texcoord;\
uniform float fov;\
void main(void)\
{\
vec3 tc; \
vec2 d; \
vec2 ang; \
d = texcoord; \
ang.x = sqrt(d.x*d.x+d.y*d.y)*fov; \
ang.y = -atan(d.y, d.x); \
tc.x = sin(ang.x) * cos(ang.y); \
tc.y = sin(ang.x) * sin(ang.y); \
tc.z = cos(ang.x); \
gl_FragColor = textureCube(source, tc);\
}";
char *panoramafshader = "\
uniform samplerCube source;\
varying vec2 texcoord;\
uniform float fov;\
void main(void)\
{\
vec3 tc; \
float ang; \
ang = texcoord.x*fov; \
tc.x = sin(ang); \
tc.y = -texcoord.y; \
tc.z = cos(ang); \
gl_FragColor = textureCube(source, tc);\
}";
if (gl_config.gles)
return;
scenepp_fisheye_program = GLSlang_CreateProgram("fisheye", "#version 110\n", NULL, vshader, fisheyefshader);
if (scenepp_fisheye_program)
{
GLSlang_UseProgram(scenepp_fisheye_program);
GLSlang_SetUniform1i(GLSlang_GetUniformLocation(scenepp_fisheye_program, "source"), 0);
scenepp_fisheye_parm_fov = GLSlang_GetUniformLocation(scenepp_fisheye_program, "fov");
GLSlang_UseProgram(0);
}
scenepp_panorama_program = GLSlang_CreateProgram("panorama", "#version 110\n", NULL, vshader, panoramafshader);
if (scenepp_panorama_program)
{
GLSlang_UseProgram(scenepp_panorama_program);
GLSlang_SetUniform1i(GLSlang_GetUniformLocation(scenepp_panorama_program, "source"), 0);
scenepp_panorama_parm_fov = GLSlang_GetUniformLocation(scenepp_panorama_program, "fov");
GLSlang_UseProgram(0);
}
}
void GL_InitSceneProcessingShaders (void) void GL_InitSceneProcessingShaders (void)
{ {
if (gl_config.arb_shader_objects) if (gl_config.arb_shader_objects)
{ {
GL_InitSceneProcessingShaders_WaterWarp(); GL_InitSceneProcessingShaders_WaterWarp();
GL_InitFisheyeFov();
} }
} }
@ -283,15 +152,15 @@ void GL_SetupSceneProcessingTextures (void)
unsigned char pp_warp_tex[PP_WARP_TEX_SIZE*PP_WARP_TEX_SIZE*3]; unsigned char pp_warp_tex[PP_WARP_TEX_SIZE*PP_WARP_TEX_SIZE*3];
unsigned char pp_edge_tex[PP_AMP_TEX_SIZE*PP_AMP_TEX_SIZE*3]; unsigned char pp_edge_tex[PP_AMP_TEX_SIZE*PP_AMP_TEX_SIZE*3];
scenepp_fisheye_texture = r_nulltex; scenepp_postproc_cube = r_nulltex;
sceneblur_texture = GL_AllocNewTexture(0, 0); TEXASSIGN(sceneblur_texture, GL_AllocNewTexture("***postprocess_blur***", 0, 0));
if (!gl_config.arb_shader_objects) if (!gl_config.arb_shader_objects)
return; return;
scenepp_texture_warp = GL_AllocNewTexture(0, 0); TEXASSIGN(scenepp_texture_warp, GL_AllocNewTexture("***postprocess_warp***", 0, 0));
scenepp_texture_edge = GL_AllocNewTexture(0, 0); TEXASSIGN(scenepp_texture_edge, GL_AllocNewTexture("***postprocess_edge***", 0, 0));
// init warp texture - this specifies offset in // init warp texture - this specifies offset in
for (y=0; y<PP_WARP_TEX_SIZE; y++) for (y=0; y<PP_WARP_TEX_SIZE; y++)
@ -361,10 +230,8 @@ void GL_SetupSceneProcessingTextures (void)
qglTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, PP_WARP_TEX_SIZE, PP_WARP_TEX_SIZE, 0, GL_RGB, GL_UNSIGNED_BYTE, pp_edge_tex); qglTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, PP_WARP_TEX_SIZE, PP_WARP_TEX_SIZE, 0, GL_RGB, GL_UNSIGNED_BYTE, pp_edge_tex);
} }
void R_RotateForEntity (float *modelview, const entity_t *e, const model_t *mod) void R_RotateForEntity (float *m, float *modelview, const entity_t *e, const model_t *mod)
{ {
float m[16];
m[0] = e->axis[0][0]; m[0] = e->axis[0][0];
m[1] = e->axis[0][1]; m[1] = e->axis[0][1];
m[2] = e->axis[0][2]; m[2] = e->axis[0][2];
@ -594,6 +461,12 @@ void R_RenderScene (void)
RQ_BeginFrame(); RQ_BeginFrame();
if (!(r_refdef.flags & Q2RDF_NOWORLDMODEL))
{
TRACE(("dbg: calling R_DrawParticles\n"));
P_DrawParticles ();
}
if (!(r_refdef.flags & Q2RDF_NOWORLDMODEL)) if (!(r_refdef.flags & Q2RDF_NOWORLDMODEL))
{ {
TRACE(("dbg: calling R_DrawWorld\n")); TRACE(("dbg: calling R_DrawWorld\n"));
@ -607,13 +480,8 @@ void R_RenderScene (void)
// R_DrawDecals(); // R_DrawDecals();
TRACE(("dbg: calling R_RenderDlights\n")); TRACE(("dbg: calling R_RenderDlights\n"));
GLR_RenderDlights (); R_RenderDlights ();
if (!(r_refdef.flags & Q2RDF_NOWORLDMODEL))
{
TRACE(("dbg: calling R_DrawParticles\n"));
P_DrawParticles ();
}
RQ_RenderBatchClear(); RQ_RenderBatchClear();
cl_numvisedicts = tmpvisents; cl_numvisedicts = tmpvisents;
@ -867,8 +735,8 @@ void GLR_DrawPortal(batch_t *batch, batch_t **blist)
GL_CullFace(0); GL_CullFace(0);
#ifdef _MSC_VER #ifdef warningmsg
#pragma message("warning: there's a bug with rtlights in portals, culling is broken or something. May also be loading the wrong matrix") #pragma warningmsg("warning: there's a bug with rtlights in portals, culling is broken or something. May also be loading the wrong matrix")
#endif #endif
} }
@ -956,12 +824,10 @@ static void R_RenderMotionBlur(void)
{ {
int vwidth = 1, vheight = 1; int vwidth = 1, vheight = 1;
float vs, vt, cs, ct; float vs, vt, cs, ct;
#ifdef _MSC_VER #ifdef warningmsg
#pragma message("backend fixme") #pragma warningmsg("backend fixme")
#endif #endif
#ifndef ANDROID #ifndef ANDROID
Con_Printf("motionblur is not updated for the backend\n");
if (gl_config.arb_texture_non_power_of_two) if (gl_config.arb_texture_non_power_of_two)
{ //we can use any size, supposedly { //we can use any size, supposedly
vwidth = vid.pixelwidth; vwidth = vid.pixelwidth;
@ -1027,9 +893,8 @@ static void R_RenderMotionBlur(void)
PPL_RevertToKnownState(); PPL_RevertToKnownState();
} }
#ifdef FISH
/*FIXME: we could use geometry shaders to draw to all 6 faces at once*/ /*FIXME: we could use geometry shaders to draw to all 6 faces at once*/
qboolean R_RenderScene_Fish(void) qboolean R_RenderScene_Cubemap(void)
{ {
int cmapsize = 512; int cmapsize = 512;
int i; int i;
@ -1037,22 +902,67 @@ qboolean R_RenderScene_Fish(void)
{ {0, -90, 0}, {0, 90, 0}, { {0, -90, 0}, {0, 90, 0},
{90, 0, 0}, {-90, 0, 0}, {90, 0, 0}, {-90, 0, 0},
{0, 0, 0}, {0, -180, 0} }; {0, 0, 0}, {0, -180, 0} };
int order[6] = {4, 0, 1, 5, 3, 2};
int numsides = 4;
vec3_t saveang; vec3_t saveang;
vrect_t vrect; vrect_t vrect;
vrect_t prect; vrect_t prect;
shader_t *shader;
int facemask;
/*needs glsl*/
if (!gl_config.arb_shader_objects)
return false;
if (!ffov.value)
return false;
facemask = 0;
if (ffov.value < 0)
{
shader = R_RegisterShader("postproc_panorama",
"{\n"
"program postproc_panorama\n"
"{\n"
"map $sourcecube\n"
"}\n"
"}\n"
);
//panoramic view needs at most the four sides
facemask |= 1<<4; /*front view*/
if (ffov.value < -90)
{
facemask |= (1<<0) | (1<<1); /*side views*/
if (ffov.value < -270)
facemask |= 1<<5; /*back view*/
}
}
else
{
shader = R_RegisterShader("postproc_fisheye",
"{\n"
"program postproc_fisheye\n"
"{\n"
"map $sourcecube\n"
"}\n"
"}\n"
);
//fisheye view sees up to a full sphere
facemask |= 1<<4; /*front view*/
if (ffov.value > 77)
facemask |= (1<<0) | (1<<1) | (1<<2) | (1<<3); /*side/top/bottom views*/
if (ffov.value > 270)
facemask |= 1<<5; /*back view*/
}
//fixme: should already have the vrect somewhere.
SCR_VRectForPlayer(&vrect, r_refdef.currentplayernum); SCR_VRectForPlayer(&vrect, r_refdef.currentplayernum);
prect.x = (vrect.x * vid.pixelwidth)/vid.width; prect.x = (vrect.x * vid.pixelwidth)/vid.width;
prect.width = (vrect.width * vid.pixelwidth)/vid.width; prect.width = (vrect.width * vid.pixelwidth)/vid.width;
prect.y = (vrect.y * vid.pixelheight)/vid.height; prect.y = (vrect.y * vid.pixelheight)/vid.height;
prect.height = (vrect.height * vid.pixelheight)/vid.height; prect.height = (vrect.height * vid.pixelheight)/vid.height;
if (!scenepp_panorama_program)
return false;
if (gl_config.arb_texture_non_power_of_two) if (gl_config.arb_texture_non_power_of_two)
{ {
if (prect.width < prect.height) if (prect.width < prect.height)
@ -1071,67 +981,17 @@ qboolean R_RenderScene_Fish(void)
VectorCopy(r_refdef.viewangles, saveang); VectorCopy(r_refdef.viewangles, saveang);
saveang[2] = 0; saveang[2] = 0;
if (ffov.value < 0) if (!TEXVALID(scenepp_postproc_cube))
{ {
//panoramic view needs at most the four sides scenepp_postproc_cube = GL_AllocNewTexture("***fish***", cmapsize, cmapsize);
if (ffov.value >= -90)
numsides = 1;
// else if (ffov.value >= -180)
// {
// numsides = 2;
// rot45 = 1;
// }
else if (ffov.value >= -270)
numsides = 3;
else
numsides = 4;
order[0] = 4; GL_MTBind(0, GL_TEXTURE_CUBE_MAP_ARB, scenepp_postproc_cube);
order[1] = 0;
order[2] = 1;
order[3] = 5;
}
else
{
//fisheye view sees a full sphere
//
if (ffov.value <= 77)
numsides = 1;
// else if (ffov.value <= 180)
// {
// numsides = 3;
// rot45 = 3;
// }
else if (ffov.value <= 270)
numsides = 5;
else
numsides = 6;
order[0] = 4;
order[1] = 0;
order[2] = 3;
order[3] = 1;
order[4] = 2;
order[5] = 5;
}
if (!TEXVALID(scenepp_fisheye_texture))
{
scenepp_fisheye_texture = GL_AllocNewTexture(cmapsize, cmapsize);
qglDisable(GL_TEXTURE_2D);
qglEnable(GL_TEXTURE_CUBE_MAP_ARB);
GL_MTBind(0, GL_TEXTURE_CUBE_MAP_ARB, scenepp_fisheye_texture);
for (i = 0; i < 6; i++) for (i = 0; i < 6; i++)
qglCopyTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB + i, 0, GL_RGB, 0, 0, cmapsize, cmapsize, 0); qglCopyTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB + i, 0, GL_RGB, 0, 0, cmapsize, cmapsize, 0);
qglTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); qglTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
qglTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); qglTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
qglTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR); qglTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
qglTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR); qglTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
qglEnable(GL_TEXTURE_2D);
qglDisable(GL_TEXTURE_CUBE_MAP_ARB);
} }
r_refdef.vrect.width = cmapsize; r_refdef.vrect.width = cmapsize;
@ -1147,44 +1007,30 @@ qboolean R_RenderScene_Fish(void)
ang[1][1] = 90; ang[1][1] = 90;
ang[1][2] = saveang[0]; ang[1][2] = saveang[0];
ang[5][0] = -saveang[0]*2; ang[5][0] = -saveang[0]*2;
for (i = 0; i < numsides; i++) for (i = 0; i < 6; i++)
{ {
if (!(facemask & (1<<i)))
continue;
r_refdef.fov_x = 90; r_refdef.fov_x = 90;
r_refdef.fov_y = 90; r_refdef.fov_y = 90;
r_refdef.viewangles[0] = saveang[0]+ang[order[i]][0]; r_refdef.viewangles[0] = saveang[0]+ang[i][0];
r_refdef.viewangles[1] = saveang[1]+ang[order[i]][1]; r_refdef.viewangles[1] = saveang[1]+ang[i][1];
r_refdef.viewangles[2] = saveang[2]+ang[order[i]][2]; r_refdef.viewangles[2] = saveang[2]+ang[i][2];
R_Clear (); R_Clear ();
// GLR_SetupFog ();
GL_SetShaderState2D(false); GL_SetShaderState2D(false);
// render normal view // render normal view
R_RenderScene (); R_RenderScene ();
GL_MTBind(0, GL_TEXTURE_CUBE_MAP_ARB, scenepp_fisheye_texture); GL_MTBind(0, GL_TEXTURE_CUBE_MAP_ARB, scenepp_postproc_cube);
qglCopyTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB + order[i], 0, 0, 0, 0, vid.pixelheight - (prect.y + cmapsize), cmapsize, cmapsize); qglCopyTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB + i, 0, 0, 0, 0, vid.pixelheight - (prect.y + cmapsize), cmapsize, cmapsize);
} }
//qglClear (GL_COLOR_BUFFER_BIT);
qglViewport (prect.x, vid.pixelheight - (prect.y+prect.height), prect.width, prect.height); qglViewport (prect.x, vid.pixelheight - (prect.y+prect.height), prect.width, prect.height);
GL_LazyBind(0, GL_TEXTURE_CUBE_MAP_ARB, scenepp_fisheye_texture, false);
if (scenepp_panorama_program && ffov.value < 0)
{
GLSlang_UseProgram(scenepp_panorama_program);
GLSlang_SetUniform1f(scenepp_panorama_parm_fov, -ffov.value*3.1415926535897932384626433832795/180);
}
else
{
GLSlang_UseProgram(scenepp_fisheye_program);
GLSlang_SetUniform1f(scenepp_fisheye_parm_fov, ffov.value*3.1415926535897932384626433832795/180);
}
// go 2d // go 2d
qglMatrixMode(GL_PROJECTION); qglMatrixMode(GL_PROJECTION);
qglPushMatrix(); qglPushMatrix();
@ -1194,37 +1040,17 @@ qboolean R_RenderScene_Fish(void)
qglPushMatrix(); qglPushMatrix();
qglLoadIdentity (); qglLoadIdentity ();
qglDisable (GL_DEPTH_TEST); // draw it through the shader
GL_CullFace(0); R2D_Image(0, 0, vid.width, vid.height, -0.5, 0.5, 0.5, -0.5, shader);
qglDisable (GL_ALPHA_TEST);
qglDisable(GL_BLEND);
qglBegin(GL_QUADS);
qglTexCoord2f(-0.5, 0.5);
qglVertex2f(0, 0);
qglTexCoord2f(0.5, 0.5);
qglVertex2f(vid.width, 0);
qglTexCoord2f(0.5, -0.5);
qglVertex2f(vid.width, vid.height);
qglTexCoord2f(-0.5, -0.5);
qglVertex2f(0, vid.height);
qglEnd();
//revert the matricies
qglMatrixMode(GL_PROJECTION); qglMatrixMode(GL_PROJECTION);
qglPopMatrix(); qglPopMatrix();
qglMatrixMode(GL_MODELVIEW); qglMatrixMode(GL_MODELVIEW);
qglPopMatrix(); qglPopMatrix();
qglDisable(GL_TEXTURE_CUBE_MAP_ARB);
qglEnable(GL_TEXTURE_2D);
GLSlang_UseProgram(0);
qglEnable (GL_DEPTH_TEST);
PPL_RevertToKnownState();
return true; return true;
} }
#endif
/* /*
================ ================
@ -1285,13 +1111,11 @@ void GLR_RenderView (void)
c_alias_polys = 0; c_alias_polys = 0;
} }
#ifdef FISH if (!(r_refdef.flags & Q2RDF_NOWORLDMODEL) && R_RenderScene_Cubemap())
if (ffov.value && cls.allow_fish && !(r_refdef.flags & Q2RDF_NOWORLDMODEL) && R_RenderScene_Fish())
{ {
//fisheye does its own rendering.
} }
else else
#endif
{ {
GL_SetShaderState2D(false); GL_SetShaderState2D(false);

View file

@ -27,8 +27,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
static void R_ReloadRTLights_f(void); static void R_ReloadRTLights_f(void);
static void R_SaveRTLights_f(void); static void R_SaveRTLights_f(void);
extern void R_InitBubble();
/* /*
================== ==================
R_InitTextures R_InitTextures
@ -246,11 +244,10 @@ R_Init
=============== ===============
*/ */
void GLR_ReInit (void) void GLR_ReInit (void)
{ {
netgraphtexture = GL_AllocNewTexture(0, 0); R_NetgraphInit();
R_InitBloomTextures(); R_InitBloomTextures();
R_InitFlashblends();
} }
/* /*
typedef struct typedef struct
@ -435,7 +432,7 @@ if (!data)
*/ */
void GLR_TimeRefresh_f (void); void GLR_TimeRefresh_f (void);
extern cvar_t gl_bump, v_contrast, r_drawflat; extern cvar_t v_contrast, r_drawflat;
extern cvar_t r_stains, r_stainfadetime, r_stainfadeammount; extern cvar_t r_stains, r_stainfadetime, r_stainfadeammount;
// callback defines // callback defines
@ -467,9 +464,9 @@ void GLR_DeInit (void)
Cvar_Unhook(&v_gamma); Cvar_Unhook(&v_gamma);
Cvar_Unhook(&v_contrast); Cvar_Unhook(&v_contrast);
GLDraw_DeInit();
Surf_DeInit(); Surf_DeInit();
GLDraw_DeInit();
} }
void GLR_Init (void) void GLR_Init (void)
@ -491,8 +488,6 @@ void GLR_Init (void)
Cvar_Hook(&v_gamma, GLV_Gamma_Callback); Cvar_Hook(&v_gamma, GLV_Gamma_Callback);
Cvar_Hook(&v_contrast, GLV_Gamma_Callback); Cvar_Hook(&v_contrast, GLV_Gamma_Callback);
R_InitBubble();
GLR_ReInit(); GLR_ReInit();
} }
@ -733,6 +728,9 @@ static void R_LoadRTLights(void)
vec3_t rgb; vec3_t rgb;
unsigned int flags; unsigned int flags;
float coronascale;
float corona;
float ambientscale, diffusescale, specularscale;
vec3_t angles; vec3_t angles;
//delete all old lights, even dynamic ones //delete all old lights, even dynamic ones
@ -789,31 +787,33 @@ static void R_LoadRTLights(void)
file = COM_Parse(file); file = COM_Parse(file);
//corona //corona
corona = file?atof(com_token):0;
file = COM_Parse(file); file = COM_Parse(file);
angles[0] = atof(com_token); angles[0] = file?atof(com_token):0;
file = COM_Parse(file); file = COM_Parse(file);
angles[1] = atof(com_token); angles[1] = file?atof(com_token):0;
file = COM_Parse(file); file = COM_Parse(file);
angles[2] = atof(com_token); angles[2] = file?atof(com_token):0;
file = COM_Parse(file); file = COM_Parse(file);
//corrona scale //corrona scale
coronascale = file?atof(com_token):0.25;
file = COM_Parse(file); file = COM_Parse(file);
//ambient //ambient
ambientscale = file?atof(com_token):0;
file = COM_Parse(file); file = COM_Parse(file);
//diffuse //diffuse
diffusescale = file?atof(com_token):1;
file = COM_Parse(file); file = COM_Parse(file);
//specular //specular
specularscale = file?atof(com_token):1;
file = COM_Parse(file); file = COM_Parse(file);
if (*com_token) flags |= file?atoi(com_token):LFLAG_REALTIMEMODE;
flags |= atoi(com_token);
else
flags |= LFLAG_REALTIMEMODE;
if (radius) if (radius)
{ {
@ -845,6 +845,7 @@ static void R_SaveRTLights_f(void)
vfsfile_t *f; vfsfile_t *f;
unsigned int i; unsigned int i;
char fname[MAX_QPATH]; char fname[MAX_QPATH];
vec3_t ang;
COM_StripExtension(cl.worldmodel->name, fname, sizeof(fname)); COM_StripExtension(cl.worldmodel->name, fname, sizeof(fname));
strncat(fname, ".rtlights", MAX_QPATH-1); strncat(fname, ".rtlights", MAX_QPATH-1);
@ -861,21 +862,22 @@ static void R_SaveRTLights_f(void)
continue; continue;
if (!light->radius) if (!light->radius)
continue; continue;
VectorAngles(light->axis[0], light->axis[2], ang);
VFS_PUTS(f, va( VFS_PUTS(f, va(
"%s%f %f %f " "%s%f %f %f "
"%f %f %f %f " "%f %f %f %f "
"%i " "%i "
"\"%s\" %f " "\"%s\" %f "
"%f %f %f " "%f %f %f "
"%f %f %f %i " "%f %f %f %f %i "
"\n" "\n"
, ,
(light->flags & LFLAG_NOSHADOWS)?"!":"", light->origin[0], light->origin[1], light->origin[2], (light->flags & LFLAG_NOSHADOWS)?"!":"", light->origin[0], light->origin[1], light->origin[2],
light->radius, light->color[0], light->color[1], light->color[2], light->radius, light->color[0], light->color[1], light->color[2],
light->style-1, light->style-1,
"", 0.0f, "", light->corona,
0.0f, 0.0f, 0.0f, ang[0], ang[1], ang[2],
0.0f, 0.0f, 0.0f, light->flags&(LFLAG_NORMALMODE|LFLAG_REALTIMEMODE) light->coronascale, light->ambientscale, light->diffusescale, light->specularscale, light->flags&(LFLAG_NORMALMODE|LFLAG_REALTIMEMODE)
)); ));
} }
VFS_CLOSE(f); VFS_CLOSE(f);
@ -970,6 +972,7 @@ TRACE(("dbg: GLR_NewMap: tp\n"));
void GLR_PreNewMap(void) void GLR_PreNewMap(void)
{ {
r_loadbumpmapping = r_deluxemapping.ival || r_shadow_realtime_world.ival || r_shadow_realtime_dlight.ival;
} }

View file

@ -26,9 +26,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "renderque.h" #include "renderque.h"
#include <math.h> #include <math.h>
extern cvar_t gl_bump;
void GLBE_ClearVBO(vbo_t *vbo) void GLBE_ClearVBO(vbo_t *vbo)
{ {
int vboh[7]; int vboh[7];
@ -327,7 +324,7 @@ void GLBE_UploadAllLightmaps(void)
lightmap[i]->lightmaps); lightmap[i]->lightmaps);
break; break;
} }
if (gl_bump.ival) if (r_deluxemapping.ival)
{ {
lightmap[i]->deluxmodified = false; lightmap[i]->deluxmodified = false;
lightmap[i]->deluxrectchange.l = LMBLOCK_WIDTH; lightmap[i]->deluxrectchange.l = LMBLOCK_WIDTH;

View file

@ -37,6 +37,7 @@ extern LPDIRECT3DDEVICE9 pD3DDev9;
#endif #endif
extern texid_t missing_texture; extern texid_t missing_texture;
static texid_t r_whiteimage;
static qboolean shader_reload_needed; static qboolean shader_reload_needed;
static qboolean shader_rescan_needed; static qboolean shader_rescan_needed;
@ -221,18 +222,17 @@ static qboolean Shader_EvaluateCondition(char **ptr)
} }
if (*token == '$') if (*token == '$')
{ {
extern cvar_t gl_bump;
token++; token++;
if (!Q_stricmp(token, "lpp")) if (!Q_stricmp(token, "lpp"))
conditiontrue = conditiontrue == !r_lightprepass.ival; conditiontrue = conditiontrue == !r_lightprepass.ival;
else if (!Q_stricmp(token, "lightmap")) else if (!Q_stricmp(token, "lightmap"))
conditiontrue = conditiontrue == !r_fullbright.value; conditiontrue = conditiontrue == !r_fullbright.value;
else if (!Q_stricmp(token, "deluxmap") ) else if (!Q_stricmp(token, "deluxmap") )
conditiontrue = conditiontrue == (r_deluxemapping.value && gl_bump.value); conditiontrue = conditiontrue == r_deluxemapping.ival;
//normalmaps are generated if they're not already known. //normalmaps are generated if they're not already known.
else if (!Q_stricmp(token, "normalmap") ) else if (!Q_stricmp(token, "normalmap") )
conditiontrue = conditiontrue == !!gl_bump.value; conditiontrue = conditiontrue == r_loadbumpmapping;
else if (!Q_stricmp(token, "gles") ) else if (!Q_stricmp(token, "gles") )
{ {
@ -265,13 +265,14 @@ static qboolean Shader_EvaluateCondition(char **ptr)
#else #else
conditiontrue = conditiontrue == false; conditiontrue = conditiontrue == false;
#endif #endif
}
// GCC hates these within if statements "error: expected '}' before 'else'" // GCC hates these within if statements "error: expected '}' before 'else'"
#ifdef _MSC_VER #ifdef warningmsg
#pragma message("shader fixme") #pragma warningmsg("shader fixme")
#endif #endif
}
else if (!Q_stricmp(token, "diffuse") ) else if (!Q_stricmp(token, "diffuse") )
conditiontrue = conditiontrue == true; conditiontrue = conditiontrue == true;
else if (!Q_stricmp(token, "specular") ) else if (!Q_stricmp(token, "specular") )
@ -548,7 +549,7 @@ static int Shader_SetImageFlags ( shader_t *shader )
static texid_t Shader_FindImage ( char *name, int flags ) static texid_t Shader_FindImage ( char *name, int flags )
{ {
if (!Q_stricmp (name, "$whiteimage")) if (!Q_stricmp (name, "$whiteimage"))
return r_nulltex; return r_whiteimage;
else else
return R_LoadHiResTexture(name, NULL, flags); return R_LoadHiResTexture(name, NULL, flags);
} }
@ -775,7 +776,6 @@ static void Shader_LoadPermutations(char *name, program_t *prog, char *script, i
unsigned int nopermutation = ~0u; unsigned int nopermutation = ~0u;
int p, n, pn; int p, n, pn;
char *end; char *end;
char *vers;
char *cvarfnames[64]; char *cvarfnames[64];
int cvarfcount = 0; int cvarfcount = 0;
@ -829,10 +829,6 @@ static void Shader_LoadPermutations(char *name, program_t *prog, char *script, i
break; break;
}; };
if (ver)
vers = va("#version %u\n", ver);
else
vers = NULL;
memset(prog->handle, 0, sizeof(*prog->handle)*PERMUTATIONS); memset(prog->handle, 0, sizeof(*prog->handle)*PERMUTATIONS);
for (p = 0; p < PERMUTATIONS; p++) for (p = 0; p < PERMUTATIONS; p++)
{ {
@ -853,7 +849,7 @@ static void Shader_LoadPermutations(char *name, program_t *prog, char *script, i
permutationdefines[pn++] = permutationname[n]; permutationdefines[pn++] = permutationname[n];
} }
permutationdefines[pn++] = NULL; permutationdefines[pn++] = NULL;
prog->handle[p].glsl = GLSlang_CreateProgram(name, vers, permutationdefines, script, script); prog->handle[p].glsl = GLSlang_CreateProgram(name, (((p & PERMUTATION_SKELETAL) && ver < 120)?120:ver), permutationdefines, script, script);
} }
#endif #endif
#ifdef D3DQUAKE #ifdef D3DQUAKE
@ -905,11 +901,10 @@ struct sbuiltin_s
/*defaultfill is a simple shader for block-filling with vertex colours. note that the blendfunc stuff is done after the shader anyway.*/ /*defaultfill is a simple shader for block-filling with vertex colours. note that the blendfunc stuff is done after the shader anyway.*/
{QR_OPENGL/*ES*/, 100, "defaultfill", {QR_OPENGL/*ES*/, 100, "defaultfill",
"#ifdef VERTEX_SHADER\n" "#ifdef VERTEX_SHADER\n"
"attribute vec2 v_texcoord;\n"
"attribute vec4 v_colour;\n" "attribute vec4 v_colour;\n"
"varying vec4 vc;\n" "varying vec4 vc;\n"
"void main (void)\n" "void main ()\n"
"{\n" "{\n"
" vc = v_colour;\n" " vc = v_colour;\n"
" gl_Position = ftetransform();\n" " gl_Position = ftetransform();\n"
@ -918,7 +913,7 @@ struct sbuiltin_s
"#ifdef FRAGMENT_SHADER\n" "#ifdef FRAGMENT_SHADER\n"
"varying lowp vec4 vc;\n" "varying lowp vec4 vc;\n"
"void main (void)\n" "void main ()\n"
"{\n" "{\n"
" gl_FragColor = vc;\n" " gl_FragColor = vc;\n"
"}\n" "}\n"
@ -932,7 +927,7 @@ struct sbuiltin_s
"varying vec2 tc;\n" "varying vec2 tc;\n"
"varying vec4 vc;\n" "varying vec4 vc;\n"
"void main (void)\n" "void main ()\n"
"{\n" "{\n"
" tc = v_texcoord;\n" " tc = v_texcoord;\n"
" vc = v_colour;\n" " vc = v_colour;\n"
@ -945,7 +940,7 @@ struct sbuiltin_s
"varying mediump vec2 tc;\n" "varying mediump vec2 tc;\n"
"varying lowp vec4 vc;\n" "varying lowp vec4 vc;\n"
"void main (void)\n" "void main ()\n"
"{\n" "{\n"
" gl_FragColor = texture2D(s_t0, tc) * vc;\n" " gl_FragColor = texture2D(s_t0, tc) * vc;\n"
"}\n" "}\n"
@ -958,7 +953,7 @@ struct sbuiltin_s
"varying vec2 tc;\n" "varying vec2 tc;\n"
"varying vec4 vc;\n" "varying vec4 vc;\n"
"void main (void)\n" "void main ()\n"
"{\n" "{\n"
" tc = v_texcoord;\n" " tc = v_texcoord;\n"
" vc = v_colour;\n" " vc = v_colour;\n"
@ -971,7 +966,7 @@ struct sbuiltin_s
"in vec2 tc;\n" "in vec2 tc;\n"
"varying vec4 vc;\n" "varying vec4 vc;\n"
"void main (void)\n" "void main ()\n"
"{\n" "{\n"
" gl_FragColor = texture2D(s_t0, tc) * vc;\n" " gl_FragColor = texture2D(s_t0, tc) * vc;\n"
"}\n" "}\n"
@ -985,7 +980,7 @@ struct sbuiltin_s
"attribute vec2 v_lmcoord;\n" "attribute vec2 v_lmcoord;\n"
"varying vec2 tc, lm;\n" "varying vec2 tc, lm;\n"
"void main (void)\n" "void main ()\n"
"{\n" "{\n"
" tc = v_texcoord;\n" " tc = v_texcoord;\n"
" lm = v_lmcoord;\n" " lm = v_lmcoord;\n"
@ -1002,7 +997,7 @@ struct sbuiltin_s
"varying mediump vec2 tc, lm;\n" "varying mediump vec2 tc, lm;\n"
"uniform mediump float cvar_gl_overbright;\n" "uniform mediump float cvar_gl_overbright;\n"
"void main (void)\n" "void main ()\n"
"{\n" "{\n"
" mediump float scale = exp2(floor(clamp(cvar_gl_overbright, 0.0, 2.0)));\n" " mediump float scale = exp2(floor(clamp(cvar_gl_overbright, 0.0, 2.0)));\n"
" gl_FragColor = texture2D(s_t0, tc) * texture2D(s_t1, lm) * vec4(scale, scale, scale, 1);\n" " gl_FragColor = texture2D(s_t0, tc) * texture2D(s_t1, lm) * vec4(scale, scale, scale, 1);\n"
@ -1016,7 +1011,7 @@ struct sbuiltin_s
"attribute vec2 v_lmcoord;\n" "attribute vec2 v_lmcoord;\n"
"varying vec2 tc, lm;\n" "varying vec2 tc, lm;\n"
"void main (void)\n" "void main ()\n"
"{\n" "{\n"
" tc = v_texcoord;\n" " tc = v_texcoord;\n"
" lm = v_lmcoord;\n" " lm = v_lmcoord;\n"
@ -1033,7 +1028,7 @@ struct sbuiltin_s
"varying vec2 tc, lm;\n" "varying vec2 tc, lm;\n"
"uniform float cvar_gl_overbright;\n" "uniform float cvar_gl_overbright;\n"
"void main (void)\n" "void main ()\n"
"{\n" "{\n"
" float scale = exp2(floor(clamp(cvar_gl_overbright, 0.0, 2.0)));\n" " float scale = exp2(floor(clamp(cvar_gl_overbright, 0.0, 2.0)));\n"
" gl_FragColor = texture2D(s_t0, tc) * texture2D(s_t1, lm) * vec4(scale, scale, scale, 1);\n" " gl_FragColor = texture2D(s_t0, tc) * texture2D(s_t1, lm) * vec4(scale, scale, scale, 1);\n"
@ -1046,7 +1041,7 @@ struct sbuiltin_s
"varying mediump vec2 tc;\n" "varying mediump vec2 tc;\n"
"#ifdef VERTEX_SHADER\n" "#ifdef VERTEX_SHADER\n"
"attribute vec2 v_texcoord;\n" "attribute vec2 v_texcoord;\n"
"void main (void)\n" "void main ()\n"
"{\n" "{\n"
" tc = v_texcoord;\n" " tc = v_texcoord;\n"
" gl_Position = ftetransform();\n" " gl_Position = ftetransform();\n"
@ -1058,7 +1053,7 @@ struct sbuiltin_s
"uniform mediump float e_time;\n" "uniform mediump float e_time;\n"
"uniform lowp float cvar_r_wateralpha;\n" "uniform lowp float cvar_r_wateralpha;\n"
"void main (void)\n" "void main ()\n"
"{\n" "{\n"
" mediump vec2 ntc;\n" " mediump vec2 ntc;\n"
" ntc.s = tc.s + sin(tc.t+e_time)*0.125;\n" " ntc.s = tc.s + sin(tc.t+e_time)*0.125;\n"
@ -1074,7 +1069,7 @@ struct sbuiltin_s
"varying vec2 tc;\n" "varying vec2 tc;\n"
"#ifdef VERTEX_SHADER\n" "#ifdef VERTEX_SHADER\n"
"attribute vec2 v_texcoord;\n" "attribute vec2 v_texcoord;\n"
"void main (void)\n" "void main ()\n"
"{\n" "{\n"
" tc = v_texcoord.st;\n" " tc = v_texcoord.st;\n"
" gl_Position = ftetransform();\n" " gl_Position = ftetransform();\n"
@ -1086,7 +1081,7 @@ struct sbuiltin_s
"uniform float e_time;\n" "uniform float e_time;\n"
"uniform float cvar_r_wateralpha;\n" "uniform float cvar_r_wateralpha;\n"
"void main (void)\n" "void main ()\n"
"{\n" "{\n"
" vec2 ntc;\n" " vec2 ntc;\n"
" ntc.s = tc.s + sin(tc.t+e_time)*0.125;\n" " ntc.s = tc.s + sin(tc.t+e_time)*0.125;\n"
@ -1097,12 +1092,122 @@ struct sbuiltin_s
"}\n" "}\n"
"#endif\n" "#endif\n"
}, },
{QR_OPENGL, 110, "underwaterwarp",
/*
inputs:
texcoords: edge points
coords: vertex coords (duh)
time
ampscale (cvar = r_waterwarp)
use ifs instead of an edge map?
*/
"!!cvarf r_waterwarp\n"
"#ifdef VERTEX_SHADER\n"
"attribute vec2 v_texcoord;\n"
"varying vec2 v_stc;\n"
"varying vec2 v_warp;\n"
"varying vec2 v_edge;\n"
"uniform float e_time;\n"
"void main ()\n"
"{\n"
"gl_Position = ftetransform();\n"
"v_stc = (1.0+(gl_Position.xy / gl_Position.w))/2.0;\n"
"v_warp.s = e_time * 0.25 + v_texcoord.s;\n"
"v_warp.t = e_time * 0.25 + v_texcoord.t;\n"
"v_edge = v_texcoord.xy;\n"
"}\n"
"#endif\n"
"#ifdef FRAGMENT_SHADER\n"
"varying vec2 v_stc;\n"
"varying vec2 v_warp;\n"
"varying vec2 v_edge;\n"
"uniform sampler2D s_t0;/*$currentrender*/\n"
"uniform sampler2D s_t1;/*warp image*/\n"
"uniform sampler2D s_t2;/*edge image*/\n"
"uniform vec3 e_rendertexturescale;\n"
"uniform float cvar_r_waterwarp;\n"
"void main ()\n"
"{\n"
"float amptemp;\n"
"vec3 edge;\n"
"edge = texture2D( s_t2, v_edge ).rgb;\n"
"amptemp = (0.010 / 0.625) * cvar_r_waterwarp * edge.x;\n"
"vec3 offset;\n"
"offset = texture2D( s_t1, v_warp ).rgb;\n"
"offset.x = (offset.x - 0.5) * 2.0;\n"
"offset.y = (offset.y - 0.5) * 2.0;\n"
"vec2 temp;\n"
"temp.x = v_stc.x + offset.x * amptemp;\n"
"temp.y = v_stc.y + offset.y * amptemp;\n"
"gl_FragColor = texture2D( s_t0, temp*e_rendertexturescale.st );\n"
"}\n"
"#endif\n"
},
{QR_OPENGL, 110, "postproc_panorama",
"!!cvarf ffov\n"
"#ifdef VERTEX_SHADER\n"
"attribute vec2 v_texcoord;\n"
"varying vec2 texcoord;\n"
"void main()\n"
"{\n"
"texcoord = v_texcoord.xy;\n"
"gl_Position = ftetransform();\n"
"}\n"
"#endif\n"
"#ifdef FRAGMENT_SHADER\n"
"uniform samplerCube s_t0;\n"
"varying vec2 texcoord;\n"
"uniform float cvar_ffov;\n"
"void main()\n"
"{\n"
"vec3 tc; \n"
"float ang; \n"
"ang = texcoord.x*-radians(cvar_ffov); \n"
"tc.x = sin(ang); \n"
"tc.y = -texcoord.y; \n"
"tc.z = cos(ang); \n"
"gl_FragColor = textureCube(s_t0, tc);\n"
"}\n"
"#endif\n"
},
{QR_OPENGL, 110, "postproc_fisheye",
"!!cvarf ffov\n"
"#ifdef VERTEX_SHADER\n"
"attribute vec2 v_texcoord;\n"
"varying vec2 texcoord;\n"
"void main()\n"
"{\n"
"texcoord = v_texcoord.xy;\n"
"gl_Position = ftetransform();\n"
"}\n"
"#endif\n"
"#ifdef FRAGMENT_SHADER\n"
"uniform samplerCube s_t0;\n"
"varying vec2 texcoord;\n"
"uniform float cvar_ffov;\n"
"void main()\n"
"{\n"
"vec3 tc; \n"
"vec2 d; \n"
"vec2 ang; \n"
"d = texcoord; \n"
"ang.x = sqrt(d.x*d.x+d.y*d.y)*radians(cvar_ffov); \n"
"ang.y = -atan(d.y, d.x); \n"
"tc.x = sin(ang.x) * cos(ang.y); \n"
"tc.y = sin(ang.x) * sin(ang.y); \n"
"tc.z = cos(ang.x); \n"
"gl_FragColor = textureCube(s_t0, tc);\n"
"}\n"
"#endif\n"
},
/*defautsky projects the texture in order to match q1 skies, along with two separate layers scrolling at separate speeds*/ /*defautsky projects the texture in order to match q1 skies, along with two separate layers scrolling at separate speeds*/
{QR_OPENGL/*ES*/, 100, "defaultsky", {QR_OPENGL/*ES*/, 100, "defaultsky",
"#ifdef VERTEX_SHADER\n" "#ifdef VERTEX_SHADER\n"
"varying vec3 pos;\n" "varying vec3 pos;\n"
"void main (void)\n" "void main ()\n"
"{\n" "{\n"
" pos = v_position.xyz;\n" " pos = v_position.xyz;\n"
" gl_Position = ftetransform();\n" " gl_Position = ftetransform();\n"
@ -1117,7 +1222,7 @@ struct sbuiltin_s
"uniform mediump vec3 e_eyepos;\n" "uniform mediump vec3 e_eyepos;\n"
"varying mediump vec3 pos;\n" "varying mediump vec3 pos;\n"
"void main (void)\n" "void main ()\n"
"{\n" "{\n"
" mediump vec2 tccoord;\n" " mediump vec2 tccoord;\n"
@ -1141,7 +1246,7 @@ struct sbuiltin_s
"#ifdef VERTEX_SHADER\n" "#ifdef VERTEX_SHADER\n"
"varying vec3 pos;\n" "varying vec3 pos;\n"
"void main (void)\n" "void main ()\n"
"{\n" "{\n"
" pos = v_position.xyz;\n" " pos = v_position.xyz;\n"
" gl_Position = ftetransform();\n" " gl_Position = ftetransform();\n"
@ -1155,7 +1260,7 @@ struct sbuiltin_s
"uniform sampler2D s_t0;\n" "uniform sampler2D s_t0;\n"
"uniform sampler2D s_t1;\n" "uniform sampler2D s_t1;\n"
"void main (void)\n" "void main ()\n"
"{\n" "{\n"
" vec2 tccoord;\n" " vec2 tccoord;\n"
@ -1181,19 +1286,20 @@ struct sbuiltin_s
"!!permu UPPER\n" "!!permu UPPER\n"
"!!permu SKELETAL\n" "!!permu SKELETAL\n"
"#ifdef VERTEX_SHADER\n" "#ifdef VERTEX_SHADER\n"
"#include \"sys/skeletal.h\"\n"
"attribute vec2 v_texcoord;\n" "attribute vec2 v_texcoord;\n"
"varying vec2 tc;\n" "varying vec2 tc;\n"
"attribute vec3 v_normal;\n"
"uniform vec3 e_light_dir;\n" "uniform vec3 e_light_dir;\n"
"uniform vec3 e_light_mul;\n" "uniform vec3 e_light_mul;\n"
"uniform vec3 e_light_ambient;\n" "uniform vec3 e_light_ambient;\n"
"varying vec3 light;\n" "varying vec3 light;\n"
"void main (void)\n" "void main ()\n"
"{\n" "{\n"
" gl_Position = ftetransform();\n" " vec3 n;\n"
" light = e_light_ambient + (dot(v_normal,e_light_dir)*e_light_mul);\n" " gl_Position = skeletaltransform_n(n);\n"
" light = e_light_ambient + (dot(n,e_light_dir)*e_light_mul);\n"
" tc = v_texcoord;\n" " tc = v_texcoord;\n"
"}\n" "}\n"
"#endif\n" "#endif\n"
@ -1215,7 +1321,7 @@ struct sbuiltin_s
"varying lowp vec3 light;\n" "varying lowp vec3 light;\n"
"uniform lowp vec4 e_colourident;\n" "uniform lowp vec4 e_colourident;\n"
"void main (void)\n" "void main ()\n"
"{\n" "{\n"
" lowp vec4 col;\n" " lowp vec4 col;\n"
" col = texture2D(s_t0, tc);\n" " col = texture2D(s_t0, tc);\n"
@ -1236,25 +1342,25 @@ struct sbuiltin_s
"}\n" "}\n"
"#endif\n" "#endif\n"
}, },
{QR_OPENGL, 120, "defaultskin", {QR_OPENGL, 110, "defaultskin",
"!!permu FULLBRIGHT\n" "!!permu FULLBRIGHT\n"
"!!permu LOWER\n" "!!permu LOWER\n"
"!!permu UPPER\n" "!!permu UPPER\n"
"!!permu SKELETAL\n" "!!permu SKELETAL\n"
"varying vec2 tc;\n"
"varying vec3 light;\n"
"#ifdef VERTEX_SHADER\n" "#ifdef VERTEX_SHADER\n"
"#include \"sys/skeletal.h\"\n"
"attribute vec2 v_texcoord;\n" "attribute vec2 v_texcoord;\n"
"varying vec2 tc;\n"
"attribute vec3 v_normal;\n"
"uniform vec3 e_light_dir;\n" "uniform vec3 e_light_dir;\n"
"uniform vec3 e_light_mul;\n" "uniform vec3 e_light_mul;\n"
"uniform vec3 e_light_ambient;\n" "uniform vec3 e_light_ambient;\n"
"varying vec3 light;\n" "void main ()\n"
"#ifndef SKELETAL\nattribute vec4 v_weight;\n#endif\n"
"void main (void)\n"
"{\n" "{\n"
" gl_Position = ftetransform();\n" " vec3 n;\n"
" light = e_light_ambient + (dot(v_normal,e_light_dir)*e_light_mul);\n" " gl_Position = skeletaltransform_n(n);\n"
" light = e_light_ambient + (dot(n,e_light_dir)*e_light_mul);\n"
" tc = v_texcoord;\n" " tc = v_texcoord;\n"
"}\n" "}\n"
"#endif\n" "#endif\n"
@ -1272,11 +1378,9 @@ struct sbuiltin_s
"#ifdef FULLBRIGHT\n" "#ifdef FULLBRIGHT\n"
"uniform sampler2D s_t3;\n" /*tex_fullbright*/ "uniform sampler2D s_t3;\n" /*tex_fullbright*/
"#endif\n" "#endif\n"
"varying vec2 tc;\n"
"varying vec3 light;\n"
"uniform vec4 e_colourident;\n" "uniform vec4 e_colourident;\n"
"void main (void)\n" "void main ()\n"
"{\n" "{\n"
" vec4 col, sp;\n" " vec4 col, sp;\n"
" col = texture2D(s_t0, tc);\n" " col = texture2D(s_t0, tc);\n"
@ -1299,34 +1403,31 @@ struct sbuiltin_s
}, },
{QR_OPENGL, 110, "lpp_depthnorm", {QR_OPENGL, 110, "lpp_depthnorm",
"!!permu BUMP\n" "!!permu BUMP\n"
"!!permu SKELETAL\n"
"varying vec2 pos;\n" "varying vec2 pos;\n"
"varying vec3 norm, tang, bitang;\n" "varying vec3 norm, tang, bitang;\n"
"#if defined(BUMP)\n" "#if defined(BUMP)\n"
"varying vec2 tc;\n" "varying vec2 tc;\n"
"#endif\n" "#endif\n"
"#ifdef VERTEX_SHADER\n" "#ifdef VERTEX_SHADER\n"
"#include \"sys/skeletal.h\"\n"
"attribute vec2 v_texcoord;\n" "attribute vec2 v_texcoord;\n"
"attribute vec3 v_normal;\n" "void main()\n"
"attribute vec3 v_svector;\n"
"attribute vec3 v_tvector;\n"
"uniform mat4 m_modelviewprojection;\n"
"void main(void)\n"
"{\n" "{\n"
"gl_Position = ftetransform();\n"
"pos = gl_Position.zw;\n"
"norm = v_normal;\n"
"#if defined(BUMP)\n" "#if defined(BUMP)\n"
"tang = v_svector;\n" "gl_Position = skeletaltransform_nst(norm, tang, bitang);\n"
"bitang = v_tvector;\n"
"tc = v_texcoord;\n" "tc = v_texcoord;\n"
"#else\n"
"gl_Position = skeletaltransform_n(norm);\n"
"#endif\n" "#endif\n"
"pos = gl_Position.zw;\n"
"}\n" "}\n"
"#endif\n" "#endif\n"
"#ifdef FRAGMENT_SHADER\n" "#ifdef FRAGMENT_SHADER\n"
"#if defined(BUMP)\n" "#if defined(BUMP)\n"
"uniform sampler2D s_t0;\n" "uniform sampler2D s_t0;\n"
"#endif\n" "#endif\n"
"void main(void)\n" "void main()\n"
"{\n" "{\n"
"vec3 onorm;\n" "vec3 onorm;\n"
"#if defined(BUMP)\n" "#if defined(BUMP)\n"
@ -1343,9 +1444,9 @@ struct sbuiltin_s
{QR_OPENGL, 110, "lpp_light", {QR_OPENGL, 110, "lpp_light",
"varying vec4 tf;\n" "varying vec4 tf;\n"
"#ifdef VERTEX_SHADER\n" "#ifdef VERTEX_SHADER\n"
"void main(void)\n" "void main()\n"
"{\n" "{\n"
"gl_Position = tf = ftetransform();\n" "tf = ftetransform(); gl_Position = tf;\n"
"}\n" "}\n"
"#endif\n" "#endif\n"
"#ifdef FRAGMENT_SHADER\n" "#ifdef FRAGMENT_SHADER\n"
@ -1368,7 +1469,7 @@ struct sbuiltin_s
"return pos.xyz / pos.w;\n" "return pos.xyz / pos.w;\n"
"}\n" "}\n"
"void main (void)\n" "void main ()\n"
"{\n" "{\n"
"vec3 lightColour = l_lightcolour.rgb;\n" "vec3 lightColour = l_lightcolour.rgb;\n"
"float lightIntensity = 1.0;\n" "float lightIntensity = 1.0;\n"
@ -1412,7 +1513,7 @@ struct sbuiltin_s
"attribute vec2 v_texcoord;\n" "attribute vec2 v_texcoord;\n"
"attribute vec2 v_lmcoord;\n" "attribute vec2 v_lmcoord;\n"
"void main (void)\n" "void main ()\n"
"{\n" "{\n"
"tc = v_texcoord;\n" "tc = v_texcoord;\n"
"lm = v_lmcoord;\n" "lm = v_lmcoord;\n"
@ -1429,7 +1530,7 @@ struct sbuiltin_s
//"uniform sampler2D s_t5;\n" /*tex_fullbright*/ //"uniform sampler2D s_t5;\n" /*tex_fullbright*/
"uniform float cvar_gl_overbright;\n" "uniform float cvar_gl_overbright;\n"
"void main (void)\n" "void main ()\n"
"{\n" "{\n"
"float lmscale = exp2(floor(clamp(cvar_gl_overbright, 0.0, 2.0)));\n" "float lmscale = exp2(floor(clamp(cvar_gl_overbright, 0.0, 2.0)));\n"
//"gl_FragColor = texture2D(s_t0, tc) * texture2D(s_t1, lm) * vec4(scale, scale, scale, 1.0);\n" //"gl_FragColor = texture2D(s_t0, tc) * texture2D(s_t1, lm) * vec4(scale, scale, scale, 1.0);\n"
@ -1741,6 +1842,8 @@ struct shader_field_names_s shader_field_names[] =
{"l_lightradius", SP_LIGHTRADIUS}, {"l_lightradius", SP_LIGHTRADIUS},
{"l_lightcolour", SP_LIGHTCOLOUR}, {"l_lightcolour", SP_LIGHTCOLOUR},
{"l_lightposition", SP_LIGHTPOSITION}, {"l_lightposition", SP_LIGHTPOSITION},
{"e_rendertexturescale", SP_RENDERTEXTURESCALE},
{NULL} {NULL}
}; };
@ -2118,8 +2221,11 @@ static void Shader_ProgramParam ( shader_t *shader, shaderpass_t *pass, char **p
} }
} }
} }
if (!foundone && !silent) if (!foundone)
Con_Printf("shader %s: param \"%s\" not found\n", shader->name, token); {
if (!silent)
Con_Printf("shader %s: param \"%s\" not found\n", shader->name, token);
}
else else
prog->numparams++; prog->numparams++;
@ -2240,6 +2346,11 @@ static qboolean ShaderPass_MapGen (shader_t *shader, shaderpass_t *pass, char *t
pass->texgen = T_GEN_SOURCECOLOUR; pass->texgen = T_GEN_SOURCECOLOUR;
pass->tcgen = TC_GEN_BASE; //FIXME: moo! pass->tcgen = TC_GEN_BASE; //FIXME: moo!
} }
else if (!Q_stricmp (tname, "$sourcecube"))
{
pass->texgen = T_GEN_SOURCECUBE;
pass->tcgen = TC_GEN_BASE; //FIXME: moo!
}
else if (!Q_stricmp (tname, "$sourcedepth")) else if (!Q_stricmp (tname, "$sourcedepth"))
{ {
pass->texgen = T_GEN_SOURCEDEPTH; pass->texgen = T_GEN_SOURCEDEPTH;
@ -2383,13 +2494,13 @@ static void Shaderpass_RGBGen (shader_t *shader, shaderpass_t *pass, char **ptr)
else if (!Q_stricmp (token, "oneMinusEntity")) else if (!Q_stricmp (token, "oneMinusEntity"))
pass->rgbgen = RGB_GEN_ONE_MINUS_ENTITY; pass->rgbgen = RGB_GEN_ONE_MINUS_ENTITY;
else if (!Q_stricmp (token, "vertex")) else if (!Q_stricmp (token, "vertex"))
pass->rgbgen = RGB_GEN_VERTEX; pass->rgbgen = RGB_GEN_VERTEX_LIGHTING;
else if (!Q_stricmp (token, "oneMinusVertex")) else if (!Q_stricmp (token, "oneMinusVertex"))
pass->rgbgen = RGB_GEN_ONE_MINUS_VERTEX; pass->rgbgen = RGB_GEN_ONE_MINUS_VERTEX;
else if (!Q_stricmp (token, "lightingDiffuse")) else if (!Q_stricmp (token, "lightingDiffuse"))
pass->rgbgen = RGB_GEN_LIGHTING_DIFFUSE; pass->rgbgen = RGB_GEN_LIGHTING_DIFFUSE;
else if (!Q_stricmp (token, "exactvertex")) else if (!Q_stricmp (token, "exactvertex"))
pass->rgbgen = RGB_GEN_EXACT_VERTEX; pass->rgbgen = RGB_GEN_VERTEX_EXACT;
else if (!Q_stricmp (token, "const") || !Q_stricmp (token, "constant")) else if (!Q_stricmp (token, "const") || !Q_stricmp (token, "constant"))
{ {
pass->rgbgen = RGB_GEN_CONST; pass->rgbgen = RGB_GEN_CONST;
@ -2606,6 +2717,17 @@ static void Shaderpass_DepthWrite (shader_t *shader, shaderpass_t *pass, char **
pass->shaderbits |= SBITS_MISC_DEPTHWRITE; pass->shaderbits |= SBITS_MISC_DEPTHWRITE;
} }
static void Shaderpass_NoDepthTest (shader_t *shader, shaderpass_t *pass, char **ptr)
{
shader->flags |= SHADER_DEPTHWRITE;
pass->shaderbits |= SBITS_MISC_NODEPTHTEST;
}
static void Shaderpass_NoDepth (shader_t *shader, shaderpass_t *pass, char **ptr)
{
shader->flags |= SHADER_DEPTHWRITE;
}
static void Shaderpass_TcMod (shader_t *shader, shaderpass_t *pass, char **ptr) static void Shaderpass_TcMod (shader_t *shader, shaderpass_t *pass, char **ptr)
{ {
int i; int i;
@ -2857,6 +2979,8 @@ static shaderkey_t shaderpasskeys[] =
{"blendfunc", Shaderpass_BlendFunc }, {"blendfunc", Shaderpass_BlendFunc },
{"depthfunc", Shaderpass_DepthFunc }, {"depthfunc", Shaderpass_DepthFunc },
{"depthwrite", Shaderpass_DepthWrite }, {"depthwrite", Shaderpass_DepthWrite },
{"nodepthtest", Shaderpass_NoDepthTest },
{"nodepth", Shaderpass_NoDepth },
{"alphafunc", Shaderpass_AlphaFunc }, {"alphafunc", Shaderpass_AlphaFunc },
{"tcmod", Shaderpass_TcMod }, {"tcmod", Shaderpass_TcMod },
{"map", Shaderpass_Map }, {"map", Shaderpass_Map },
@ -2941,6 +3065,7 @@ int Shader_InitCallback (const char *name, int size, void *param)
qboolean Shader_Init (void) qboolean Shader_Init (void)
{ {
int wibuf[16];
shaderbuflen = 0; shaderbuflen = 0;
if (!r_shaders) if (!r_shaders)
@ -2958,6 +3083,12 @@ qboolean Shader_Init (void)
shader_rescan_needed = true; shader_rescan_needed = true;
Shader_NeedReload(); Shader_NeedReload();
Shader_DoReload(); Shader_DoReload();
memset(wibuf, 0xff, sizeof(wibuf));
if (!qrenderer)
r_whiteimage = r_nulltex;
else
r_whiteimage = R_LoadTexture("$whiteimage", 4, 4, TF_RGBA32, wibuf, IF_NOMIPMAP|IF_NOPICMIP|IF_NEAREST|IF_NOGAMMA);
return true; return true;
} }
@ -3146,12 +3277,17 @@ void Shader_SetBlendmode (shaderpass_t *pass)
if ((pass->rgbgen == RGB_GEN_IDENTITY) && (pass->alphagen == ALPHA_GEN_IDENTITY)) if ((pass->rgbgen == RGB_GEN_IDENTITY) && (pass->alphagen == ALPHA_GEN_IDENTITY))
{ {
pass->blendmode = PBM_REPLACE; pass->blendmode = PBM_REPLACE;
return;
}
else if ((pass->rgbgen == RGB_GEN_IDENTITY_LIGHTING) && (pass->alphagen == ALPHA_GEN_IDENTITY))
{
pass->shaderbits &= ~SBITS_BLEND_BITS;
pass->shaderbits |= SBITS_SRCBLEND_ONE;
pass->shaderbits |= SBITS_DSTBLEND_ZERO;
pass->blendmode = PBM_REPLACELIGHT;
} }
else else
{ {
#ifdef _MSC_VER
#pragma message("is this correct?")
#endif
pass->shaderbits &= ~SBITS_BLEND_BITS; pass->shaderbits &= ~SBITS_BLEND_BITS;
pass->shaderbits |= SBITS_SRCBLEND_ONE; pass->shaderbits |= SBITS_SRCBLEND_ONE;
pass->shaderbits |= SBITS_DSTBLEND_ZERO; pass->shaderbits |= SBITS_DSTBLEND_ZERO;
@ -3254,7 +3390,8 @@ void Shader_Readpass (shader_t *shader, char **ptr)
// check some things // check some things
if ( ignore ) if ( ignore )
{ {
Shader_Free ( shader ); Shader_FreePass (pass);
shader->numpasses--;
return; return;
} }
@ -3293,8 +3430,8 @@ void Shader_Readpass (shader_t *shader, char **ptr)
if ((shader->flags & SHADER_SKY) && (shader->flags & SHADER_DEPTHWRITE)) if ((shader->flags & SHADER_SKY) && (shader->flags & SHADER_DEPTHWRITE))
{ {
#ifdef _MSC_VER #ifdef warningmsg
#pragma message("is this valid?") #pragma warningmsg("is this valid?")
#endif #endif
pass->shaderbits &= ~SBITS_MISC_DEPTHWRITE; pass->shaderbits &= ~SBITS_MISC_DEPTHWRITE;
} }
@ -3434,9 +3571,9 @@ void Shader_SetFeatures ( shader_t *s )
case RGB_GEN_LIGHTING_DIFFUSE: case RGB_GEN_LIGHTING_DIFFUSE:
s->features |= MF_NORMALS; s->features |= MF_NORMALS;
break; break;
case RGB_GEN_VERTEX: case RGB_GEN_VERTEX_LIGHTING:
case RGB_GEN_ONE_MINUS_VERTEX: case RGB_GEN_ONE_MINUS_VERTEX:
case RGB_GEN_EXACT_VERTEX: case RGB_GEN_VERTEX_EXACT:
s->features |= MF_COLORS; s->features |= MF_COLORS;
break; break;
default: default:
@ -3488,7 +3625,7 @@ void Shader_Finish (shader_t *s)
/*or if its purely a skybox and has missing textures*/ /*or if its purely a skybox and has missing textures*/
if (!s->numpasses) if (!s->numpasses)
for (i = 0; i < 6; i++) for (i = 0; i < 6; i++)
if (missing_texture.num == s->skydome->farbox_textures[i].num) if (missing_texture.ref == s->skydome->farbox_textures[i].ref)
s->flags = 0; s->flags = 0;
if (!(s->flags & SHADER_SKY)) if (!(s->flags & SHADER_SKY))
{ {
@ -3521,7 +3658,7 @@ void Shader_Finish (shader_t *s)
else else
{ {
pass->texgen = T_GEN_SINGLEMAP; pass->texgen = T_GEN_SINGLEMAP;
pass->anim_frames[0] = R_LoadHiResTexture(s->name, NULL, IF_NOALPHA); TEXASSIGN(pass->anim_frames[0], R_LoadHiResTexture(s->name, NULL, IF_NOALPHA));
if (!TEXVALID(pass->anim_frames[0])) if (!TEXVALID(pass->anim_frames[0]))
{ {
Con_Printf("Shader %s failed to load default texture\n", s->name); Con_Printf("Shader %s failed to load default texture\n", s->name);
@ -3530,7 +3667,7 @@ void Shader_Finish (shader_t *s)
Con_Printf("Shader %s with no passes and no surfaceparm nodraw, inserting pass\n", s->name); Con_Printf("Shader %s with no passes and no surfaceparm nodraw, inserting pass\n", s->name);
} }
pass->shaderbits |= SBITS_MISC_DEPTHWRITE; pass->shaderbits |= SBITS_MISC_DEPTHWRITE;
pass->rgbgen = RGB_GEN_VERTEX; pass->rgbgen = RGB_GEN_VERTEX_LIGHTING;
pass->alphagen = ALPHA_GEN_IDENTITY; pass->alphagen = ALPHA_GEN_IDENTITY;
pass->numMergedPasses = 1; pass->numMergedPasses = 1;
Shader_SetBlendmode(pass); Shader_SetBlendmode(pass);
@ -3576,7 +3713,7 @@ void Shader_Finish (shader_t *s)
pass = s->passes; pass = s->passes;
for (i = 0; i < s->numpasses; i++, pass++) for (i = 0; i < s->numpasses; i++, pass++)
{ {
if (pass->rgbgen == RGB_GEN_VERTEX) if (pass->rgbgen == RGB_GEN_VERTEX_LIGHTING)
break; break;
} }
@ -3628,7 +3765,7 @@ void Shader_Finish (shader_t *s)
memcpy ( &s->passes[0], pass, sizeof(shaderpass_t) ); memcpy ( &s->passes[0], pass, sizeof(shaderpass_t) );
} }
s->passes[0].rgbgen = RGB_GEN_VERTEX; s->passes[0].rgbgen = RGB_GEN_VERTEX_LIGHTING;
s->passes[0].alphagen = ALPHA_GEN_IDENTITY; s->passes[0].alphagen = ALPHA_GEN_IDENTITY;
s->passes[0].blendmode = 0; s->passes[0].blendmode = 0;
s->passes[0].flags &= ~(SHADER_PASS_ANIMMAP|SHADER_PASS_NOCOLORARRAY); s->passes[0].flags &= ~(SHADER_PASS_ANIMMAP|SHADER_PASS_NOCOLORARRAY);
@ -3666,7 +3803,9 @@ done:;
if (pass->rgbgen == RGB_GEN_UNKNOWN) if (pass->rgbgen == RGB_GEN_UNKNOWN)
{ {
if (!s->fog_dist && !(pass->flags & SHADER_PASS_LIGHTMAP)) if ( (pass->shaderbits & SBITS_SRCBLEND_BITS) == 0
|| (pass->shaderbits & SBITS_SRCBLEND_BITS) == SBITS_SRCBLEND_ONE
|| (pass->shaderbits & SBITS_SRCBLEND_BITS) == SBITS_SRCBLEND_SRC_ALPHA)
pass->rgbgen = RGB_GEN_IDENTITY_LIGHTING; pass->rgbgen = RGB_GEN_IDENTITY_LIGHTING;
else else
pass->rgbgen = RGB_GEN_IDENTITY; pass->rgbgen = RGB_GEN_IDENTITY;
@ -3804,8 +3943,6 @@ void Shader_UpdateRegistration (void)
void R_BuildDefaultTexnums(texnums_t *tn, shader_t *shader) void R_BuildDefaultTexnums(texnums_t *tn, shader_t *shader)
{ {
extern cvar_t gl_bump;
/*dlights/realtime lighting needs some stuff*/ /*dlights/realtime lighting needs some stuff*/
if (!TEXVALID(tn->base)) if (!TEXVALID(tn->base))
{ {
@ -3814,7 +3951,7 @@ void R_BuildDefaultTexnums(texnums_t *tn, shader_t *shader)
if (TEXVALID(tn->base)) if (TEXVALID(tn->base))
shader->flags &= ~SHADER_NOIMAGE; shader->flags &= ~SHADER_NOIMAGE;
if (gl_bump.ival) if (r_loadbumpmapping)
{ {
if (!TEXVALID(tn->bump)) if (!TEXVALID(tn->bump))
tn->bump = R_LoadHiResTexture(va("%s_norm", shader->name), NULL, IF_NOALPHA); tn->bump = R_LoadHiResTexture(va("%s_norm", shader->name), NULL, IF_NOALPHA);
@ -3832,7 +3969,12 @@ void R_BuildDefaultTexnums(texnums_t *tn, shader_t *shader)
tn->upperoverlay = R_LoadHiResTexture(va("%s_shirt", shader->name), NULL, 0); tn->upperoverlay = R_LoadHiResTexture(va("%s_shirt", shader->name), NULL, 0);
} }
shader->defaulttextures = *tn; TEXASSIGN(shader->defaulttextures.base, tn->base);
TEXASSIGN(shader->defaulttextures.specular, tn->specular);
TEXASSIGN(shader->defaulttextures.fullbright, tn->fullbright);
TEXASSIGN(shader->defaulttextures.bump, tn->bump);
TEXASSIGN(shader->defaulttextures.loweroverlay, tn->loweroverlay);
TEXASSIGN(shader->defaulttextures.upperoverlay, tn->upperoverlay);
} }
void Shader_DefaultScript(char *shortname, shader_t *s, const void *args) void Shader_DefaultScript(char *shortname, shader_t *s, const void *args)
@ -3936,7 +4078,7 @@ void Shader_DefaultBSPLM(char *shortname, shader_t *s, const void *args)
"{\n" "{\n"
"map $diffuse\n" "map $diffuse\n"
"tcgen base\n" "tcgen base\n"
"if gl_bump\n" "if $deluxmap\n"
"[\n" "[\n"
"blendfunc gl_one gl_zero\n" "blendfunc gl_one gl_zero\n"
"]\n" "]\n"
@ -4268,7 +4410,7 @@ void Shader_DefaultBSPVertex(char *shortname, shader_t *s, const void *args)
pass->tcgen = TC_GEN_BASE; pass->tcgen = TC_GEN_BASE;
pass->anim_frames[0] = R_LoadHiResTexture(shortname, NULL, 0); pass->anim_frames[0] = R_LoadHiResTexture(shortname, NULL, 0);
pass->shaderbits |= SBITS_MISC_DEPTHWRITE; pass->shaderbits |= SBITS_MISC_DEPTHWRITE;
pass->rgbgen = RGB_GEN_VERTEX; pass->rgbgen = RGB_GEN_VERTEX_LIGHTING;
pass->alphagen = ALPHA_GEN_IDENTITY; pass->alphagen = ALPHA_GEN_IDENTITY;
pass->numMergedPasses = 1; pass->numMergedPasses = 1;
Shader_SetBlendmode(pass); Shader_SetBlendmode(pass);
@ -4293,7 +4435,7 @@ void Shader_DefaultBSPFlare(char *shortname, shader_t *s, const void *args)
pass->flags = SHADER_PASS_NOCOLORARRAY; pass->flags = SHADER_PASS_NOCOLORARRAY;
pass->shaderbits |= SBITS_SRCBLEND_ONE|SBITS_DSTBLEND_ONE; pass->shaderbits |= SBITS_SRCBLEND_ONE|SBITS_DSTBLEND_ONE;
pass->anim_frames[0] = R_LoadHiResTexture(shortname, NULL, 0); pass->anim_frames[0] = R_LoadHiResTexture(shortname, NULL, 0);
pass->rgbgen = RGB_GEN_VERTEX; pass->rgbgen = RGB_GEN_VERTEX_LIGHTING;
pass->alphagen = ALPHA_GEN_IDENTITY; pass->alphagen = ALPHA_GEN_IDENTITY;
pass->numtcmods = 0; pass->numtcmods = 0;
pass->tcgen = TC_GEN_BASE; pass->tcgen = TC_GEN_BASE;
@ -4322,9 +4464,7 @@ void Shader_DefaultSkin(char *shortname, shader_t *s, const void *args)
"if $lpp\n" "if $lpp\n"
"[\n" "[\n"
"program defaultskin\n" "program defaultskin\n"
"]\n" "][\n"
"else\n"
"[\n"
"program lpp_skin\n" "program lpp_skin\n"
"]\n" "]\n"
"{\n" "{\n"
@ -4382,11 +4522,11 @@ void Shader_Default2D(char *shortname, shader_t *s, const void *genargs)
"}\n" "}\n"
); );
s->defaulttextures.base = R_LoadHiResTexture(shortname, NULL, IF_NOPICMIP|IF_NOMIPMAP|IF_CLAMP); TEXASSIGN(s->defaulttextures.base, R_LoadHiResTexture(shortname, NULL, IF_NOPICMIP|IF_NOMIPMAP|IF_CLAMP));
if (!TEXVALID(s->defaulttextures.base)) if (!TEXVALID(s->defaulttextures.base))
{ {
unsigned char data[4*4] = {0}; unsigned char data[4*4] = {0};
s->defaulttextures.base = R_LoadTexture8("black", 4, 4, data, 0, 0); TEXASSIGN(s->defaulttextures.base, R_LoadTexture8("black", 4, 4, data, 0, 0));
s->flags |= SHADER_NOIMAGE; s->flags |= SHADER_NOIMAGE;
s->width = 64; s->width = 64;

View file

@ -1001,60 +1001,252 @@ static qboolean Sh_LeafInView(qbyte *lightvis, qbyte *vvis)
return false; return false;
} }
static void Sh_Scissor (int x, int y, int width, int height) typedef struct
{
int x;
int y;
int width;
int height;
double dmin;
double dmax;
} srect_t;
static void Sh_Scissor (srect_t r)
{ {
#if 0 //visible scissors #if 0 //visible scissors
glMatrixMode(GL_PROJECTION); extern cvar_t temp1;
glPushMatrix(); if (temp1.ival)
glLoadIdentity(); {
glOrtho (0, glwidth, glheight, 0, -99999, 99999); qglMatrixMode(GL_PROJECTION);
glMatrixMode(GL_MODELVIEW); qglPushMatrix();
glPushMatrix(); qglLoadIdentity();
glLoadIdentity(); qglOrtho (0, vid.pixelwidth, vid.pixelheight, 0, -99999, 99999);
// GL_Set2D(); qglMatrixMode(GL_MODELVIEW);
qglPushMatrix();
qglLoadIdentity();
// GL_Set2D();
glColor4f(1,1,1,1); qglColor4f(1,1,1,1);
glDisable(GL_DEPTH_TEST); qglDisable(GL_DEPTH_TEST);
glDisable(GL_SCISSOR_TEST); qglDisable(GL_SCISSOR_TEST);
glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE ); qglColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE );
glDisable(GL_TEXTURE_2D); qglDisable(GL_TEXTURE_2D);
GL_TexEnv(GL_REPLACE);
glBegin(GL_LINE_LOOP); qglBegin(GL_LINE_LOOP);
glVertex2f(x, y); qglVertex2f(r.x, vid.pixelheight - (r.y + r.height));
glVertex2f(x+glwidth, y); qglVertex2f(r.x+r.width, vid.pixelheight - (r.y + r.height));
glVertex2f(x+glwidth, y+glheight); qglVertex2f(r.x+r.width, vid.pixelheight - (r.y));
glVertex2f(x, y+glheight); qglVertex2f(r.x, vid.pixelheight - (r.y));
glEnd(); qglEnd();
glMatrixMode(GL_PROJECTION); qglColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE );
glPopMatrix();
glMatrixMode(GL_MODELVIEW); qglMatrixMode(GL_PROJECTION);
glPopMatrix(); qglPopMatrix();
qglMatrixMode(GL_MODELVIEW);
qglPopMatrix();
}
#endif #endif
qglScissor(x, vid.pixelheight - (y + height),width,height); qglScissor(r.x, r.y, r.width, r.height);
if (qglDepthBoundsEXT)
{
qglDepthBoundsEXT(r.dmin, r.dmax);
qglEnable(GL_DEPTH_BOUNDS_TEST_EXT);
}
} }
#if 0
static qboolean Sh_ScissorForSphere(vec3_t center, float radius, vrect_t *rect)
{
/*return false to say that its fully offscreen*/
float v[4], tempv[4];
extern cvar_t temp1;
int i;
vrect_t r;
radius *= temp1.value;
rect->x = 0;
rect->y = 0;
rect->width = vid.pixelwidth;
rect->height = vid.pixelheight;
/*
for (i = 0; i < 4; i++)
{
v[3] = 1;
VectorMA(center, radius, frustum[i].normal, v);
tempv[0] = r_refdef.m_view[0]*v[0] + r_refdef.m_view[4]*v[1] + r_refdef.m_view[8]*v[2] + r_refdef.m_view[12]*v[3];
tempv[1] = r_refdef.m_view[1]*v[0] + r_refdef.m_view[5]*v[1] + r_refdef.m_view[9]*v[2] + r_refdef.m_view[13]*v[3];
tempv[2] = r_refdef.m_view[2]*v[0] + r_refdef.m_view[6]*v[1] + r_refdef.m_view[10]*v[2] + r_refdef.m_view[14]*v[3];
tempv[3] = r_refdef.m_view[3]*v[0] + r_refdef.m_view[7]*v[1] + r_refdef.m_view[11]*v[2] + r_refdef.m_view[15]*v[3];
product[0] = r_refdef.m_projection[0]*tempv[0] + r_refdef.m_projection[4]*tempv[1] + r_refdef.m_projection[8]*tempv[2] + r_refdef.m_projection[12]*tempv[3];
product[1] = r_refdef.m_projection[1]*tempv[0] + r_refdef.m_projection[5]*tempv[1] + r_refdef.m_projection[9]*tempv[2] + r_refdef.m_projection[13]*tempv[3];
product[2] = r_refdef.m_projection[2]*tempv[0] + r_refdef.m_projection[6]*tempv[1] + r_refdef.m_projection[10]*tempv[2] + r_refdef.m_projection[14]*tempv[3];
product[3] = r_refdef.m_projection[3]*tempv[0] + r_refdef.m_projection[7]*tempv[1] + r_refdef.m_projection[11]*tempv[2] + r_refdef.m_projection[15]*tempv[3];
v[0] /= v[3];
v[1] /= v[3];
v[2] /= v[3];
out[0] = (1+v[0])/2;
out[1] = (1+v[1])/2;
out[2] = (1+v[2])/2;
r.x
}
*/
return false;
}
#endif
#define BoxesOverlap(a,b,c,d) ((a)[0] <= (d)[0] && (b)[0] >= (c)[0] && (a)[1] <= (d)[1] && (b)[1] >= (c)[1] && (a)[2] <= (d)[2] && (b)[2] >= (c)[2]) #define BoxesOverlap(a,b,c,d) ((a)[0] <= (d)[0] && (b)[0] >= (c)[0] && (a)[1] <= (d)[1] && (b)[1] >= (c)[1] && (a)[2] <= (d)[2] && (b)[2] >= (c)[2])
static qboolean Sh_ScissorForBox(vec3_t mins, vec3_t maxs) static qboolean Sh_ScissorForBox(vec3_t mins, vec3_t maxs, srect_t *r)
{
static const edge[12][2] =
{
{0, 1}, {0, 2}, {1, 3}, {2, 3},
{4, 5}, {4, 6}, {5, 7}, {6, 7},
{0, 4}, {1, 5}, {2, 6}, {3, 7}
};
//the box is a simple cube.
//clip each vert to the near clip plane
//insert a replacement vertex for edges that cross the nearclip plane where it crosses
//calc the scissor rect from projecting the verts that survived, plus the clipped edge ones.
float ncpdist;
float dist[8];
int sign[8];
vec4_t vert[20];
vec3_t p[8];
int numverts = 0, i, v1, v2;
vec4_t v,tv;
float frac;
float x,x1,x2,y,y1,y2;
double z, z1, z2;
extern cvar_t gl_mindist;
r->x = 0;
r->y = 0;
r->width = vid.pixelwidth;
r->height = vid.pixelheight;
r->dmin = 0;
r->dmax = 1;
if (0)//!r_shadow_scissor.integer)
{
return false;
}
/*if view is inside the box, then skip this maths*/
// if (BoxesOverlap(r_refdef.vieworg, r_refdef.vieworg, mins, maxs))
// {
// return false;
// }
ncpdist = DotProduct(r_refdef.vieworg, vpn) + gl_mindist.value;
for (i = 0; i < 8; i++)
{
p[i][0] = (i & 1) ? mins[0] : maxs[0];
p[i][1] = (i & 2) ? mins[1] : maxs[1];
p[i][2] = (i & 4) ? mins[2] : maxs[2];
dist[i] = ncpdist - DotProduct(p[i], vpn);
sign[i] = (dist[i] > 0);
if (!sign[i])
{
VectorCopy(p[i], vert[numverts]);
numverts++;
}
}
/*fully clipped by near plane*/
if (!numverts)
return true;
if (numverts != 8)
{
/*crosses near clip plane somewhere*/
for (i = 0; i < 12; i++)
{
v1 = edge[i][0];
v2 = edge[i][1];
if (sign[v1] != sign[v2])
{
frac = dist[v1] / (dist[v1] - dist[v2]);
VectorInterpolate(p[v1], frac, p[v2], vert[numverts]);
numverts++;
}
}
}
x1 = y1 = z1 = 1;
x2 = y2 = z2 = -1;
/*transform each vert to get the screen pos*/
for (i = 0; i < numverts; i++)
{
vert[i][3] = 1;
Matrix4x4_CM_Transform4(r_refdef.m_view, vert[i], tv);
Matrix4x4_CM_Transform4(r_refdef.m_projection, tv, v);
x = v[0] / v[3];
y = v[1] / v[3];
z = (double)v[2] / v[3];
if (x < x1) x1 = x;
if (x > x2) x2 = x;
if (y < y1) y1 = y;
if (y > y2) y2 = y;
if (z < z1) z1 = z;
if (z > z2) z2 = z;
}
x1 = ((1+x1) * r_refdef.vrect.width * vid.pixelwidth) / (vid.width * 2);
x2 = ((1+x2) * r_refdef.vrect.width * vid.pixelwidth) / (vid.width * 2);
y1 = ((1+y1) * r_refdef.vrect.height * vid.pixelheight) / (vid.height * 2);
y2 = ((1+y2) * r_refdef.vrect.height * vid.pixelheight) / (vid.height * 2);
z1 = (1+z1) / 2;
z2 = (1+z2) / 2;
if (x1 < 0)
x1 = 0;
if (y1 < 0)
y1 = 0;
if (x2 < 0)
x2 = 0;
if (y1 > r_refdef.vrect.height * vid.pixelheight / vid.height)
y1 = r_refdef.vrect.height * vid.pixelheight / vid.height;
if (y2 > r_refdef.vrect.height * vid.pixelheight / vid.height)
y2 = r_refdef.vrect.height * vid.pixelheight / vid.height;
r->x = floor(x1);
r->y = floor(y1);
r->width = ceil(x2) - r->x;
r->height = ceil(y2) - r->y;
r->x += r_refdef.vrect.x;
r->y += r_refdef.vrect.y;
r->dmin = z1;
r->dmax = z2;
return false;
}
#if 0
static qboolean Sh_ScissorForBox(vec3_t mins, vec3_t maxs, vrect_t *r)
{ {
int i, ix1, iy1, ix2, iy2; int i, ix1, iy1, ix2, iy2;
float x1, y1, x2, y2, x, y, f; float x1, y1, x2, y2, x, y, f;
vec3_t smins, smaxs; vec3_t smins, smaxs;
vec4_t v, v2; vec4_t v, v2;
int r_view_x = 0;
int r_view_y = 0; r->x = 0;
int r_view_width = vid.pixelwidth; r->y = 0;
int r_view_height = vid.pixelheight; r->width = vid.pixelwidth;
r->height = vid.pixelheight;
if (0)//!r_shadow_scissor.integer) if (0)//!r_shadow_scissor.integer)
{ {
Sh_Scissor(r_view_x, r_view_y, r_view_width, r_view_height);
return false; return false;
} }
// if view is inside the box, just say yes it's visible // if view is inside the box, just say yes it's fully visible
if (BoxesOverlap(r_refdef.vieworg, r_refdef.vieworg, mins, maxs)) if (BoxesOverlap(r_refdef.vieworg, r_refdef.vieworg, mins, maxs))
{ {
Sh_Scissor(r_view_x, r_view_y, r_view_width, r_view_height);
return false; return false;
} }
for (i = 0;i < 3;i++) for (i = 0;i < 3;i++)
@ -1070,11 +1262,10 @@ static qboolean Sh_ScissorForBox(vec3_t mins, vec3_t maxs)
v2[i] = mins[i]; v2[i] = mins[i];
} }
} }
f = DotProduct(vpn, r_refdef.vieworg) + 1; f = DotProduct(vpn, r_refdef.vieworg);
if (DotProduct(vpn, v2) <= f) if (DotProduct(vpn, v2) <= f)
{ {
// entirely behind nearclip plane // entirely behind nearclip plane, entirely obscured
Sh_Scissor(r_view_x, r_view_y, r_view_width, r_view_height);
return true; return true;
} }
if (DotProduct(vpn, v) >= f) if (DotProduct(vpn, v) >= f)
@ -1088,8 +1279,8 @@ static qboolean Sh_ScissorForBox(vec3_t mins, vec3_t maxs)
v[2] = (i & 4) ? mins[2] : maxs[2]; v[2] = (i & 4) ? mins[2] : maxs[2];
v[3] = 1.0f; v[3] = 1.0f;
Matrix4x4_CM_Project(v, v2, r_refdef.viewangles, r_refdef.vieworg, r_refdef.fov_x, r_refdef.fov_y); Matrix4x4_CM_Project(v, v2, r_refdef.viewangles, r_refdef.vieworg, r_refdef.fov_x, r_refdef.fov_y);
v2[0]*=r_view_width; v2[0]*=vid.pixelwidth;
v2[1]*=r_view_height; v2[1]*=vid.pixelheight;
// GL_TransformToScreen(v, v2); // GL_TransformToScreen(v, v2);
//Con_Printf("%.3f %.3f %.3f %.3f transformed to %.3f %.3f %.3f %.3f\n", v[0], v[1], v[2], v[3], v2[0], v2[1], v2[2], v2[3]); //Con_Printf("%.3f %.3f %.3f %.3f transformed to %.3f %.3f %.3f %.3f\n", v[0], v[1], v[2], v[3], v2[0], v2[1], v2[2], v2[3]);
x = v2[0]; x = v2[0];
@ -1160,8 +1351,8 @@ static qboolean Sh_ScissorForBox(vec3_t mins, vec3_t maxs)
v[2] = v2[0] * vright[2] + v2[1] * vup[2] + v2[2] * vpn[2] + r_refdef.vieworg[2]; v[2] = v2[0] * vright[2] + v2[1] * vup[2] + v2[2] * vpn[2] + r_refdef.vieworg[2];
v[3] = 1.0f; v[3] = 1.0f;
Matrix4x4_CM_Project(v, v2, r_refdef.viewangles, r_refdef.vieworg, r_refdef.fov_x, r_refdef.fov_y); Matrix4x4_CM_Project(v, v2, r_refdef.viewangles, r_refdef.vieworg, r_refdef.fov_x, r_refdef.fov_y);
v2[0]*=r_view_width; v2[0]*=vid.pixelwidth;
v2[1]*=r_view_height; v2[1]*=vid.pixelheight;
//Con_Printf("%.3f %.3f %.3f %.3f transformed to %.3f %.3f %.3f %.3f\n", v[0], v[1], v[2], v[3], v2[0], v2[1], v2[2], v2[3]); //Con_Printf("%.3f %.3f %.3f %.3f transformed to %.3f %.3f %.3f %.3f\n", v[0], v[1], v[2], v[3], v2[0], v2[1], v2[2], v2[3]);
x = v2[0]; x = v2[0];
y = v2[1]; y = v2[1];
@ -1189,8 +1380,8 @@ static qboolean Sh_ScissorForBox(vec3_t mins, vec3_t maxs)
v[2] = (i & 4) ? mins[2] : maxs[2]; v[2] = (i & 4) ? mins[2] : maxs[2];
v[3] = 1.0f; v[3] = 1.0f;
Matrix4x4_CM_Project(v, v2, r_refdef.viewangles, r_refdef.vieworg, r_refdef.fov_x, r_refdef.fov_y); Matrix4x4_CM_Project(v, v2, r_refdef.viewangles, r_refdef.vieworg, r_refdef.fov_x, r_refdef.fov_y);
v2[0]*=r_view_width; v2[0]*=vid.pixelwidth;
v2[1]*=r_view_height; v2[1]*=vid.pixelheight;
//Con_Printf("%.3f %.3f %.3f %.3f transformed to %.3f %.3f %.3f %.3f\n", v[0], v[1], v[2], v[3], v2[0], v2[1], v2[2], v2[3]); //Con_Printf("%.3f %.3f %.3f %.3f transformed to %.3f %.3f %.3f %.3f\n", v[0], v[1], v[2], v[3], v2[0], v2[1], v2[2], v2[3]);
if (v2[2] > 0) if (v2[2] > 0)
{ {
@ -1210,17 +1401,21 @@ static qboolean Sh_ScissorForBox(vec3_t mins, vec3_t maxs)
ix2 = x2 + 1.0f; ix2 = x2 + 1.0f;
iy2 = y2 + 1.0f; iy2 = y2 + 1.0f;
//Con_Printf("%f %f %f %f\n", x1, y1, x2, y2); //Con_Printf("%f %f %f %f\n", x1, y1, x2, y2);
if (ix1 < r_view_x) ix1 = r_view_x; if (ix1 < r->x) ix1 = r->x;
if (iy1 < r_view_y) iy1 = r_view_y; if (iy1 < r->y) iy1 = r->y;
if (ix2 > r_view_x + r_view_width) ix2 = r_view_x + r_view_width; if (ix2 > r->x + r->width) ix2 = r->x + r->width;
if (iy2 > r_view_y + r_view_height) iy2 = r_view_y + r_view_height; if (iy2 > r->y + r->height) iy2 = r->y + r->height;
if (ix2 <= ix1 || iy2 <= iy1) if (ix2 <= ix1 || iy2 <= iy1)
return true; return true;
// set up the scissor rectangle // set up the scissor rectangle
qglScissor(ix1, iy1, ix2 - ix1, iy2 - iy1);
// qglEnable(GL_SCISSOR_TEST); r->x = ix1;
r->y = iy1;
r->width = ix2 - ix1;
r->height = iy2 - iy1;
return false; return false;
} }
#endif
void GL_BeginRenderBuffer_DepthOnly(texid_t depthtexture) void GL_BeginRenderBuffer_DepthOnly(texid_t depthtexture)
@ -1376,7 +1571,7 @@ void Sh_GenShadowMap (dlight_t *l, qbyte *lvis)
if (!TEXVALID(l->stexture)) if (!TEXVALID(l->stexture))
{ {
l->stexture = GL_AllocNewTexture(smsize, smsize); l->stexture = GL_AllocNewTexture("***shadowmap***", smsize, smsize);
GL_MTBind(0, GL_TEXTURE_2D, l->stexture); GL_MTBind(0, GL_TEXTURE_2D, l->stexture);
qglTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32_ARB, smsize, smsize, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL); qglTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32_ARB, smsize, smsize, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL);
@ -1453,6 +1648,7 @@ static void Sh_DrawShadowMapLight(dlight_t *l, vec3_t colour, qbyte *vvis)
vec3_t mins, maxs; vec3_t mins, maxs;
qbyte *lvis; qbyte *lvis;
qbyte lvisb[MAX_MAP_LEAFS/8]; qbyte lvisb[MAX_MAP_LEAFS/8];
srect_t rect;
if (R_CullSphere(l->origin, l->radius)) if (R_CullSphere(l->origin, l->radius))
{ {
@ -1468,7 +1664,7 @@ static void Sh_DrawShadowMapLight(dlight_t *l, vec3_t colour, qbyte *vvis)
maxs[1] = l->origin[1] + l->radius; maxs[1] = l->origin[1] + l->radius;
maxs[2] = l->origin[2] + l->radius; maxs[2] = l->origin[2] + l->radius;
if (Sh_ScissorForBox(mins, maxs)) if (Sh_ScissorForBox(mins, maxs, &rect))
{ {
bench.numscissorculled++; bench.numscissorculled++;
return; return;
@ -1528,6 +1724,9 @@ static void Sh_DrawShadowMapLight(dlight_t *l, vec3_t colour, qbyte *vvis)
bench.numlights++; bench.numlights++;
Sh_Scissor(rect);
qglEnable(GL_STENCIL_TEST);
qglMatrixMode(GL_TEXTURE); qglMatrixMode(GL_TEXTURE);
GL_MTBind(7, GL_TEXTURE_2D, l->stexture); GL_MTBind(7, GL_TEXTURE_2D, l->stexture);
@ -1542,7 +1741,7 @@ static void Sh_DrawShadowMapLight(dlight_t *l, vec3_t colour, qbyte *vvis)
ve = 0; ve = 0;
BE_SelectDLight(l, colour); GLBE_SelectDLight(l, colour);
BE_SelectMode(l->fov?BEM_SMAPLIGHTSPOT:BEM_SMAPLIGHT); BE_SelectMode(l->fov?BEM_SMAPLIGHTSPOT:BEM_SMAPLIGHT);
Sh_DrawEntLighting(l, colour); Sh_DrawEntLighting(l, colour);
@ -1618,8 +1817,8 @@ static void Sh_DrawEntLighting(dlight_t *light, vec3_t colour)
#define PROJECTION_DISTANCE (float)(dl->radius*2)//0x7fffffff #define PROJECTION_DISTANCE (float)(dl->radius*2)//0x7fffffff
/*Fixme: this is brute forced*/ /*Fixme: this is brute forced*/
#ifdef _MSC_VER #ifdef warningmsg
#pragma message("brush shadows are bruteforced") #pragma warningmsg("brush shadows are bruteforced")
#endif #endif
static void Sh_DrawBrushModelShadow(dlight_t *dl, entity_t *e) static void Sh_DrawBrushModelShadow(dlight_t *dl, entity_t *e)
{ {
@ -1801,6 +2000,7 @@ static qboolean Sh_DrawStencilLight(dlight_t *dl, vec3_t colour, qbyte *vvis)
int sincrw; int sincrw;
int leaf; int leaf;
qbyte *lvis; qbyte *lvis;
srect_t rect;
qbyte lvisb[MAX_MAP_LEAFS/8]; qbyte lvisb[MAX_MAP_LEAFS/8];
@ -1844,19 +2044,20 @@ static qboolean Sh_DrawStencilLight(dlight_t *dl, vec3_t colour, qbyte *vvis)
} }
//sets up the gl scissor (and culls to view) //sets up the gl scissor (and culls to view)
if (Sh_ScissorForBox(mins, maxs)) if (Sh_ScissorForBox(mins, maxs, &rect))
{ {
bench.numscissorculled++; bench.numscissorculled++;
return false; //this doesn't cull often. return false; //this doesn't cull often.
} }
bench.numlights++; bench.numlights++;
BE_SelectDLight(dl, colour); GLBE_SelectDLight(dl, colour);
BE_SelectMode(BEM_STENCIL); BE_SelectMode(BEM_STENCIL);
//The backend doesn't maintain scissor state. //The backend doesn't maintain scissor state.
//qglEnable(GL_SCISSOR_TEST);
//The backend doesn't maintain stencil test state either - it needs to be active for more than just stencils, or disabled. its awkward. //The backend doesn't maintain stencil test state either - it needs to be active for more than just stencils, or disabled. its awkward.
Sh_Scissor(rect);
qglEnable(GL_SCISSOR_TEST);
qglEnable(GL_STENCIL_TEST); qglEnable(GL_STENCIL_TEST);
//FIXME: is it practical to test to see if scissors allow not clearing the stencil buffer? //FIXME: is it practical to test to see if scissors allow not clearing the stencil buffer?
@ -1998,6 +2199,7 @@ static qboolean Sh_DrawStencilLight(dlight_t *dl, vec3_t colour, qbyte *vvis)
static void Sh_DrawShadowlessLight(dlight_t *dl, vec3_t colour, qbyte *vvis) static void Sh_DrawShadowlessLight(dlight_t *dl, vec3_t colour, qbyte *vvis)
{ {
vec3_t mins, maxs; vec3_t mins, maxs;
srect_t rect;
if (R_CullSphere(dl->origin, dl->radius)) if (R_CullSphere(dl->origin, dl->radius))
{ {
@ -2041,16 +2243,19 @@ static void Sh_DrawShadowlessLight(dlight_t *dl, vec3_t colour, qbyte *vvis)
maxs[2] = dl->origin[2] + dl->radius; maxs[2] = dl->origin[2] + dl->radius;
//sets up the gl scissor (and culls to view) //sets up the gl scissor (actually just culls to view)
if (Sh_ScissorForBox(mins, maxs)) if (Sh_ScissorForBox(mins, maxs, &rect))
{ {
bench.numscissorculled++; bench.numscissorculled++;
return; //was culled. return; //was culled.
} }
qglDisable(GL_SCISSOR_TEST);
if (qglDepthBoundsEXT)
qglDisable(GL_DEPTH_BOUNDS_TEST_EXT);
bench.numlights++; bench.numlights++;
BE_SelectDLight(dl, colour); GLBE_SelectDLight(dl, colour);
BE_SelectMode(BEM_LIGHT); BE_SelectMode(BEM_LIGHT);
Sh_DrawEntLighting(dl, colour); Sh_DrawEntLighting(dl, colour);
} }
@ -2142,6 +2347,8 @@ void Sh_DrawLights(qbyte *vis)
} }
qglDisable(GL_SCISSOR_TEST); qglDisable(GL_SCISSOR_TEST);
if (qglDepthBoundsEXT)
qglDisable(GL_DEPTH_BOUNDS_TEST_EXT);
BE_SelectMode(BEM_STANDARD); BE_SelectMode(BEM_STANDARD);
// if (developer.value) // if (developer.value)

View file

@ -191,12 +191,11 @@ FTEPFNGLACTIVESTENCILFACEEXTPROC qglActiveStencilFaceEXT;
//quick hack that made quake work on both 1 and 1.1 gl implementations. //quick hack that made quake work on both 1 and 1.1 gl implementations.
BINDTEXFUNCPTR bindTexFunc; BINDTEXFUNCPTR bindTexFunc;
#define GLchar char
#if defined(_DEBUG) && !defined(DEBUG) #if defined(_DEBUG) && !defined(DEBUG)
#define DEBUG #define DEBUG
#endif #endif
#if defined(DEBUG) #if defined(DEBUG)
#define GLchar char
typedef void (APIENTRY *GLDEBUGPROCAMD)(GLuint id, typedef void (APIENTRY *GLDEBUGPROCAMD)(GLuint id,
GLenum category, GLenum category,
GLenum severity, GLenum severity,
@ -279,7 +278,6 @@ void (APIENTRY myGLDEBUGPROCAMD)(GLuint id,
int gl_mtexarbable=0; //max texture units int gl_mtexarbable=0; //max texture units
qboolean gl_mtexable = false; qboolean gl_mtexable = false;
int gl_bumpmappingpossible;
qboolean gammaworks; //if the gl drivers can set proper gamma. qboolean gammaworks; //if the gl drivers can set proper gamma.
@ -318,18 +316,6 @@ qboolean GL_CheckExtension(char *extname)
return !!strstr(gl_extensions, extname); return !!strstr(gl_extensions, extname);
} }
texid_t GL_AllocNewTexture(int w, int h)
{
texid_t r;
qglGenTextures(1, &r.num);
return r;
}
void GL_DestroyTexture(texid_t tex)
{
qglDeleteTextures(1, &tex.num);
}
void APIENTRY GL_DrawRangeElementsEmul(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices) void APIENTRY GL_DrawRangeElementsEmul(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices)
{ {
qglDrawElements(mode, count, type, indices); qglDrawElements(mode, count, type, indices);
@ -346,8 +332,6 @@ void APIENTRY GL_ClientStateStub(GLenum array)
#define getglext(name) getglfunction(name) #define getglext(name) getglfunction(name)
void GL_CheckExtensions (void *(*getglfunction) (char *name), float ver) void GL_CheckExtensions (void *(*getglfunction) (char *name), float ver)
{ {
extern cvar_t gl_bump;
memset(&gl_config, 0, sizeof(gl_config)); memset(&gl_config, 0, sizeof(gl_config));
gl_config.glversion = ver; gl_config.glversion = ver;
@ -397,9 +381,6 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name), float ver)
mtexid0 = 0; mtexid0 = 0;
mtexid1 = 0; mtexid1 = 0;
//none of them bumpmapping possibilities.
gl_bumpmappingpossible = false;
//no GL_ATI_separate_stencil //no GL_ATI_separate_stencil
qglStencilOpSeparateATI = NULL; qglStencilOpSeparateATI = NULL;
@ -528,6 +509,13 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name), float ver)
gl_config.arb_texture_compression = true; gl_config.arb_texture_compression = true;
} }
if (GL_CheckExtension("GL_EXT_depth_bounds_test"))
qglDepthBoundsEXT = (void *)getglext("glDepthBoundsEXT");
else if (GL_CheckExtension("GL_NV_depth_bounds_test"))
qglDepthBoundsEXT = (void *)getglext("glDepthBoundsNV");
else
qglDepthBoundsEXT = NULL;
if (GL_CheckExtension("GL_ATI_pn_triangles")) if (GL_CheckExtension("GL_ATI_pn_triangles"))
{ {
qglPNTrianglesfATI = (void *)getglext("glPNTrianglesfATI"); qglPNTrianglesfATI = (void *)getglext("glPNTrianglesfATI");
@ -556,9 +544,6 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name), float ver)
gl_config.arb_texture_cube_map = GL_CheckExtension("GL_ARB_texture_cube_map"); gl_config.arb_texture_cube_map = GL_CheckExtension("GL_ARB_texture_cube_map");
if (gl_mtexarbable && gl_config.arb_texture_cube_map && gl_config.arb_texture_env_combine && gl_config.arb_texture_env_dot3 && !COM_CheckParm("-nobump") && gl_bump.value)
gl_bumpmappingpossible = true;
/*vbos*/ /*vbos*/
if (GL_CheckExtension("GL_ARB_vertex_buffer_object")) if (GL_CheckExtension("GL_ARB_vertex_buffer_object"))
{ {
@ -574,7 +559,7 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name), float ver)
// glslang // glslang
//the gf2 to gf4 cards emulate vertex_shader and thus supports shader_objects. //the gf2 to gf4 cards emulate vertex_shader and thus supports shader_objects.
//but our code kinda requires both for clean workings. //but our code kinda requires both for clean workings.
if (gl_config.glversion >= 2) if (gl_config.glversion >= 2)// && (gl_config.gles || 0))
{ {
/*core names are different from extension names (more functions too)*/ /*core names are different from extension names (more functions too)*/
gl_config.arb_shader_objects = true; gl_config.arb_shader_objects = true;
@ -680,87 +665,237 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name), float ver)
#endif #endif
} }
static const char *glsl_hdrs[] =
{
"sys/skeletal.h",
"attribute vec3 v_normal;\n"
"attribute vec3 v_svector;\n"
"attribute vec3 v_tvector;\n"
"#ifdef SKELETAL\n"
"attribute vec4 v_bone;"
"attribute vec4 v_weight;"
"uniform mat3x4 m_bones["STRINGIFY(MAX_BONES)"];\n"
"vec4 skeletaltransform()"
"{"
"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);"
"}\n"
"vec4 skeletaltransform_nst(out vec3 n, out vec3 t, out vec3 b)"
"{"
"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, 1.0) * wmat;"
"t = vec4(v_svector.xyz, 1.0) * wmat;"
"b = vec4(v_tvector.xyz, 1.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;\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, 1.0) * wmat;"
"t = vec4(v_svector.xyz, 1.0) * wmat;"
"b = vec4(v_tvector.xyz, 1.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;\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, 1.0) * wmat;"
"return m_modelviewprojection * vec4(vec4(v_position.xyz, 1.0) * wmat, 1.0);"
"}\n"
"#else\n"
"#define skeletaltransform() ftetransform()\n"
"vec4 skeletaltransform_wnst(out vec3 w, out vec3 n, out vec3 t, out vec3 b)"
"{"
"n = v_normal;"
"t = v_svector;"
"b = v_tvector;"
"w = v_position.xyz;"
"return ftetransform();"
"}\n"
"vec4 skeletaltransform_nst(out vec3 n, out vec3 t, out vec3 b)"
"{"
"n = v_normal;"
"t = v_svector;"
"b = v_tvector;"
"return ftetransform();"
"}\n"
"vec4 skeletaltransform_n(out vec3 n)"
"{"
"n = v_normal;"
"return ftetransform();"
"}\n"
"#endif\n"
,
NULL
};
qboolean GLSlang_GenerateIncludes(int maxstrings, int *strings, const GLchar *prstrings[], GLint length[], const char *shadersource)
{
int i;
char *incline, *inc;
char incname[256];
while((incline=strstr(shadersource, "#include")))
{
if (*strings == maxstrings)
return false;
/*emit up to the include*/
prstrings[*strings] = shadersource;
length[*strings] = incline - shadersource;
*strings += 1;
incline += 8;
incline = COM_ParseOut (incline, incname, sizeof(incname));
for (i = 0; glsl_hdrs[i]; i += 2)
{
if (!strcmp(incname, glsl_hdrs[i]))
{
if (!GLSlang_GenerateIncludes(maxstrings, strings, prstrings, length, glsl_hdrs[i+1]))
return false;
break;
}
}
if (!glsl_hdrs[i])
{
if (FS_LoadFile(incname, &inc) >= 0)
{
if (!GLSlang_GenerateIncludes(maxstrings, strings, prstrings, length, inc))
{
FS_FreeFile(inc);
return false;
}
FS_FreeFile(inc);
}
}
/*move the pointer past the include*/
shadersource = incline;
}
if (*shadersource)
{
if (*strings == maxstrings)
return false;
/*dump the remaining shader string*/
prstrings[*strings] = shadersource;
length[*strings] = strlen(prstrings[*strings]);
*strings += 1;
}
return true;
}
// glslang helper api function definitions // glslang helper api function definitions
// type should be GL_FRAGMENT_SHADER_ARB or GL_VERTEX_SHADER_ARB // type should be GL_FRAGMENT_SHADER_ARB or GL_VERTEX_SHADER_ARB
GLhandleARB GLSlang_CreateShader (char *name, char *versionline, char **precompilerconstants, char *shadersource, GLenum shadertype) GLhandleARB GLSlang_CreateShader (char *name, int ver, char **precompilerconstants, const char *shadersource, GLenum shadertype)
{ {
GLhandleARB shader; GLhandleARB shader;
GLint compiled; GLint compiled;
char str[1024]; char str[1024];
int loglen, i; int loglen, i;
char *prstrings[6+16]; const GLchar *prstrings[64+16];
GLint length[sizeof(prstrings)/sizeof(prstrings[0])];
int strings = 0; int strings = 0;
if (versionline) if (ver)
prstrings[strings++] = versionline; {
prstrings[strings] = va("#version %u\n", ver);
length[strings] = strlen(prstrings[strings]);
strings++;
}
while(*precompilerconstants) while(*precompilerconstants)
prstrings[strings++] = *precompilerconstants++; {
prstrings[strings] = *precompilerconstants++;
length[strings] = strlen(prstrings[strings]);
strings++;
}
prstrings[strings] = "#define ENGINE_"DISTRIBUTION"\n";
length[strings] = strlen(prstrings[strings]);
strings++;
prstrings[strings++] = "#define ENGINE_"DISTRIBUTION"\n";
switch (shadertype) switch (shadertype)
{ {
case GL_FRAGMENT_SHADER_ARB: case GL_FRAGMENT_SHADER_ARB:
prstrings[strings++] = "#define FRAGMENT_SHADER\n"; prstrings[strings] = "#define FRAGMENT_SHADER\n";
length[strings] = strlen(prstrings[strings]);
strings++;
if (gl_config.gles) if (gl_config.gles)
{ {
prstrings[strings++] = "precision mediump float;\n"; prstrings[strings] = "precision mediump float;\n";
length[strings] = strlen(prstrings[strings]);
strings++;
} }
break; break;
case GL_VERTEX_SHADER_ARB: case GL_VERTEX_SHADER_ARB:
prstrings[strings++] = "#define VERTEX_SHADER\n"; prstrings[strings] = "#define VERTEX_SHADER\n";
length[strings] = strlen(prstrings[strings]);
strings++;
if (gl_config.gles) if (gl_config.gles)
{ {
prstrings[strings++] = prstrings[strings] =
"#ifdef GL_FRAGMENT_PRECISION_HIGH\n" "#ifdef GL_FRAGMENT_PRECISION_HIGH\n"
"precision highp float;\n" "precision highp float;\n"
"#else\n" "#else\n"
"precision mediump float;\n" "precision mediump float;\n"
"#endif\n"; "#endif\n"
;
length[strings] = strlen(prstrings[strings]);
strings++;
} }
if (gl_config.nofixedfunc) if (gl_config.nofixedfunc)
{ {
prstrings[strings++] = prstrings[strings] =
"attribute vec3 v_position;\n"
"#define ftetransform() (m_modelviewprojection * vec4(v_position, 1.0))\n" "#define ftetransform() (m_modelviewprojection * vec4(v_position, 1.0))\n"
"uniform mat4 m_modelviewprojection;\n" "uniform mat4 m_modelviewprojection;\n"
"attribute vec3 v_position;\n"; ;
length[strings] = strlen(prstrings[strings]);
strings++;
} }
else else
{ {
prstrings[strings++] = prstrings[strings] =
"#ifdef SKELETAL\n" "#define ftetransform ftransform\n"
"attribute vec4 v_bone;\n" "#define v_position gl_Vertex\n"
"attribute vec4 v_weight;\n" "uniform mat4 m_modelviewprojection;\n"
"uniform mat4 m_modelviewprojection;\n" ;
"uniform mat3x4 m_bones["STRINGIFY(MAX_BONES)"];\n" length[strings] = strlen(prstrings[strings]);
"attribute vec3 v_position;\n" strings++;
"vec4 skeletaltransform()\n"
"{"
" 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);\n"
"}\n"
"#define ftetransform() skeletaltransform()\n"
"#else\n"
"#define ftetransform() ftransform()\n"
"#define v_position gl_Vertex\n"
"#endif\n";
} }
break; break;
default: default:
prstrings[strings++] = "#define UNKNOWN_SHADER\n"; prstrings[strings] = "#define UNKNOWN_SHADER\n";
length[strings] = strlen(prstrings[strings]);
strings++;
break; break;
} }
prstrings[strings++] = shadersource;
GLSlang_GenerateIncludes(sizeof(prstrings)/sizeof(prstrings[0]), &strings, prstrings, length, shadersource);
shader = qglCreateShaderObjectARB(shadertype); shader = qglCreateShaderObjectARB(shadertype);
qglShaderSourceARB(shader, strings, (const GLcharARB**)prstrings, NULL); qglShaderSourceARB(shader, strings, prstrings, length);
qglCompileShaderARB(shader); qglCompileShaderARB(shader);
qglGetShaderParameteriv_(shader, GL_OBJECT_COMPILE_STATUS_ARB, &compiled); qglGetShaderParameteriv_(shader, GL_OBJECT_COMPILE_STATUS_ARB, &compiled);
@ -771,19 +906,28 @@ GLhandleARB GLSlang_CreateShader (char *name, char *versionline, char **precompi
switch (shadertype) switch (shadertype)
{ {
case GL_FRAGMENT_SHADER_ARB: case GL_FRAGMENT_SHADER_ARB:
Con_Printf("Fragment shader compilation error:\n----------\n%s\n----------\n", str); Con_Printf("Fragment shader (%s) compilation error:\n----------\n%s----------\n", name, str);
break; break;
case GL_VERTEX_SHADER_ARB: case GL_VERTEX_SHADER_ARB:
Con_Printf("Vertex shader compilation error:\n----------\n%s\n----------\n", str); Con_Printf("Vertex shader (%s) compilation error:\n----------\n%s----------\n", name, str);
break; break;
default: default:
Con_Printf("Shader_CreateShader: This shouldn't happen ever\n"); Con_Printf("Shader_CreateShader: This shouldn't happen ever\n");
break; break;
} }
Con_Printf("Shader \"%s\" source:\n", name); Con_DPrintf("Shader \"%s\" source:\n", name);
for (i = 0; i < strings; i++) for (i = 0; i < strings; i++)
Con_Printf("%s", prstrings[i]); {
Con_Printf("%s\n", str); int j;
if (length[i] < 0)
Con_DPrintf("%s", prstrings[i]);
else
{
for (j = 0; j < length[i]; j++)
Con_DPrintf("%c", prstrings[i][j]);
}
}
Con_DPrintf("%s\n", str);
return 0; return 0;
} }
@ -840,30 +984,11 @@ GLhandleARB GLSlang_CreateProgramObject (GLhandleARB vert, GLhandleARB frag)
return program; return program;
} }
#if HASHPROGRAMS GLhandleARB GLSlang_CreateProgram(char *name, int ver, char **precompilerconstants, char *vert, char *frag)
struct compiledshaders_s
{
int uses;
char *consts;
char *vert;
char *frag;
GLhandleARB handle;
bucket_t buck;
};
bucket_t *compiledshadersbuckets[64];
static hashtable_t compiledshaderstable;
#endif
GLhandleARB GLSlang_CreateProgram(char *name, char *versionline, char **precompilerconstants, char *vert, char *frag)
{ {
GLhandleARB handle; GLhandleARB handle;
GLhandleARB vs; GLhandleARB vs;
GLhandleARB fs; GLhandleARB fs;
#if HASHPROGRAMS
unsigned int hashkey;
struct compiledshaders_s *cs;
#endif
char *nullconstants = NULL; char *nullconstants = NULL;
if (!gl_config.arb_shader_objects) if (!gl_config.arb_shader_objects)
@ -872,25 +997,8 @@ GLhandleARB GLSlang_CreateProgram(char *name, char *versionline, char **precompi
if (!precompilerconstants) if (!precompilerconstants)
precompilerconstants = &nullconstants; precompilerconstants = &nullconstants;
#if HASHPROGRAMS vs = GLSlang_CreateShader(name, ver, precompilerconstants, vert, GL_VERTEX_SHADER_ARB);
hashkey = Hash_Key(precompilerconstants, ~0) ^ Hash_Key(frag, ~0); fs = GLSlang_CreateShader(name, ver, precompilerconstants, frag, GL_FRAGMENT_SHADER_ARB);
cs = Hash_GetKey(&compiledshaderstable, hashkey);
while(cs)
{
if (!strcmp(cs->consts, precompilerconstants))
if (!strcmp(cs->vert, vert))
if (!strcmp(cs->frag, frag))
{
cs->uses++;
return cs->handle;
}
cs = Hash_GetNextKey(&compiledshaderstable, hashkey, cs);
}
#endif
vs = GLSlang_CreateShader(name, versionline, precompilerconstants, vert, GL_VERTEX_SHADER_ARB);
fs = GLSlang_CreateShader(name, versionline, precompilerconstants, frag, GL_FRAGMENT_SHADER_ARB);
if (!vs || !fs) if (!vs || !fs)
handle = 0; handle = 0;
@ -900,19 +1008,6 @@ GLhandleARB GLSlang_CreateProgram(char *name, char *versionline, char **precompi
qglDeleteShaderObject_(vs); qglDeleteShaderObject_(vs);
qglDeleteShaderObject_(fs); qglDeleteShaderObject_(fs);
#if HASHPROGRAMS
cs = Z_Malloc(sizeof(*cs) + strlen(precompilerconstants)+1+strlen(vert)+1+strlen(frag)+1);
cs->consts = (char*)(cs + 1);
cs->vert = cs->consts + strlen(precompilerconstants)+1;
cs->frag = cs->vert + strlen(vert)+1;
cs->handle = handle;
cs->uses = 1;
strcpy(cs->consts, precompilerconstants);
strcpy(cs->vert, vert);
strcpy(cs->frag, frag);
Hash_AddKey(&compiledshaderstable, hashkey, cs, &cs->buck);
#endif
return handle; return handle;
} }
@ -1148,10 +1243,6 @@ void GL_Init(void *(*getglfunction) (char *name))
qglDebugMessageCallbackAMD(myGLDEBUGPROCAMD, NULL); qglDebugMessageCallbackAMD(myGLDEBUGPROCAMD, NULL);
qglGetError(); /*suck up the invalid operation error for non-debug contexts*/ qglGetError(); /*suck up the invalid operation error for non-debug contexts*/
#endif #endif
#if HASHPROGRAMS
Hash_InitTable(&compiledshaderstable, sizeof(compiledshadersbuckets)/Hash_BytesForBuckets(1), compiledshadersbuckets);
#endif
} }
unsigned int d_8to24rgbtable[256]; unsigned int d_8to24rgbtable[256];
@ -1171,7 +1262,7 @@ rendererinfo_t openglrendererinfo = {
GLDraw_Init, GLDraw_Init,
GLDraw_ReInit, GLDraw_DeInit,
GL_LoadTextureFmt, GL_LoadTextureFmt,
GL_LoadTexture8Pal24, GL_LoadTexture8Pal24,
@ -1234,6 +1325,7 @@ rendererinfo_t openglrendererinfo = {
GLBE_ClearVBO, GLBE_ClearVBO,
GLBE_UploadAllLightmaps, GLBE_UploadAllLightmaps,
GLBE_SelectEntity, GLBE_SelectEntity,
GLBE_SelectDLight,
GLBE_LightCullModel, GLBE_LightCullModel,
"" ""

View file

@ -1105,15 +1105,25 @@ void IN_MouseMove (float *movements, int pnum)
#ifdef VM_UI #ifdef VM_UI
UI_MousePosition(mousecursor_x, mousecursor_y); UI_MousePosition(mousecursor_x, mousecursor_y);
#endif #endif
}
#ifdef PEXT_CSQC #ifdef PEXT_CSQC
if (CSQC_MouseMove(mx, my)) if (CSQC_MousePosition(mousecursor_x, mousecursor_y))
{ {
mx = 0; mx = 0;
my = 0; my = 0;
} }
#endif #endif
}
else
{
#ifdef PEXT_CSQC
if (CSQC_MouseMove(mx, my))
{
mx = 0;
my = 0;
}
#endif
}
if (m_filter.value) if (m_filter.value)
{ {

View file

@ -174,8 +174,9 @@ RECT window_rect;
HMODULE hInstGL = NULL; HMODULE hInstGL = NULL;
HMODULE hInstwgl = NULL; HMODULE hInstwgl = NULL;
char reqminidriver[MAX_OSPATH]; static qboolean usingminidriver;
char opengldllname[MAX_OSPATH]; static char reqminidriver[MAX_OSPATH];
static char opengldllname[MAX_OSPATH];
//just GetProcAddress with a safty net. //just GetProcAddress with a safty net.
void *getglfunc(char *name) void *getglfunc(char *name)
@ -221,6 +222,9 @@ HDC (WINAPI *qwglGetCurrentDC)(VOID);
PROC (WINAPI *qwglGetProcAddress)(LPCSTR); PROC (WINAPI *qwglGetProcAddress)(LPCSTR);
BOOL (WINAPI *qwglMakeCurrent)(HDC, HGLRC); BOOL (WINAPI *qwglMakeCurrent)(HDC, HGLRC);
BOOL (WINAPI *qSwapBuffers)(HDC); BOOL (WINAPI *qSwapBuffers)(HDC);
int (WINAPI *qChoosePixelFormat)(HDC, CONST PIXELFORMATDESCRIPTOR *);
BOOL (WINAPI *qSetPixelFormat)(HDC, int, CONST PIXELFORMATDESCRIPTOR *);
int (WINAPI *qDescribePixelFormat)(HDC, int, UINT, LPPIXELFORMATDESCRIPTOR);
BOOL (WINAPI *qwglSwapIntervalEXT) (int); BOOL (WINAPI *qwglSwapIntervalEXT) (int);
@ -249,6 +253,7 @@ qboolean GLInitialise (char *renderer)
{ {
if (!hInstGL || strcmp(reqminidriver, renderer)) if (!hInstGL || strcmp(reqminidriver, renderer))
{ {
usingminidriver = false;
if (hInstGL) if (hInstGL)
FreeLibrary(hInstGL); FreeLibrary(hInstGL);
hInstGL=NULL; hInstGL=NULL;
@ -265,7 +270,10 @@ qboolean GLInitialise (char *renderer)
hInstGL = LoadLibrary(opengldllname); hInstGL = LoadLibrary(opengldllname);
if (hInstGL) if (hInstGL)
{
usingminidriver = true;
Con_DPrintf (" Success\n"); Con_DPrintf (" Success\n");
}
else else
Con_DPrintf (" Failed\n"); Con_DPrintf (" Failed\n");
} }
@ -309,7 +317,21 @@ qboolean GLInitialise (char *renderer)
qwglGetCurrentDC = (void *)getwglfunc("wglGetCurrentDC"); qwglGetCurrentDC = (void *)getwglfunc("wglGetCurrentDC");
qwglGetProcAddress = (void *)getwglfunc("wglGetProcAddress"); qwglGetProcAddress = (void *)getwglfunc("wglGetProcAddress");
qwglMakeCurrent = (void *)getwglfunc("wglMakeCurrent"); qwglMakeCurrent = (void *)getwglfunc("wglMakeCurrent");
qSwapBuffers = SwapBuffers;
if (usingminidriver)
{
qSwapBuffers = (void *)getglfunc("wglSwapBuffers");
qChoosePixelFormat = (void *)getglfunc("wglChoosePixelFormat");
qSetPixelFormat = (void *)getglfunc("wglSetPixelFormat");
qDescribePixelFormat = (void *)getglfunc("wglDescribePixelFormat");
}
else
{
qSwapBuffers = SwapBuffers;
qChoosePixelFormat = ChoosePixelFormat;
qSetPixelFormat = SetPixelFormat;
qDescribePixelFormat = DescribePixelFormat;
}
qGetDeviceGammaRamp = (void *)getglfunc("wglGetDeviceGammaRamp3DFX"); qGetDeviceGammaRamp = (void *)getglfunc("wglGetDeviceGammaRamp3DFX");
qSetDeviceGammaRamp = (void *)getglfunc("wglSetDeviceGammaRamp3DFX"); qSetDeviceGammaRamp = (void *)getglfunc("wglSetDeviceGammaRamp3DFX");
@ -320,7 +342,7 @@ qboolean GLInitialise (char *renderer)
} }
/*doesn't consider parent offsets*/ /*doesn't consider parent offsets*/
RECT centerrect(unsigned int parentwidth, unsigned int parentheight, unsigned int cwidth, unsigned int cheight) RECT centerrect(unsigned int parentleft, unsigned int parenttop, unsigned int parentwidth, unsigned int parentheight, unsigned int cwidth, unsigned int cheight)
{ {
RECT r; RECT r;
if (!vid_width.ival) if (!vid_width.ival)
@ -330,23 +352,23 @@ RECT centerrect(unsigned int parentwidth, unsigned int parentheight, unsigned in
if (parentwidth < cwidth) if (parentwidth < cwidth)
{ {
r.left = 0; r.left = parentleft;
r.right = parentwidth; r.right = r.left+parentwidth;
} }
else else
{ {
r.left = (parentwidth - cwidth) / 2; r.left = parentleft + (parentwidth - cwidth) / 2;
r.right = r.left + cwidth; r.right = r.left + cwidth;
} }
if (parentheight < cheight) if (parentheight < cheight)
{ {
r.top = 0; r.top = parenttop;
r.bottom = parentheight; r.bottom = r.top + parentheight;
} }
else else
{ {
r.top = (parentheight - cheight) / 2; r.top = parenttop + (parentheight - cheight) / 2;
r.bottom = r.top + cheight; r.bottom = r.top + cheight;
} }
@ -358,7 +380,7 @@ qboolean VID_SetWindowedMode (rendererstate_t *info)
{ {
int i; int i;
HDC hdc; HDC hdc;
int lastmodestate, wwidth, wheight, pwidth, pheight; int lastmodestate, wwidth, wheight, pleft, ptop, pwidth, pheight;
RECT rect; RECT rect;
hdc = GetDC(NULL); hdc = GetDC(NULL);
@ -385,6 +407,8 @@ qboolean VID_SetWindowedMode (rendererstate_t *info)
WindowStyle = WS_CHILDWINDOW|WS_OVERLAPPED; WindowStyle = WS_CHILDWINDOW|WS_OVERLAPPED;
ExWindowStyle = 0; ExWindowStyle = 0;
pleft = sys_parentleft;
ptop = sys_parenttop;
pwidth = sys_parentwidth; pwidth = sys_parentwidth;
pheight = sys_parentheight; pheight = sys_parentheight;
} }
@ -397,6 +421,8 @@ qboolean VID_SetWindowedMode (rendererstate_t *info)
WindowStyle |= WS_SIZEBOX | WS_MAXIMIZEBOX; WindowStyle |= WS_SIZEBOX | WS_MAXIMIZEBOX;
pleft = 0;
ptop = 0;
pwidth = GetSystemMetrics(SM_CXSCREEN); pwidth = GetSystemMetrics(SM_CXSCREEN);
pheight = GetSystemMetrics(SM_CYSCREEN); pheight = GetSystemMetrics(SM_CYSCREEN);
@ -414,7 +440,7 @@ qboolean VID_SetWindowedMode (rendererstate_t *info)
wwidth = rect.right - rect.left; wwidth = rect.right - rect.left;
wheight = rect.bottom - rect.top; wheight = rect.bottom - rect.top;
WindowRect = centerrect(pwidth, pheight, wwidth, wheight); WindowRect = centerrect(pleft, ptop, pwidth, pheight, wwidth, wheight);
// Create the DIB window // Create the DIB window
dibwindow = CreateWindowEx ( dibwindow = CreateWindowEx (
@ -770,7 +796,6 @@ int GLVID_SetMode (rendererstate_t *info, unsigned char *palette)
vid.recalc_refdef = 1; vid.recalc_refdef = 1;
maindc = GetDC(mainwindow);
if (vid_desktopgamma.value) if (vid_desktopgamma.value)
{ {
HDC hDC = GetDC(GetDesktopWindow()); HDC hDC = GetDC(GetDesktopWindow());
@ -1098,7 +1123,7 @@ void GLVID_Recenter_f(void)
if (sys_parentwindow && modestate==MS_WINDOWED) if (sys_parentwindow && modestate==MS_WINDOWED)
{ {
WindowRect = centerrect(sys_parentwidth, sys_parentheight, vid_width.value, vid_height.value); WindowRect = centerrect(sys_parentleft, sys_parenttop, sys_parentwidth, sys_parentheight, vid_width.value, vid_height.value);
MoveWindow(mainwindow, WindowRect.left, WindowRect.top, WindowRect.right - WindowRect.left, WindowRect.bottom - WindowRect.top, FALSE); MoveWindow(mainwindow, WindowRect.left, WindowRect.top, WindowRect.right - WindowRect.left, WindowRect.bottom - WindowRect.top, FALSE);
Cvar_ForceCallback(&vid_conautoscale); Cvar_ForceCallback(&vid_conautoscale);
@ -1449,14 +1474,14 @@ BOOL bSetupPixelFormat(HDC hDC)
} }
else else
{ {
if ((pixelformat = ChoosePixelFormat(hDC, &pfd))) if ((pixelformat = qChoosePixelFormat(hDC, &pfd)))
{ {
TRACE(("dbg: ChoosePixelFormat 1: worked\n")); TRACE(("dbg: ChoosePixelFormat 1: worked\n"));
if (SetPixelFormat(hDC, pixelformat, &pfd)) if (qSetPixelFormat(hDC, pixelformat, &pfd))
{ {
TRACE(("dbg: bSetupPixelFormat: we can use the stencil buffer. woot\n")); TRACE(("dbg: bSetupPixelFormat: we can use the stencil buffer. woot\n"));
DescribePixelFormat(hDC, pixelformat, sizeof(pfd), &pfd); qDescribePixelFormat(hDC, pixelformat, sizeof(pfd), &pfd);
FixPaletteInDescriptor(hDC, &pfd); FixPaletteInDescriptor(hDC, &pfd);
gl_canstencil = pfd.cStencilBits; gl_canstencil = pfd.cStencilBits;
return TRUE; return TRUE;
@ -1467,14 +1492,14 @@ BOOL bSetupPixelFormat(HDC hDC)
pfd.cStencilBits = 0; pfd.cStencilBits = 0;
gl_canstencil = false; gl_canstencil = false;
if ( (pixelformat = ChoosePixelFormat(hDC, &pfd)) == 0 ) if ( (pixelformat = qChoosePixelFormat(hDC, &pfd)) == 0 )
{ {
Con_Printf("bSetupPixelFormat: ChoosePixelFormat failed (%i)\n", (int)GetLastError()); Con_Printf("bSetupPixelFormat: ChoosePixelFormat failed (%i)\n", (int)GetLastError());
return FALSE; return FALSE;
} }
} }
if (SetPixelFormat(hDC, pixelformat, &pfd) == FALSE) if (qSetPixelFormat(hDC, pixelformat, &pfd) == FALSE)
{ {
Con_Printf("bSetupPixelFormat: SetPixelFormat failed (%i)\n", (int)GetLastError()); Con_Printf("bSetupPixelFormat: SetPixelFormat failed (%i)\n", (int)GetLastError());
return FALSE; return FALSE;
@ -1755,7 +1780,7 @@ LONG WINAPI GLMainWndProc (
if (MessageBox (mainwindow, "Are you sure you want to quit?", "Confirm Exit", if (MessageBox (mainwindow, "Are you sure you want to quit?", "Confirm Exit",
MB_YESNO | MB_SETFOREGROUND | MB_ICONQUESTION) == IDYES) MB_YESNO | MB_SETFOREGROUND | MB_ICONQUESTION) == IDYES)
{ {
Sys_Quit (); Cbuf_AddText("\nquit\n", RESTRICT_LOCAL);
} }
break; break;
@ -1771,6 +1796,8 @@ LONG WINAPI GLMainWndProc (
// fix the leftover Alt from any Alt-Tab or the like that switched us away // fix the leftover Alt from any Alt-Tab or the like that switched us away
ClearAllStates (); ClearAllStates ();
Cvar_ForceCallback(&vid_conautoscale);
break; break;
case WM_DESTROY: case WM_DESTROY:

View file

@ -783,6 +783,12 @@ void R_InitSky (struct texnums_s *tn, texture_t *mt, qbyte *src)
Q_snprintfz(name, sizeof(name), "%s_trans", mt->name); Q_snprintfz(name, sizeof(name), "%s_trans", mt->name);
Q_strlwr(name); Q_strlwr(name);
tn->fullbright = R_LoadReplacementTexture(name, NULL, 0); tn->fullbright = R_LoadReplacementTexture(name, NULL, 0);
if (!TEXVALID(tn->fullbright))
{
Q_snprintfz(name, sizeof(name), "%s_alpha", mt->name);
Q_strlwr(name);
tn->fullbright = R_LoadReplacementTexture(name, NULL, 0);
}
if (!TEXVALID(tn->fullbright)) if (!TEXVALID(tn->fullbright))
tn->fullbright = R_LoadTexture32(name, 128, 128, trans, IF_NOGAMMA); tn->fullbright = R_LoadTexture32(name, 128, 128, trans, IF_NOGAMMA);
} }

View file

@ -90,6 +90,7 @@ void GL_InitFogTexture(void);
void GL_BeginRendering (void); void GL_BeginRendering (void);
void GL_EndRendering (void); void GL_EndRendering (void);
void R_NetgraphInit(void);
void GLR_NetGraph (void); void GLR_NetGraph (void);
void GLR_FrameTimeGraph (int frametime); void GLR_FrameTimeGraph (int frametime);
void GL_FlushSkinCache(void); void GL_FlushSkinCache(void);
@ -188,15 +189,15 @@ void GL_Upload24BGR (char *name, qbyte *data, int width, int height, unsigned in
void GL_Upload8_EXT (qbyte *data, int width, int height, qboolean mipmap, qboolean alpha); void GL_Upload8_EXT (qbyte *data, int width, int height, qboolean mipmap, qboolean alpha);
#endif #endif
*/ */
texid_t GL_LoadTexture (char *identifier, int width, int height, qbyte *data, unsigned int flags, unsigned int transtype); texid_tf GL_LoadTexture (char *identifier, int width, int height, qbyte *data, unsigned int flags, unsigned int transtype);
texid_t GL_LoadTexture8Bump (char *identifier, int width, int height, unsigned char *data, unsigned int flags, float bumpscale); texid_tf GL_LoadTexture8Bump (char *identifier, int width, int height, unsigned char *data, unsigned int flags, float bumpscale);
texid_t GL_LoadTexture8Pal24 (char *identifier, int width, int height, qbyte *data, qbyte *palette24, unsigned int flags); texid_tf GL_LoadTexture8Pal24 (char *identifier, int width, int height, qbyte *data, qbyte *palette24, unsigned int flags);
texid_t GL_LoadTexture8Pal32 (char *identifier, int width, int height, qbyte *data, qbyte *palette32, unsigned int flags); texid_tf GL_LoadTexture8Pal32 (char *identifier, int width, int height, qbyte *data, qbyte *palette32, unsigned int flags);
texid_t GL_LoadTexture32 (char *identifier, int width, int height, void *data, unsigned int flags); texid_tf GL_LoadTexture32 (char *identifier, int width, int height, void *data, unsigned int flags);
texid_t GL_LoadCompressed(char *name); texid_tf GL_LoadCompressed(char *name);
texid_t GL_FindTexture (char *identifier); texid_tf GL_FindTexture (char *identifier);
texid_t GL_LoadTextureFB (char *identifier, int width, int height, qbyte *data, unsigned int flags); texid_tf GL_LoadTextureFB (char *identifier, int width, int height, qbyte *data, unsigned int flags);
void GL_Upload8Pal24 (qbyte *data, qbyte *pal, int width, int height, unsigned int flags); void GL_Upload8Pal24 (qbyte *data, qbyte *pal, int width, int height, unsigned int flags);
/* /*
typedef struct typedef struct
@ -240,6 +241,7 @@ extern int r_framecount;
extern mplane_t frustum[4]; extern mplane_t frustum[4];
extern float r_wateralphaval; extern float r_wateralphaval;
extern qboolean r_loadbumpmapping;
// //
// view origin // view origin
@ -260,10 +262,7 @@ extern texture_t *r_notexture_mip;
extern int d_lightstylevalue[256]; // 8.8 fraction of base light value extern int d_lightstylevalue[256]; // 8.8 fraction of base light value
extern texid_t netgraphtexture; // netgraph texture extern texid_t netgraphtexture; // netgraph texture
extern shader_t *netgraphshader;
extern int mirrortexturenum; // quake texturenum, not gltexturenum
extern qboolean mirror;
extern mplane_t *mirror_plane;
extern const char *gl_vendor; extern const char *gl_vendor;
extern const char *gl_renderer; extern const char *gl_renderer;
@ -332,7 +331,7 @@ void FTE_DEPRECATED R_IBrokeTheArrays(void);
// gl_draw.c // gl_draw.c
// //
#ifdef GLQUAKE #ifdef GLQUAKE
texid_t GL_LoadPicTexture (qpic_t *pic); texid_tf GL_LoadPicTexture (qpic_t *pic);
void GL_Set2D (void); void GL_Set2D (void);
#endif #endif
@ -341,7 +340,7 @@ void GL_Set2D (void);
// //
qboolean R_ShouldDraw(entity_t *e); qboolean R_ShouldDraw(entity_t *e);
#ifdef GLQUAKE #ifdef GLQUAKE
void R_RotateForEntity (float *modelviewmatrix, const entity_t *e, const model_t *mod); void R_RotateForEntity (float *modelmatrix, float *modelviewmatrix, const entity_t *e, const model_t *mod);
void GL_InitSceneProcessingShaders (void); void GL_InitSceneProcessingShaders (void);
void GL_SetupSceneProcessingTextures (void); void GL_SetupSceneProcessingTextures (void);
@ -363,11 +362,11 @@ void R_DrawHLModel(entity_t *curent);
// //
// gl_rlight.c // gl_rlight.c
// //
void GLR_RenderDlights (void); void R_RenderDlights (void);
void R_GenDlightBatches(batch_t *batches[]); void R_GenDlightBatches(batch_t *batches[]);
void R_InitFlashblends(void);
#ifdef GLQUAKE #ifdef GLQUAKE
void GLR_MarkQ2Lights (dlight_t *light, int bit, mnode_t *node); void GLR_MarkQ2Lights (dlight_t *light, int bit, mnode_t *node);
void R_InitFlashblends (void);
int GLR_LightPoint (vec3_t p); int GLR_LightPoint (vec3_t p);
#endif #endif
void GLQ3_LightGrid(model_t *mod, vec3_t point, vec3_t res_diffuse, vec3_t res_ambient, vec3_t res_dir); void GLQ3_LightGrid(model_t *mod, vec3_t point, vec3_t res_diffuse, vec3_t res_ambient, vec3_t res_dir);
@ -786,6 +785,8 @@ extern void (APIENTRY *qglFramebufferTexture2DEXT)(GLenum target, GLenum attachm
extern void (APIENTRY *qglFramebufferRenderbufferEXT)(GLenum target, GLenum attachmentPoint, GLenum textureTarget, GLuint textureId); extern void (APIENTRY *qglFramebufferRenderbufferEXT)(GLenum target, GLenum attachmentPoint, GLenum textureTarget, GLuint textureId);
extern GLenum (APIENTRY *qglCheckFramebufferStatusEXT)(GLenum target); extern GLenum (APIENTRY *qglCheckFramebufferStatusEXT)(GLenum target);
void (APIENTRY *qglDepthBoundsEXT) (GLclampd zmin, GLclampd zmax);
/* /*
extern qboolean gl_arb_fragment_program; extern qboolean gl_arb_fragment_program;
extern PFNGLPROGRAMSTRINGARBPROC qglProgramStringARB; extern PFNGLPROGRAMSTRINGARBPROC qglProgramStringARB;
@ -826,7 +827,7 @@ extern FTEPFNGLUNIFORM1IARBPROC qglUniform1iARB;
extern FTEPFNGLUNIFORM1FARBPROC qglUniform1fARB; extern FTEPFNGLUNIFORM1FARBPROC qglUniform1fARB;
//glslang helper api //glslang helper api
GLhandleARB GLSlang_CreateProgram(char *name, char *versionline, char **precompilerconstants, char *vert, char *frag); GLhandleARB GLSlang_CreateProgram(char *name, int ver, char **precompilerconstants, char *vert, char *frag);
GLint GLSlang_GetUniformLocation (int prog, char *name); GLint GLSlang_GetUniformLocation (int prog, char *name);
void GL_SelectProgram(int program); void GL_SelectProgram(int program);
#define GLSlang_UseProgram(prog) GL_SelectProgram(prog) #define GLSlang_UseProgram(prog) GL_SelectProgram(prog)

View file

@ -263,6 +263,10 @@ typedef void (APIENTRY *PFNGLPNTRIANGLESIATIPROC)(GLenum pname, GLint param);
typedef void (APIENTRY *PFNGLPNTRIANGLESFATIPROC)(GLenum pname, GLfloat param); typedef void (APIENTRY *PFNGLPNTRIANGLESFATIPROC)(GLenum pname, GLfloat param);
#endif #endif
#ifndef GL_EXT_depth_bounds_test
#define GL_EXT_depth_bounds_test 1
#define GL_DEPTH_BOUNDS_TEST_EXT 0x8890
#endif
#ifndef GL_EXT_stencil_two_side #ifndef GL_EXT_stencil_two_side
#define GL_EXT_stencil_two_side 1 #define GL_EXT_stencil_two_side 1

View file

@ -156,8 +156,8 @@ typedef struct shaderpass_s {
RGB_GEN_WAVE, RGB_GEN_WAVE,
RGB_GEN_ENTITY, RGB_GEN_ENTITY,
RGB_GEN_ONE_MINUS_ENTITY, RGB_GEN_ONE_MINUS_ENTITY,
RGB_GEN_VERTEX, RGB_GEN_VERTEX_LIGHTING,
RGB_GEN_EXACT_VERTEX, RGB_GEN_VERTEX_EXACT,
RGB_GEN_ONE_MINUS_VERTEX, RGB_GEN_ONE_MINUS_VERTEX,
RGB_GEN_IDENTITY_LIGHTING, RGB_GEN_IDENTITY_LIGHTING,
RGB_GEN_IDENTITY, RGB_GEN_IDENTITY,
@ -223,6 +223,8 @@ typedef struct shaderpass_s {
T_GEN_SOURCECOLOUR, //used for render-to-texture targets T_GEN_SOURCECOLOUR, //used for render-to-texture targets
T_GEN_SOURCEDEPTH, //used for render-to-texture targets T_GEN_SOURCEDEPTH, //used for render-to-texture targets
T_GEN_SOURCECUBE, //used for render-to-texture targets
T_GEN_VIDEOMAP, //use the media playback as an image source, updating each frame for which it is visible T_GEN_VIDEOMAP, //use the media playback as an image source, updating each frame for which it is visible
T_GEN_SKYBOX, //use a skybox instead, otherwise T_GEN_SINGLEMAP T_GEN_SKYBOX, //use a skybox instead, otherwise T_GEN_SINGLEMAP
} texgen; } texgen;
@ -464,6 +466,7 @@ void GLBE_UploadAllLightmaps(void);
void GLBE_DrawWorld (qbyte *vis); void GLBE_DrawWorld (qbyte *vis);
qboolean GLBE_LightCullModel(vec3_t org, model_t *model); qboolean GLBE_LightCullModel(vec3_t org, model_t *model);
void GLBE_SelectEntity(entity_t *ent); void GLBE_SelectEntity(entity_t *ent);
void GLBE_SelectDLight(dlight_t *dl, vec3_t colour);
#endif #endif
#ifdef D3DQUAKE #ifdef D3DQUAKE
void D3DBE_Init(void); void D3DBE_Init(void);
@ -478,17 +481,17 @@ void D3DBE_UploadAllLightmaps(void);
void D3DBE_DrawWorld (qbyte *vis); void D3DBE_DrawWorld (qbyte *vis);
qboolean D3DBE_LightCullModel(vec3_t org, model_t *model); qboolean D3DBE_LightCullModel(vec3_t org, model_t *model);
void D3DBE_SelectEntity(entity_t *ent); void D3DBE_SelectEntity(entity_t *ent);
void D3DBE_SelectDLight(dlight_t *dl, vec3_t colour);
void D3DShader_CreateProgram (program_t *prog, int permu, char **precompilerconstants, char *vert, char *frag); void D3DShader_CreateProgram (program_t *prog, int permu, char **precompilerconstants, char *vert, char *frag);
int D3DShader_FindUniform(union programhandle_u *h, int type, char *name); int D3DShader_FindUniform(union programhandle_u *h, int type, char *name);
void D3DShader_Init(void); void D3DShader_Init(void);
void D3DBE_Reset(qboolean before);
#endif #endif
//Asks the backend to invoke DrawMeshChain for each surface, and to upload lightmaps as required //Asks the backend to invoke DrawMeshChain for each surface, and to upload lightmaps as required
void BE_DrawNonWorld (void); void BE_DrawNonWorld (void);
void D3DBE_Reset(qboolean before);
//Builds a hardware shader from the software representation //Builds a hardware shader from the software representation
void BE_GenerateProgram(shader_t *shader); void BE_GenerateProgram(shader_t *shader);
@ -503,8 +506,6 @@ void Sh_DrawLights(qbyte *vis);
void Sh_Shutdown(void); void Sh_Shutdown(void);
//Draws the depth of ents in the world near the current light //Draws the depth of ents in the world near the current light
void BE_BaseEntShadowDepth(void); void BE_BaseEntShadowDepth(void);
//Sets the given light+colour to be the current one that everything is to be lit/culled by.
void BE_SelectDLight(dlight_t *dl, vec3_t colour);
#endif #endif
struct shader_field_names_s struct shader_field_names_s

View file

@ -41,6 +41,38 @@ void PRHunkFree(progfuncs_t *progfuncs, int mark)
return; return;
} }
/*if we ran out of memory, the vm can allocate a new block, but doing so requires fixing up all sorts of pointers*/
void PRAddressableRelocate(progfuncs_t *progfuncs, char *oldb, char *newb, int oldlen)
{
unsigned int i;
edictrun_t *e;
for (i=0 ; i<maxedicts; i++)
{
e = (edictrun_t *)(prinst->edicttable[i]);
if (e && (char*)e->fields >= oldb && (char*)e->fields < oldb+oldlen)
e->fields = ((char*)e->fields - oldb) + newb;
}
if (progfuncs->stringtable >= oldb && progfuncs->stringtable < oldb+oldlen)
progfuncs->stringtable = (progfuncs->stringtable - oldb) + newb;
for (i=0; i < maxprogs; i++)
{
if ((char*)prinst->progstate[i].globals >= oldb && (char*)prinst->progstate[i].globals < oldb+oldlen)
prinst->progstate[i].globals = (float*)(((char*)prinst->progstate[i].globals - oldb) + newb);
if (prinst->progstate[i].strings >= oldb && prinst->progstate[i].strings < oldb+oldlen)
prinst->progstate[i].strings = (prinst->progstate[i].strings - oldb) + newb;
}
for (i = 0; i < numfields; i++)
{
if (field[i].name >= oldb && field[i].name < oldb+oldlen)
field[i].name = (field[i].name - oldb) + newb;
}
externs->addressablerelocated(progfuncs, oldb, newb, oldlen);
}
//for 64bit systems. :) //for 64bit systems. :)
//addressable memory is memory available to the vm itself for writing. //addressable memory is memory available to the vm itself for writing.
//once allocated, it cannot be freed for the lifetime of the VM. //once allocated, it cannot be freed for the lifetime of the VM.
@ -48,7 +80,46 @@ void *PRAddressableAlloc(progfuncs_t *progfuncs, int ammount)
{ {
ammount = (ammount + 4)&~3; //round up to 4 ammount = (ammount + 4)&~3; //round up to 4
if (addressableused + ammount > addressablesize) if (addressableused + ammount > addressablesize)
Sys_Error("Not enough addressable memory for progs VM"); {
/*only do this if the caller states that it can cope with addressable-block relocations/resizes*/
if (externs->addressablerelocated)
{
#ifdef _WIN32
char *newblock;
#if 0//def _DEBUG
int oldtot = addressablesize;
#endif
int newsize = (addressableused + ammount + 4096) & ~(4096-1);
newblock = VirtualAlloc (NULL, addressablesize, MEM_RESERVE, PAGE_NOACCESS);
if (newblock)
{
VirtualAlloc (newblock, addressableused, MEM_COMMIT, PAGE_READWRITE);
memcpy(newblock, addressablehunk, addressableused);
#if 0//def _DEBUG
VirtualAlloc (addressablehunk, oldtot, MEM_RESERVE, PAGE_NOACCESS);
#else
VirtualFree (addressablehunk, 0, MEM_RELEASE);
#endif
PRAddressableRelocate(progfuncs, addressablehunk, newblock, addressableused);
addressablehunk = newblock;
addressablesize = newsize;
}
#else
char *newblock;
addressablesize = (addressableused + ammount + 1024*1024) & ~(1024*1024-1);
newblock = realloc(newblock, addressablesize);
if (newblock)
{
PRAddressableRelocate(progfuncs, addressablehunk, newblock, addressableused);
addressablehunk = newblock;
addressablesize = newsize;
}
#endif
}
if (addressableused + ammount > addressablesize)
Sys_Error("Not enough addressable memory for progs VM");
}
addressableused += ammount; addressableused += ammount;

View file

@ -5,11 +5,6 @@ struct edict_s;
#include "progsint.h" #include "progsint.h"
//#include "crc.h" //#include "crc.h"
/*int maxedicts;
evalc_t spawnflagscache;
*/
#ifdef _WIN32 #ifdef _WIN32
//this is windows all files are written with this endian standard. we do this to try to get a little more speed. //this is windows all files are written with this endian standard. we do this to try to get a little more speed.
#define NOENDIAN #define NOENDIAN
@ -18,30 +13,8 @@ evalc_t spawnflagscache;
vec3_t vec3_origin; vec3_t vec3_origin;
//edictrun_t *sv_edicts;
//int sv_num_edicts;
//int pr_edict_size; // in bytes
//int pr_max_edict_size;
//unsigned short pr_crc;
fdef_t *ED_FieldAtOfs (progfuncs_t *progfuncs, unsigned int ofs); fdef_t *ED_FieldAtOfs (progfuncs_t *progfuncs, unsigned int ofs);
pbool ED_ParseEpair (progfuncs_t *progfuncs, void *base, ddefXX_t *key, char *s, int bits); pbool ED_ParseEpair (progfuncs_t *progfuncs, int qcptr, ddefXX_t *key, char *s, int bits);
/*
#define MAX_FIELD_LEN 64
#define GEFV_CACHESIZE 5
typedef struct {
ddef_t *pcache;
char field[MAX_FIELD_LEN];
} gefv_cache;
static gefv_cache gefvCache[GEFV_CACHESIZE] = {{NULL, ""}, {NULL, ""}};
*/
/* /*
================= =================
@ -1052,22 +1025,21 @@ Can parse either fields or globals
returns false if error returns false if error
============= =============
*/ */
pbool ED_ParseEpair (progfuncs_t *progfuncs, void *base, ddefXX_t *key, char *s, int structtype) pbool ED_ParseEpair (progfuncs_t *progfuncs, int qcptr, ddefXX_t *key, char *s, int structtype)
{ {
int i; int i;
char string[128]; char string[128];
fdef_t *def; fdef_t *def;
char *v, *w; char *v, *w;
void *d;
string_t st; string_t st;
dfunction_t *func; dfunction_t *func;
int type = 0; // warning about beign used without initializing it int type;
switch(structtype) switch(structtype)
{ {
case PST_DEFAULT: case PST_DEFAULT:
d = (void *)((int *)base + ((ddef16_t*)key)->ofs); qcptr += ((ddef16_t*)key)->ofs*sizeof(int);
if (pr_types) if (pr_types)
type = pr_types[((ddef16_t*)key)->type & ~DEF_SAVEGLOBAL].type; type = pr_types[((ddef16_t*)key)->type & ~DEF_SAVEGLOBAL].type;
@ -1075,7 +1047,7 @@ pbool ED_ParseEpair (progfuncs_t *progfuncs, void *base, ddefXX_t *key, char *s,
type = ((ddef16_t*)key)->type & ~DEF_SAVEGLOBAL; type = ((ddef16_t*)key)->type & ~DEF_SAVEGLOBAL;
break; break;
case PST_FTE32: case PST_FTE32:
d = (void *)((int *)base + ((ddef32_t*)key)->ofs); qcptr += ((ddef32_t*)key)->ofs*sizeof(int);
if (pr_types) if (pr_types)
type = pr_types[((ddef32_t*)key)->type & ~DEF_SAVEGLOBAL].type; type = pr_types[((ddef32_t*)key)->type & ~DEF_SAVEGLOBAL].type;
@ -1084,22 +1056,22 @@ pbool ED_ParseEpair (progfuncs_t *progfuncs, void *base, ddefXX_t *key, char *s,
break; break;
default: default:
Sys_Error("Bad struct type in ED_ParseEpair"); Sys_Error("Bad struct type in ED_ParseEpair");
d = 0; return false;
} }
switch (type) switch (type)
{ {
case ev_string: case ev_string:
st = PR_StringToProgs(progfuncs, ED_NewString (progfuncs, s, 0)); st = PR_StringToProgs(progfuncs, ED_NewString (progfuncs, s, 0));
*(string_t *)d = st; *(string_t *)(progfuncs->stringtable + qcptr) = st;
break; break;
case ev_float: case ev_float:
*(float *)d = (float)atof (s); *(float *)(progfuncs->stringtable + qcptr) = (float)atof (s);
break; break;
case ev_integer: case ev_integer:
*(int *)d = atoi (s); *(int *)(progfuncs->stringtable + qcptr) = atoi (s);
break; break;
case ev_vector: case ev_vector:
@ -1112,20 +1084,20 @@ pbool ED_ParseEpair (progfuncs_t *progfuncs, void *base, ddefXX_t *key, char *s,
v++; v++;
if (!*v) if (!*v)
{ {
((float *)d)[i] = (float)atof (w); ((float *)(progfuncs->stringtable + qcptr))[i] = (float)atof (w);
w = v; w = v;
} }
else else
{ {
*v = 0; *v = 0;
((float *)d)[i] = (float)atof (w); ((float *)(progfuncs->stringtable + qcptr))[i] = (float)atof (w);
w = v = v+1; w = v = v+1;
} }
} }
break; break;
case ev_entity: case ev_entity:
*(int *)d = atoi (s); *(int *)(progfuncs->stringtable + qcptr) = atoi (s);
break; break;
case ev_field: case ev_field:
@ -1135,13 +1107,13 @@ pbool ED_ParseEpair (progfuncs_t *progfuncs, void *base, ddefXX_t *key, char *s,
printf ("Can't find field %s\n", s); printf ("Can't find field %s\n", s);
return false; return false;
} }
*(int *)d = def->ofs; *(int *)(progfuncs->stringtable + qcptr) = def->ofs;
break; break;
case ev_function: case ev_function:
if (s[1]==':'&&s[2]=='\0') if (s[1]==':'&&s[2]=='\0')
{ {
*(func_t *)d = 0; *(func_t *)(progfuncs->stringtable + qcptr) = 0;
return true; return true;
} }
func = ED_FindFunction (progfuncs, s, &i, -1); func = ED_FindFunction (progfuncs, s, &i, -1);
@ -1150,7 +1122,7 @@ pbool ED_ParseEpair (progfuncs_t *progfuncs, void *base, ddefXX_t *key, char *s,
printf ("Can't find function %s\n", s); printf ("Can't find function %s\n", s);
return false; return false;
} }
*(func_t *)d = (func - pr_progstate[i].functions) | (i<<24); *(func_t *)(progfuncs->stringtable + qcptr) = (func - pr_progstate[i].functions) | (i<<24);
break; break;
default: default:
@ -1259,7 +1231,7 @@ char *ED_ParseEdict (progfuncs_t *progfuncs, char *data, edictrun_t *ent)
} }
cont: cont:
if (!ED_ParseEpair (progfuncs, ent->fields, (ddefXX_t*)key, qcc_token, PST_FTE32)) if (!ED_ParseEpair (progfuncs, (char*)ent->fields - progfuncs->stringtable, (ddefXX_t*)key, qcc_token, PST_FTE32))
{ {
continue; continue;
// Sys_Error ("ED_ParseEdict: parse error on entities"); // Sys_Error ("ED_ParseEdict: parse error on entities");
@ -1905,7 +1877,7 @@ int LoadEnts(progfuncs_t *progfuncs, char *file, float killonspawnflags)
else else
{ {
file = QCC_COM_Parse(file); file = QCC_COM_Parse(file);
ED_ParseEpair(progfuncs, pr_globals, (ddefXX_t*)d16, qcc_token, PST_DEFAULT); ED_ParseEpair(progfuncs, (char*)pr_globals - progfuncs->stringtable, (ddefXX_t*)d16, qcc_token, PST_DEFAULT);
} }
break; break;
case PST_QTEST: case PST_QTEST:
@ -1918,7 +1890,7 @@ int LoadEnts(progfuncs_t *progfuncs, char *file, float killonspawnflags)
else else
{ {
file = QCC_COM_Parse(file); file = QCC_COM_Parse(file);
ED_ParseEpair(progfuncs, pr_globals, (ddefXX_t*)d32, qcc_token, PST_FTE32); ED_ParseEpair(progfuncs, (char*)pr_globals - progfuncs->stringtable, (ddefXX_t*)d32, qcc_token, PST_FTE32);
} }
break; break;
default: default:
@ -2004,7 +1976,7 @@ int LoadEnts(progfuncs_t *progfuncs, char *file, float killonspawnflags)
else else
{ {
file = QCC_COM_Parse(file); file = QCC_COM_Parse(file);
ED_ParseEpair(progfuncs, pr_globals, (ddefXX_t*)d16, qcc_token, PST_DEFAULT); ED_ParseEpair(progfuncs, (char*)pr_globals - progfuncs->stringtable, (ddefXX_t*)d16, qcc_token, PST_DEFAULT);
} }
break; break;
case PST_QTEST: case PST_QTEST:
@ -2017,7 +1989,7 @@ int LoadEnts(progfuncs_t *progfuncs, char *file, float killonspawnflags)
else else
{ {
file = QCC_COM_Parse(file); file = QCC_COM_Parse(file);
ED_ParseEpair(progfuncs, pr_globals, (ddefXX_t*)d32, qcc_token, PST_FTE32); ED_ParseEpair(progfuncs, (char*)pr_globals - progfuncs->stringtable, (ddefXX_t*)d32, qcc_token, PST_FTE32);
} }
break; break;
default: default:
@ -2922,9 +2894,6 @@ retry:
break; break;
} }
} }
if (st16[i].op >= OP_RAND0 && st16[i].op <= OP_RANDV2)
if (!st16[i].c)
st16[i].c = OFS_RETURN;
} }
if (hexencalling) if (hexencalling)
{ {
@ -2932,6 +2901,9 @@ retry:
{ {
if (st16[i].op >= OP_CALL1 && st16[i].op <= OP_CALL8) if (st16[i].op >= OP_CALL1 && st16[i].op <= OP_CALL8)
st16[i].op += OP_CALL1H - OP_CALL1; st16[i].op += OP_CALL1H - OP_CALL1;
if (st16[i].op >= OP_RAND0 && st16[i].op <= OP_RANDV2)
if (!st16[i].c)
st16[i].c = OFS_RETURN;
} }
} }
break; break;
@ -2954,9 +2926,6 @@ retry:
break; break;
} }
} }
if (st16[i].op >= OP_RAND0 && st16[i].op <= OP_RANDV2)
if (!st16[i].c)
st16[i].c = OFS_RETURN;
} }
if (hexencalling) if (hexencalling)
{ {
@ -2964,6 +2933,9 @@ retry:
{ {
if (pr_statements32[i].op >= OP_CALL1 && pr_statements32[i].op <= OP_CALL8) if (pr_statements32[i].op >= OP_CALL1 && pr_statements32[i].op <= OP_CALL8)
pr_statements32[i].op += OP_CALL1H - OP_CALL1; pr_statements32[i].op += OP_CALL1H - OP_CALL1;
if (pr_statements32[i].op >= OP_RAND0 && pr_statements32[i].op <= OP_RANDV2)
if (!pr_statements32[i].c)
pr_statements32[i].c = OFS_RETURN;
} }
} }
break; break;
@ -3123,7 +3095,7 @@ retry:
d16 = ED_FindGlobal16(progfuncs, s); d16 = ED_FindGlobal16(progfuncs, s);
if (!d16) if (!d16)
{ {
printf("Progs requires \"%s\" the external function \"%s\", but the definition was stripped", filename, s); printf("Progs requires \"%s\" the external function \"%s\", but the definition was stripped\n", filename, s);
PRHunkFree(progfuncs, hmark); PRHunkFree(progfuncs, hmark);
pr_progs=NULL; pr_progs=NULL;
return false; return false;
@ -3131,7 +3103,7 @@ retry:
((int *)glob)[d16->ofs] = PR_FindFunc(progfuncs, s, PR_ANY); ((int *)glob)[d16->ofs] = PR_FindFunc(progfuncs, s, PR_ANY);
if (!((int *)glob)[d16->ofs]) if (!((int *)glob)[d16->ofs])
printf("Warning: Runtime-linked function %s was not found in primary progs (loading %s)", s, filename); printf("Warning: Runtime-linked function %s could not be found (loading %s)\n", s, filename);
/* /*
d2 = ED_FindGlobalOfsFromProgs(progfuncs, s, 0, ev_function); d2 = ED_FindGlobalOfsFromProgs(progfuncs, s, 0, ev_function);
if (!d2) if (!d2)

View file

@ -56,6 +56,10 @@ struct jitstate
unsigned char *code; unsigned char *code;
unsigned int codesize; unsigned int codesize;
unsigned int jitstatements; unsigned int jitstatements;
float *glob;
unsigned int cachedglobal;
unsigned int cachereg;
}; };
static void EmitByte(struct jitstate *jit, unsigned char byte) static void EmitByte(struct jitstate *jit, unsigned char byte)
@ -112,7 +116,11 @@ enum
REG_ESP, REG_ESP,
REG_EBP, REG_EBP,
REG_ESI, REG_ESI,
REG_EDI REG_EDI,
/*I'm not going to list S1 here, as that makes things too awkward*/
REG_S0,
REG_NONE
}; };
#define XOR(sr,dr) EmitByte(0x31);EmitByte(0xc0 | (sr<<3) | dr); #define XOR(sr,dr) EmitByte(0x31);EmitByte(0xc0 | (sr<<3) | dr);
#define CLEARREG(reg) XOR(reg,reg) #define CLEARREG(reg) XOR(reg,reg)
@ -122,6 +130,117 @@ enum
#define STOREI(i, addr) EmitByte(0xc7);EmitByte(0x05); EmitAdr(addr);Emit4Byte(i); #define STOREI(i, addr) EmitByte(0xc7);EmitByte(0x05); EmitAdr(addr);Emit4Byte(i);
#define SETREGI(val,reg) EmitByte(0xbe);Emit4Byte(val); #define SETREGI(val,reg) EmitByte(0xbe);Emit4Byte(val);
#define ARGREGS(a,b,c) GCache_Load(jit, op[i].a, a, op[i].b, b, op[i].c, c)
#define RESULTREG(r) GCache_Store(jit, op[i].c, r)
//for the purposes of the cache, 'temp' offsets are only read when they have been written only within the preceeding control block.
//if they were read at any other time, then we must write them out in full.
//this logic applies only to locals of a function.
//#define USECACHE
static void GCache_Load(struct jitstate *jit, int ao, int ar, int bo, int br, int co, int cr)
{
#if USECACHE
if (jit->cachedreg != REG_NONE)
{
/*something is cached, if its one of the input offsets then can chain the instruction*/
if (jit->cachedglobal === ao && ar != REG_NONE)
{
if (jit->cachedreg == ar)
ar = REG_NONE;
}
if (jit->cachedglobal === bo && br != REG_NONE)
{
if (jit->cachedreg == br)
br = REG_NONE;
}
if (jit->cachedglobal === co && cr != REG_NONE)
{
if (jit->cachedreg == cr)
cr = REG_NONE;
}
if (!istemp(ao))
{
/*purge the old cache*/
switch(jit->cachedreg)
{
case REG_NONE:
break;
case REG_S0:
//fstps glob[C]
EmitByte(0xd9);EmitByte(0x1d);EmitAdr(jit->glob + jit->cachedglobal);
break;
default:
STOREREG(jit->cachedreg, jit->glob + jit->cachedglobal);
break;
}
jit->cachedglobal = -1;
jit->cachedreg = REG_NONE;
}
#endif
switch(ar)
{
case REG_NONE:
break;
case REG_S0:
//flds glob[A]
EmitByte(0xd9);EmitByte(0x05);EmitAdr(jit->glob + op[i].a);
break;
default:
LOADREG(jit->glob + ao, ar);
break;
}
switch(br)
{
case REG_NONE:
break;
case REG_S0:
//flds glob[A]
EmitByte(0xd9);EmitByte(0x05);EmitAdr(jit->glob + op[i].b);
break;
default:
LOADREG(jit->glob + bo, br);
break;
}
switch(cr)
{
case REG_NONE:
break;
case REG_S0:
//flds glob[A]
EmitByte(0xd9);EmitByte(0x05);EmitAdr(jit->glob + op[i].c);
break;
default:
LOADREG(jit->glob + co, cr);
break;
}
}
static void GCache_Store(struct jitstate *jit, int ofs, int reg)
{
#if USECACHE
jit->cachedglobal = ofs;
jit->cachedreg = reg;
#else
switch(reg)
{
case REG_NONE:
break;
case REG_S0:
//fstps glob[C]
EmitByte(0xd9);EmitByte(0x1d);EmitAdr(jit->glob + ofs);
break;
default:
STOREREG(reg, jit->glob + ofs);
break;
}
#endif
}
static void *LocalLoc(struct jitstate *jit) static void *LocalLoc(struct jitstate *jit)
{ {
return &jit->code[jit->codesize]; return &jit->code[jit->codesize];
@ -359,6 +478,9 @@ struct jitstate *PR_GenerateJit(progfuncs_t *progfuncs)
case OP_CALL6: case OP_CALL6:
case OP_CALL7: case OP_CALL7:
case OP_CALL8: case OP_CALL8:
//FIXME: the size of this instruction is going to hurt cache performance if every single function call is expanded into this HUGE CHUNK of gibberish!
//FIXME: consider the feasability of just calling a C function and just jumping to the address it returns.
//save the state in place the rest of the engine can cope with //save the state in place the rest of the engine can cope with
//movl $i, pr_xstatement //movl $i, pr_xstatement
EmitByte( 0xc7);EmitByte(0x05);EmitAdr(&pr_xstatement);Emit4Byte(i); EmitByte( 0xc7);EmitByte(0x05);EmitAdr(&pr_xstatement);Emit4Byte(i);
@ -721,6 +843,7 @@ struct jitstate *PR_GenerateJit(progfuncs_t *progfuncs)
case OP_AND_F: case OP_AND_F:
//test floats properly, so we don't get confused with -0.0 //test floats properly, so we don't get confused with -0.0
//FIXME: is it feasable to grab the value as an int and test it against 0x7fffffff?
//flds glob[A] //flds glob[A]
EmitByte(0xd9); EmitByte(0x05); EmitAdr(glob + op[i].a); EmitByte(0xd9); EmitByte(0x05); EmitAdr(glob + op[i].a);

View file

@ -1,5 +1,7 @@
#ifdef _WIN32 #ifdef _WIN32
#ifndef _CRT_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS #define _CRT_SECURE_NO_WARNINGS
#endif
#define _CRT_NONSTDC_NO_WARNINGS #define _CRT_NONSTDC_NO_WARNINGS
#ifndef AVAIL_ZLIB #ifndef AVAIL_ZLIB
#ifdef _MSC_VER #ifdef _MSC_VER
@ -34,10 +36,6 @@ typedef unsigned char qbyte;
#define PROGSUSED #define PROGSUSED
#endif #endif
extern int maxedicts;
extern int maxprogs;
extern int hunksize;
#include "progtype.h" #include "progtype.h"
#include "progslib.h" #include "progslib.h"
@ -283,7 +281,7 @@ unsigned int NUM_FOR_EDICT(progfuncs_t *progfuncs, struct edict_s *e);
#define GQ_STRING(o) (*(QCC_string_t *)&pr_globals[o]) #define GQ_STRING(o) (*(QCC_string_t *)&pr_globals[o])
#define GQ_STRING2(o) ((char*)*(QCC_string_t *)&pr_globals[o]) #define GQ_STRING2(o) ((char*)*(QCC_string_t *)&pr_globals[o])
#define G_FUNCTION(o) (*(func_t *)&pr_globals[o]) #define G_FUNCTION(o) (*(func_t *)&pr_globals[o])
#define G_PROG(o) (*(progsnum_t *)&pr_globals[o]) //simply so it's nice and easy to change... #define G_PROG(o) G_FLOAT(o) //simply so it's nice and easy to change...
#define RETURN_EDICT(e) (((int *)pr_globals)[OFS_RETURN] = EDICT_TO_PROG(e)) #define RETURN_EDICT(e) (((int *)pr_globals)[OFS_RETURN] = EDICT_TO_PROG(e))
@ -356,8 +354,8 @@ typedef struct prinst_s {
int maxallocedstrings; int maxallocedstrings;
int numallocedstrings; int numallocedstrings;
var(progstate_t *, pr_progstate); var(progstate_t *, progstate);
#define pr_progstate prinst->pr_progstate #define pr_progstate prinst->progstate
var(progsnum_t, pr_typecurrent); var(progsnum_t, pr_typecurrent);
#define pr_typecurrent prinst->pr_typecurrent #define pr_typecurrent prinst->pr_typecurrent

View file

@ -181,6 +181,7 @@ typedef struct progexterns_s {
unsigned int *sv_num_edicts; //pointer to the engine's edict count. unsigned int *sv_num_edicts; //pointer to the engine's edict count.
int (*useeditor) (progfuncs_t *prinst, char *filename, int line, int nump, char **parms); //called on syntax errors or step-by-step debugging. int (*useeditor) (progfuncs_t *prinst, char *filename, int line, int nump, char **parms); //called on syntax errors or step-by-step debugging.
void (*addressablerelocated) (progfuncs_t *progfuncs, char *oldb, char *newb, int oldlen); //called when the progs memory was resized. you must fix up all pointers to globals, strings, fields, addressable blocks.
void *user; /*contains the owner's world reference in FTE*/ void *user; /*contains the owner's world reference in FTE*/
} progparms_t, progexterns_t; } progparms_t, progexterns_t;
@ -210,7 +211,7 @@ typedef union eval_s
func_t function; func_t function;
int _int; int _int;
int edict; int edict;
progsnum_t prog; //so it can easily be changed float prog; //so it can easily be changed
} eval_t; } eval_t;
#endif #endif

View file

@ -4921,6 +4921,9 @@ int QCC_canConv(QCC_def_t *from, etype_t to)
} }
} }
if (from->type->type == ev_variant)
return 5;
/* if (from->type->type == ev_pointer && from->type->aux_type->type == to) /* if (from->type->type == ev_pointer && from->type->aux_type->type == to)
return 1; return 1;

View file

@ -4,13 +4,12 @@
#include <commdlg.h> #include <commdlg.h>
#include <richedit.h> #include <richedit.h>
#include <stdio.h> #include <stdio.h>
#include <sys/stat.h>
#include "qcc.h" #include "qcc.h"
#include "gui.h" #include "gui.h"
/* /*
============== ==============
LoadFile LoadFile
@ -281,11 +280,14 @@ typedef struct editor_s {
char filename[MAX_PATH]; //abs char filename[MAX_PATH]; //abs
HWND window; HWND window;
HWND editpane; HWND editpane;
pbool modified;
time_t filemodifiedtime;
struct editor_s *next; struct editor_s *next;
} editor_t; } editor_t;
editor_t *editors; editor_t *editors;
void EditorReload(editor_t *editor);
int EditorSave(editor_t *edit); int EditorSave(editor_t *edit);
void EditFile(char *name, int line); void EditFile(char *name, int line);
pbool EditorModified(editor_t *e); pbool EditorModified(editor_t *e);
@ -318,7 +320,7 @@ void GenericMenu(WPARAM wParam)
break; break;
case IDM_ABOUT: case IDM_ABOUT:
MessageBox(NULL, "FTE QuakeC Compiler\nWritten by Forethough Entertainment.\nBasically that means it was written by Spike.\n\nIt has a few cool features, like a useful IDE.\n\nSupports:\nPrecompiler (with macros)\nArrays\n+= / -= / *= / /= operations.\nSwitch statements\nfor loops\nLots of optimisations.", "About", 0); MessageBox(NULL, "FTE QuakeC Compiler\nWritten by Forethough Entertainment.\n\nIt has a few cool features, like a semi-useful IDE.\n\nSupports:\nPrecompiler (with macros)\nArrays\n+= / -= / *= / /= operations.\nSwitch statements\nfor loops\nLots of optimisations.", "About", 0);
break; break;
case IDM_CASCADE: case IDM_CASCADE:
@ -409,7 +411,7 @@ static LONG CALLBACK EditorWndProc(HWND hWnd,UINT message,
{ {
case WM_CLOSE: case WM_CLOSE:
case WM_QUIT: case WM_QUIT:
if (EditorModified(editor)) if (editor->modified)
{ {
switch (MessageBox(hWnd, "Would you like to save?", editor->filename, MB_YESNOCANCEL)) switch (MessageBox(hWnd, "Would you like to save?", editor->filename, MB_YESNOCANCEL))
{ {
@ -478,22 +480,49 @@ static LONG CALLBACK EditorWndProc(HWND hWnd,UINT message,
return TRUE; return TRUE;
break; break;
case WM_COMMAND: case WM_COMMAND:
if (mdibox) if (HIWORD(wParam) == EN_CHANGE && (HWND)lParam == editor->editpane)
goto gdefault; {
EditorMenu(editor, wParam); if (!editor->modified)
{
char title[2048];
CHARRANGE chrg;
editor->modified = true;
if (EditorModified(editor))
if (MessageBox(NULL, "warning: file was modified externally. reload?", "Modified!", MB_YESNO) == IDYES)
EditorReload(editor);
SendMessage(editor->editpane, EM_EXGETSEL, 0, (LPARAM) &chrg);
if (editor->modified)
sprintf(title, "*%s:%i - FTEQCC Editor", editor->filename, 1+Edit_LineFromChar(editor->editpane, chrg.cpMin));
else
sprintf(title, "%s:%i - FTEQCC Editor", editor->filename, 1+Edit_LineFromChar(editor->editpane, chrg.cpMin));
SetWindowText(editor->window, title);
}
}
else
{
if (mdibox)
goto gdefault;
EditorMenu(editor, wParam);
}
break; break;
case WM_NOTIFY: case WM_NOTIFY:
{ {
NMHDR *nmhdr; NMHDR *nmhdr;
SELCHANGE *sel; SELCHANGE *sel;
char message[2048]; char title[2048];
nmhdr = (NMHDR *)lParam; nmhdr = (NMHDR *)lParam;
switch(nmhdr->code) switch(nmhdr->code)
{ {
case EN_SELCHANGE: case EN_SELCHANGE:
sel = (SELCHANGE *)nmhdr; sel = (SELCHANGE *)nmhdr;
sprintf(message, "%s:%i - FTEQCC Editor", editor->filename, 1+Edit_LineFromChar(editor->editpane, sel->chrg.cpMin)); if (editor->modified)
SetWindowText(editor->window, message); sprintf(title, "*%s:%i - FTEQCC Editor", editor->filename, 1+Edit_LineFromChar(editor->editpane, sel->chrg.cpMin));
else
sprintf(title, "%s:%i - FTEQCC Editor", editor->filename, 1+Edit_LineFromChar(editor->editpane, sel->chrg.cpMin));
SetWindowText(editor->window, title);
break; break;
} }
} }
@ -758,7 +787,7 @@ int Rehighlight(editor_t *edit)
InvalidateRect(edit->editpane, NULL, true); InvalidateRect(edit->editpane, NULL, true);
InvalidateRect(edit->window, NULL, true); InvalidateRect(edit->window, NULL, true);
SendMessage(edit->editpane, EM_SETEVENTMASK, 0, ENM_SELCHANGE); SendMessage(edit->editpane, EM_SETEVENTMASK, 0, ENM_SELCHANGE|ENM_CHANGE);
SendMessage(edit->editpane, EM_SETSCROLLPOS, 0, (LPARAM)&scrollpos); SendMessage(edit->editpane, EM_SETSCROLLPOS, 0, (LPARAM)&scrollpos);
SendMessage(edit->editpane, EM_EXSETSEL, 0, (LPARAM) &chrg); SendMessage(edit->editpane, EM_EXSETSEL, 0, (LPARAM) &chrg);
@ -845,11 +874,46 @@ int Rehighlight(editor_t *edit)
} }
#endif #endif
void EditorReload(editor_t *editor)
{
struct stat sbuf;
int flen;
char *file;
flen = QCC_FileSize(editor->filename);
if (flen >= 0)
{
file = malloc(flen+1);
QCC_ReadFile(editor->filename, file, flen);
file[flen] = 0;
}
SendMessage(editor->editpane, EM_SETEVENTMASK, 0, 0);
/*clear it out*/
Edit_SetSel(editor->editpane,0,Edit_GetTextLength(editor->editpane));
Edit_ReplaceSel(editor->editpane,"");
if (!fl_autohighlight)
{
GUIPrint(editor->editpane, file);
}
else
{
GUIFormattingPrint(editor->editpane, file);
}
free(file);
editor->modified = false;
stat(editor->filename, &sbuf);
editor->filemodifiedtime = sbuf.st_mtime;
SendMessage(editor->editpane, EM_SETEVENTMASK, 0, ENM_SELCHANGE|ENM_CHANGE);
}
void EditFile(char *name, int line) void EditFile(char *name, int line)
{ {
char title[1024]; char title[1024];
int flen;
char *file;
editor_t *neweditor; editor_t *neweditor;
WNDCLASS wndclass; WNDCLASS wndclass;
HMENU menu, menufile, menuhelp, menunavig; HMENU menu, menufile, menuhelp, menunavig;
@ -871,8 +935,7 @@ void EditFile(char *name, int line)
} }
} }
flen = QCC_FileSize(name); if (QCC_FileSize(name) == -1)
if (flen == -1)
{ {
MessageBox(NULL, "File not found.", "Error", 0); MessageBox(NULL, "File not found.", "Error", 0);
return; return;
@ -959,23 +1022,7 @@ void EditFile(char *name, int line)
return; return;
} }
flen = QCC_FileSize(name); EditorReload(neweditor);
file = malloc(flen+1);
QCC_ReadFile(name, file, flen);
file[flen] = 0;
SendMessage(neweditor->editpane, EM_SETEVENTMASK, 0, 0);
if (!fl_autohighlight)
{
GUIPrint(neweditor->editpane, file);
}
else
{
GUIFormattingPrint(neweditor->editpane, file);
}
SendMessage(neweditor->editpane, EM_SETEVENTMASK, 0, ENM_SELCHANGE);
if (line >= 0) if (line >= 0)
Edit_SetSel(neweditor->editpane, Edit_LineIndex(neweditor->editpane, line), Edit_LineIndex(neweditor->editpane, line+1)); Edit_SetSel(neweditor->editpane, Edit_LineIndex(neweditor->editpane, line), Edit_LineIndex(neweditor->editpane, line+1));
@ -992,6 +1039,7 @@ void EditFile(char *name, int line)
int EditorSave(editor_t *edit) int EditorSave(editor_t *edit)
{ {
struct stat sbuf;
int len; int len;
char *file; char *file;
len = Edit_GetTextLength(edit->editpane); len = Edit_GetTextLength(edit->editpane);
@ -1009,6 +1057,11 @@ int EditorSave(editor_t *edit)
} }
free(file); free(file);
/*now whatever is on disk should have the current time*/
edit->modified = false;
stat(edit->filename, &sbuf);
edit->filemodifiedtime = sbuf.st_mtime;
return true; return true;
} }
void EditorsRun(void) void EditorsRun(void)
@ -1046,26 +1099,14 @@ int GUIFileSize(char *fname)
return QCC_FileSize(fname); return QCC_FileSize(fname);
} }
/*checks if the file has been modified externally*/
pbool EditorModified(editor_t *e) pbool EditorModified(editor_t *e)
{ {
char *buffer; struct stat sbuf;
int elen, flen; stat(e->filename, &sbuf);
elen = Edit_GetTextLength(e->editpane); if (e->filemodifiedtime != sbuf.st_mtime)
flen = QCC_FileSize(e->filename);
if (elen != flen)
return true; return true;
buffer = malloc(elen+flen);
Edit_GetText(e->editpane, buffer, elen);
QCC_ReadFile(e->filename, buffer+elen, flen);
if (memcmp(buffer, buffer+elen, elen))
{
free(buffer);
return true;
}
free(buffer);
return false; return false;
} }
@ -1898,6 +1939,41 @@ void RunCompiler(char *args)
progexterns_t ext; progexterns_t ext;
progfuncs_t funcs; progfuncs_t funcs;
editor_t *editor;
for (editor = editors; editor; editor = editor->next)
{
if (editor->modified)
{
if (EditorModified(editor))
{
char msg[1024];
sprintf(msg, "%s is modified in both memory and on disk. Overwrite external modification? (saying no will reload from disk)", editor->filename);
switch(MessageBox(NULL, msg, "Modification conflict", MB_YESNOCANCEL))
{
case IDYES:
EditorSave(editor);
break;
case IDNO:
EditorReload(editor);
break;
case IDCANCEL:
break; /*compiling will use whatever is in memory*/
}
}
else
{
/*not modified on disk, but modified in memory? try and save it, cos we might as well*/
EditorSave(editor);
}
}
else
{
/*modified on disk but not in memory? just reload it off disk*/
if (EditorModified(editor))
EditorReload(editor);
}
}
memset(&funcs, 0, sizeof(funcs)); memset(&funcs, 0, sizeof(funcs));
funcs.parms = &ext; funcs.parms = &ext;
memset(&ext, 0, sizeof(ext)); memset(&ext, 0, sizeof(ext));

View file

@ -516,7 +516,7 @@ int WriteBodylessFuncs (int handle)
{ {
if (d->type->type == ev_function && !d->scope)// function parms are ok if (d->type->type == ev_function && !d->scope)// function parms are ok
{ {
if (d->initialized != 1 && d->references>0) if (!(d->initialized & 1) && d->references>0)
{ {
SafeWrite(handle, d->name, strlen(d->name)+1); SafeWrite(handle, d->name, strlen(d->name)+1);
ret++; ret++;
@ -1646,9 +1646,9 @@ void QCC_PR_BeginCompilation (void *memory, int memsize)
type_float = QCC_PR_NewType("float", ev_float); type_float = QCC_PR_NewType("float", ev_float);
type_vector = QCC_PR_NewType("vector", ev_vector); type_vector = QCC_PR_NewType("vector", ev_vector);
type_entity = QCC_PR_NewType("entity", ev_entity); type_entity = QCC_PR_NewType("entity", ev_entity);
type_field = QCC_PR_NewType("field", ev_field); type_field = QCC_PR_NewType("__field", ev_field);
type_function = QCC_PR_NewType("function", ev_function); type_function = QCC_PR_NewType("__function", ev_function);
type_pointer = QCC_PR_NewType("pointer", ev_pointer); type_pointer = QCC_PR_NewType("__pointer", ev_pointer);
type_integer = QCC_PR_NewType("__integer", ev_integer); type_integer = QCC_PR_NewType("__integer", ev_integer);
type_variant = QCC_PR_NewType("__variant", ev_variant); type_variant = QCC_PR_NewType("__variant", ev_variant);
@ -1741,7 +1741,7 @@ int QCC_PR_FinishCompilation (void)
bodylessfuncs = true; bodylessfuncs = true;
errors = true; errors = true;
} }
s_file = NULL; s_file = 0;
// errors = true; // errors = true;
} }
else if (d->initialized==2) else if (d->initialized==2)

View file

@ -951,8 +951,8 @@ void NPP_NQWriteByte(int dest, qbyte data) //replacement write func (nq to qw)
protocollen++; protocollen++;
if (data & DPSND_LARGESOUND) if (data & DPSND_LARGESOUND)
protocollen++; protocollen++;
#ifdef _MSC_VER #ifdef warningmsg
#pragma message("NPP_NQWriteByte: this ignores SVC_SOUND from nq mods (nexuiz)") #pragma warningmsg("NPP_NQWriteByte: this ignores SVC_SOUND from nq mods (nexuiz)")
#endif #endif
ignoreprotocol = true; ignoreprotocol = true;
break; break;

View file

@ -24,7 +24,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "sv_sql.h" #include "sv_sql.h"
#endif #endif
#define G_PROG G_FLOAT
#define Z_QC_TAG 2 #define Z_QC_TAG 2
#ifndef CLIENTONLY #ifndef CLIENTONLY
@ -64,7 +63,7 @@ cvar_t pr_maxedicts = CVARF("pr_maxedicts", "2048", CVAR_LATCH);
cvar_t pr_no_playerphysics = CVARF("pr_no_playerphysics", "0", CVAR_LATCH); cvar_t pr_no_playerphysics = CVARF("pr_no_playerphysics", "0", CVAR_LATCH);
cvar_t pr_no_parsecommand = CVARF("pr_no_parsecommand", "0", 0); cvar_t pr_no_parsecommand = CVARF("pr_no_parsecommand", "0", 0);
cvar_t progs = CVARAF("progs", "", "sv_progs", CVAR_ARCHIVE | CVAR_SERVERINFO | CVAR_NOTFROMSERVER); cvar_t pr_ssqc_progs = CVARAF("progs", "", "sv_progs", CVAR_ARCHIVE | CVAR_SERVERINFO | CVAR_NOTFROMSERVER);
cvar_t qc_nonetaccess = CVAR("qc_nonetaccess", "0"); //prevent write_... builtins from doing anything. This means we can run any mod, specific to any engine, on the condition that it also has a qw or nq crc. cvar_t qc_nonetaccess = CVAR("qc_nonetaccess", "0"); //prevent write_... builtins from doing anything. This means we can run any mod, specific to any engine, on the condition that it also has a qw or nq crc.
cvar_t pr_overridebuiltins = CVAR("pr_overridebuiltins", "1"); cvar_t pr_overridebuiltins = CVAR("pr_overridebuiltins", "1");
@ -135,8 +134,8 @@ func_t EndFrameQC; //a common extension
qboolean pr_items2; //hipnotic (or was it rogue?) qboolean pr_items2; //hipnotic (or was it rogue?)
nqglobalvars_t realpr_nqglobal_struct; globalptrs_t realpr_global_ptrs;
nqglobalvars_t *pr_nqglobal_struct = &realpr_nqglobal_struct; globalptrs_t *pr_global_ptrs = &realpr_global_ptrs;
progfuncs_t *svprogfuncs; progfuncs_t *svprogfuncs;
progparms_t svprogparms; progparms_t svprogparms;
@ -337,6 +336,54 @@ pbool SV_BadField(progfuncs_t *inst, edict_t *foo, const char *keyname, const ch
return false; return false;
} }
void PR_SV_FillWorldGlobals(world_t *w)
{
w->g.self = pr_global_ptrs->self;
w->g.other = pr_global_ptrs->other;
w->g.force_retouch = pr_global_ptrs->force_retouch;
w->g.physics_mode = pr_global_ptrs->physics_mode;
w->g.frametime = pr_global_ptrs->frametime;
w->g.newmis = pr_global_ptrs->newmis;
w->g.time = pr_global_ptrs->time;
}
void PR_SSQC_Relocated(progfuncs_t *pr, char *oldb, char *newb, int oldlen)
{
edict_t *ent;
int i;
union {
globalptrs_t *g;
char **c;
} b;
b.g = pr_global_ptrs;
for (i = 0; i < sizeof(*b.g)/sizeof(*b.c); i++)
{
if (b.c[i] >= oldb && b.c[i] < oldb+oldlen)
b.c[i] += newb - oldb;
}
PR_SV_FillWorldGlobals(&sv.world);
for (i = 0; i < sv.world.num_edicts; i++)
{
ent = EDICT_NUM(pr, i);
if ((char*)ent->xv >= oldb && (char*)ent->xv < oldb+oldlen)
ent->xv = (extentvars_t*)((char*)ent->xv - oldb + newb);
}
for (i = 0; sv.strings.model_precache[i]; i++)
{
if (sv.strings.model_precache[i] >= oldb && sv.strings.model_precache[i] < oldb+oldlen)
sv.strings.model_precache[i] += newb - oldb;
}
for (i = 0; i < MAX_CLIENTS; i++)
{
if (svs.clients[i].name >= oldb && svs.clients[i].name < oldb+oldlen)
svs.clients[i].name += newb - oldb;
if (svs.clients[i].team >= oldb && svs.clients[i].team < oldb+oldlen)
svs.clients[i].team += newb - oldb;
}
}
//int QCEditor (char *filename, int line, int nump, char **parms); //int QCEditor (char *filename, int line, int nump, char **parms);
void QC_Clear(void); void QC_Clear(void);
builtin_t pr_builtin[]; builtin_t pr_builtin[];
@ -468,6 +515,10 @@ void Q_SetProgsParms(qboolean forcompiler)
svprogparms.useeditor = QCEditor;//void (*useeditor) (char *filename, int line, int nump, char **parms); svprogparms.useeditor = QCEditor;//void (*useeditor) (char *filename, int line, int nump, char **parms);
//until its properly tested
if (pr_ssqc_memsize.ival == -2)
svprogparms.addressablerelocated = PR_SSQC_Relocated;
if (!svprogfuncs) if (!svprogfuncs)
{ {
sv.world.progs = svprogfuncs = InitProgs(&svprogparms); sv.world.progs = svprogfuncs = InitProgs(&svprogparms);
@ -475,7 +526,7 @@ void Q_SetProgsParms(qboolean forcompiler)
sv.world.Event_Touch = SVPR_Event_Touch; sv.world.Event_Touch = SVPR_Event_Touch;
sv.world.Event_Think = SVPR_Event_Think; sv.world.Event_Think = SVPR_Event_Think;
sv.world.Event_Sound = SVQ1_StartSound; sv.world.Event_Sound = SVQ1_StartSound;
sv.world.GetCModel = SVPR_GetCModel; sv.world.Get_CModel = SVPR_GetCModel;
PRSV_ClearThreads(); PRSV_ClearThreads();
PR_fclose_progs(svprogfuncs); PR_fclose_progs(svprogfuncs);
@ -524,6 +575,7 @@ void PR_Deinit(void)
void PR_LoadGlabalStruct(void) void PR_LoadGlabalStruct(void)
{ {
static float svphysicsmode = 2;
static float writeonly; static float writeonly;
static float dimension_send_default; static float dimension_send_default;
static float zero_default; static float zero_default;
@ -534,13 +586,13 @@ void PR_LoadGlabalStruct(void)
static vec3_t input_movevalues_default; static vec3_t input_movevalues_default;
int i; int i;
int *v; int *v;
nqglobalvars_t *pr_globals = pr_nqglobal_struct; globalptrs_t *pr_globals = pr_global_ptrs;
#define globalfloat(need,name) ((nqglobalvars_t*)pr_nqglobal_struct)->name = (float *)PR_FindGlobal(svprogfuncs, #name, 0, NULL); if (need && !((nqglobalvars_t*)pr_globals)->name) SV_Error("Could not find \""#name"\" export in progs\n"); #define globalfloat(need,name) (pr_globals)->name = (float *)PR_FindGlobal(svprogfuncs, #name, 0, NULL); if (need && !(pr_globals)->name) SV_Error("Could not find \""#name"\" export in progs\n");
#define globalint(need,name) ((nqglobalvars_t*)pr_globals)->name = (int *)PR_FindGlobal(svprogfuncs, #name, 0, NULL); if (need && !((nqglobalvars_t*)pr_globals)->name) SV_Error("Could not find export \""#name"\" in progs\n"); #define globalint(need,name) (pr_globals)->name = (int *)PR_FindGlobal(svprogfuncs, #name, 0, NULL); if (need && !(pr_globals)->name) SV_Error("Could not find export \""#name"\" in progs\n");
#define globalstring(need,name) ((nqglobalvars_t*)pr_globals)->name = (int *)PR_FindGlobal(svprogfuncs, #name, 0, NULL); if (need && !((nqglobalvars_t*)pr_globals)->name) SV_Error("Could not find export \""#name"\" in progs\n"); #define globalstring(need,name) (pr_globals)->name = (int *)PR_FindGlobal(svprogfuncs, #name, 0, NULL); if (need && !(pr_globals)->name) SV_Error("Could not find export \""#name"\" in progs\n");
#define globalvec(need,name) ((nqglobalvars_t*)pr_globals)->V_##name = (vec3_t *)PR_FindGlobal(svprogfuncs, #name, 0, NULL); if (need && !((nqglobalvars_t*)pr_globals)->V_##name) SV_Error("Could not find export \""#name"\" in progs\n"); #define globalvec(need,name) (pr_globals)->V_##name = (vec3_t *)PR_FindGlobal(svprogfuncs, #name, 0, NULL); if (need && !(pr_globals)->V_##name) SV_Error("Could not find export \""#name"\" in progs\n");
#define globalvec_(need,name) ((nqglobalvars_t*)pr_globals)->name = (vec3_t *)PR_FindGlobal(svprogfuncs, #name, 0, NULL); if (need && !((nqglobalvars_t*)pr_globals)->name) SV_Error("Could not find export \""#name"\" in progs\n"); #define globalvec_(need,name) (pr_globals)->name = (vec3_t *)PR_FindGlobal(svprogfuncs, #name, 0, NULL); if (need && !(pr_globals)->name) SV_Error("Could not find export \""#name"\" in progs\n");
#define globalfunc(need,name) ((nqglobalvars_t*)pr_globals)->name = (func_t *)PR_FindGlobal(svprogfuncs, #name, 0, NULL); if (!((nqglobalvars_t*)pr_globals)->name) {static func_t stripped##name; stripped##name = PR_FindFunction(svprogfuncs, #name, 0); if (stripped##name) ((nqglobalvars_t*)pr_globals)->name = &stripped##name; else if (need) SV_Error("Could not find function \""#name"\" in progs\n"); } #define globalfunc(need,name) (pr_globals)->name = (func_t *)PR_FindGlobal(svprogfuncs, #name, 0, NULL); if (!(pr_globals)->name) {static func_t stripped##name; stripped##name = PR_FindFunction(svprogfuncs, #name, 0); if (stripped##name) (pr_globals)->name = &stripped##name; else if (need) SV_Error("Could not find function \""#name"\" in progs\n"); }
// globalint(pad); // globalint(pad);
globalint (true, self); //we need the qw ones, but any in standard quake and not quakeworld, we don't really care about. globalint (true, self); //we need the qw ones, but any in standard quake and not quakeworld, we don't really care about.
globalint (true, other); globalint (true, other);
@ -598,9 +650,9 @@ void PR_LoadGlabalStruct(void)
memset(&evalc_pitch_speed, 0, sizeof(evalc_pitch_speed)); memset(&evalc_pitch_speed, 0, sizeof(evalc_pitch_speed));
for (i = 0; i < NUM_SPAWN_PARMS; i++) for (i = 0; i < NUM_SPAWN_PARMS; i++)
spawnparamglobals[i] = (float *)PR_FindGlobal(svprogfuncs, va("parm%i", i+1), 0, NULL); pr_global_ptrs->spawnparamglobals[i] = (float *)PR_FindGlobal(svprogfuncs, va("parm%i", i+1), 0, NULL);
#define ensureglobal(name,var) if (!((nqglobalvars_t*)pr_globals)->name) ((nqglobalvars_t*)pr_globals)->name = &var; #define ensureglobal(name,var) if (!(pr_globals)->name) (pr_globals)->name = &var;
// make sure these entries are always valid pointers // make sure these entries are always valid pointers
ensureglobal(dimension_send, dimension_send_default); ensureglobal(dimension_send, dimension_send_default);
@ -613,22 +665,22 @@ void PR_LoadGlabalStruct(void)
ensureglobal(input_buttons, input_buttons_default); ensureglobal(input_buttons, input_buttons_default);
// qtest renames and missing variables // qtest renames and missing variables
if (!((nqglobalvars_t*)pr_globals)->V_trace_plane_normal) if (!(pr_globals)->V_trace_plane_normal)
{ {
((nqglobalvars_t*)pr_globals)->V_trace_plane_normal = (vec3_t *)PR_FindGlobal(svprogfuncs, "trace_normal", 0, NULL); (pr_globals)->V_trace_plane_normal = (vec3_t *)PR_FindGlobal(svprogfuncs, "trace_normal", 0, NULL);
if (!((nqglobalvars_t*)pr_globals)->V_trace_plane_normal) if (!(pr_globals)->V_trace_plane_normal)
SV_Error("Could not find export trace_plane_normal in progs\n"); SV_Error("Could not find export trace_plane_normal in progs\n");
} }
if (!((nqglobalvars_t*)pr_globals)->V_trace_endpos) if (!(pr_globals)->V_trace_endpos)
{ {
((nqglobalvars_t*)pr_globals)->V_trace_endpos = (vec3_t *)PR_FindGlobal(svprogfuncs, "trace_impact", 0, NULL); (pr_globals)->V_trace_endpos = (vec3_t *)PR_FindGlobal(svprogfuncs, "trace_impact", 0, NULL);
if (!((nqglobalvars_t*)pr_globals)->V_trace_endpos) if (!(pr_globals)->V_trace_endpos)
SV_Error("Could not find export trace_endpos in progs\n"); SV_Error("Could not find export trace_endpos in progs\n");
} }
if (!((nqglobalvars_t*)pr_globals)->trace_fraction) if (!(pr_globals)->trace_fraction)
{ {
((nqglobalvars_t*)pr_globals)->trace_fraction = (float *)PR_FindGlobal(svprogfuncs, "trace_frac", 0, NULL); (pr_globals)->trace_fraction = (float *)PR_FindGlobal(svprogfuncs, "trace_frac", 0, NULL);
if (!((nqglobalvars_t*)pr_globals)->trace_fraction) if (!(pr_globals)->trace_fraction)
SV_Error("Could not find export trace_fraction in progs\n"); SV_Error("Could not find export trace_fraction in progs\n");
} }
ensureglobal(serverflags, zero_default); ensureglobal(serverflags, zero_default);
@ -641,6 +693,7 @@ void PR_LoadGlabalStruct(void)
ensureglobal(trace_plane_dist, writeonly); ensureglobal(trace_plane_dist, writeonly);
ensureglobal(trace_inopen, writeonly); ensureglobal(trace_inopen, writeonly);
ensureglobal(trace_inwater, writeonly); ensureglobal(trace_inwater, writeonly);
ensureglobal(physics_mode, svphysicsmode);
pr_global_struct->dimension_send = 255; pr_global_struct->dimension_send = 255;
pr_global_struct->serverflags = 0; pr_global_struct->serverflags = 0;
@ -676,20 +729,15 @@ void PR_LoadGlabalStruct(void)
EndFrameQC = PR_FindFunction (svprogfuncs, "EndFrame", PR_ANY); EndFrameQC = PR_FindFunction (svprogfuncs, "EndFrame", PR_ANY);
v = (int *)PR_globals(svprogfuncs, PR_CURRENT); v = (int *)PR_globals(svprogfuncs, PR_CURRENT);
QC_AddSharedVar(svprogfuncs, (int *)((nqglobalvars_t*)pr_nqglobal_struct)->self-v, 1); QC_AddSharedVar(svprogfuncs, (int *)(pr_global_ptrs)->self-v, 1);
QC_AddSharedVar(svprogfuncs, (int *)((nqglobalvars_t*)pr_nqglobal_struct)->other-v, 1); QC_AddSharedVar(svprogfuncs, (int *)(pr_global_ptrs)->other-v, 1);
QC_AddSharedVar(svprogfuncs, (int *)((nqglobalvars_t*)pr_nqglobal_struct)->time-v, 1); QC_AddSharedVar(svprogfuncs, (int *)(pr_global_ptrs)->time-v, 1);
pr_items2 = !!PR_FindGlobal(svprogfuncs, "items2", 0, NULL); pr_items2 = !!PR_FindGlobal(svprogfuncs, "items2", 0, NULL);
SV_ClearQCStats(); SV_ClearQCStats();
sv.world.g.self = pr_nqglobal_struct->self; PR_SV_FillWorldGlobals(&sv.world);
sv.world.g.other = pr_nqglobal_struct->other;
sv.world.g.force_retouch = pr_nqglobal_struct->force_retouch;
sv.world.g.frametime = pr_nqglobal_struct->frametime;
sv.world.g.newmis = pr_nqglobal_struct->newmis;
sv.world.g.time = pr_nqglobal_struct->time;
/*Hexen2 has lots of extra stats, which I don't want special support for, so list them here and send them as for csqc*/ /*Hexen2 has lots of extra stats, which I don't want special support for, so list them here and send them as for csqc*/
if (progstype == PROG_H2) if (progstype == PROG_H2)
@ -1101,7 +1149,7 @@ void PR_Init(void)
Cvar_Register (&temp1, cvargroup_progs); Cvar_Register (&temp1, cvargroup_progs);
Cvar_Register (&noexit, cvargroup_progs); Cvar_Register (&noexit, cvargroup_progs);
Cvar_Register (&progs, cvargroup_progs); Cvar_Register (&pr_ssqc_progs, cvargroup_progs);
Cvar_Register (&pr_compatabilitytest, cvargroup_progs); Cvar_Register (&pr_compatabilitytest, cvargroup_progs);
Cvar_Register (&qc_nonetaccess, cvargroup_progs); Cvar_Register (&qc_nonetaccess, cvargroup_progs);
@ -1202,13 +1250,15 @@ void Q_InitProgs(void)
} }
} }
if (*progs.string && strlen(progs.string)<64 && *progs.string != '*') //a * is a special case to not load a q2 dll. /*if pr_ssqc_progs cvar is set, override the default*/
if (*pr_ssqc_progs.string && strlen(pr_ssqc_progs.string)<64 && *pr_ssqc_progs.string != '*') //a * is a special case to not load a q2 dll.
{ {
Q_strncpyz(addons, progs.string, MAX_QPATH); Q_strncpyz(addons, pr_ssqc_progs.string, MAX_QPATH);
COM_DefaultExtension(addons, ".dat", sizeof(addons)); COM_DefaultExtension(addons, ".dat", sizeof(addons));
} }
oldprnum= AddProgs(addons); oldprnum= AddProgs(addons);
/*try to load qwprogs.dat if we didn't manage to load one yet*/
if (oldprnum < 0 && strcmp(addons, "qwprogs.dat")) if (oldprnum < 0 && strcmp(addons, "qwprogs.dat"))
{ {
#ifndef SERVERONLY #ifndef SERVERONLY
@ -1218,6 +1268,7 @@ void Q_InitProgs(void)
oldprnum= AddProgs("qwprogs.dat"); oldprnum= AddProgs("qwprogs.dat");
} }
/*try to load qwprogs.dat if we didn't manage to load one yet*/
if (oldprnum < 0 && strcmp(addons, "progs.dat")) if (oldprnum < 0 && strcmp(addons, "progs.dat"))
{ {
#ifndef SERVERONLY #ifndef SERVERONLY
@ -2804,7 +2855,7 @@ already running on that entity/channel pair.
An attenuation of 0 will play full volume everywhere in the level. An attenuation of 0 will play full volume everywhere in the level.
Larger attenuations will drop off. Larger attenuations will drop off.
pitchadj is a number between -128 and 127. values greater than 0 will result in a higher pitch, less than 0 gives lower pitch. pitchadj is a percent. values greater than 100 will result in a lower pitch, less than 100 gives a higher pitch.
================= =================
*/ */
@ -4423,7 +4474,7 @@ void QCBUILTIN PF_WriteAngle (progfuncs_t *prinst, struct globalvars_s *pr_globa
client_t *cl = Write_GetClient(); client_t *cl = Write_GetClient();
if (!cl) if (!cl)
return; return;
ClientReliableCheckBlock(cl, 1); ClientReliableCheckBlock(cl, 4);
ClientReliableWrite_Angle(cl, G_FLOAT(OFS_PARM1)); ClientReliableWrite_Angle(cl, G_FLOAT(OFS_PARM1));
} }
else else
@ -4881,8 +4932,8 @@ void QCBUILTIN PF_setspawnparms (progfuncs_t *prinst, struct globalvars_s *pr_gl
client = svs.clients + (i-1); client = svs.clients + (i-1);
for (i=0 ; i< NUM_SPAWN_PARMS ; i++) for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
if (spawnparamglobals[i]) if (pr_global_ptrs->spawnparamglobals[i])
*spawnparamglobals[i] = client->spawn_parms[i]; *pr_global_ptrs->spawnparamglobals[i] = client->spawn_parms[i];
} }
/* /*
@ -6649,6 +6700,7 @@ static void QCBUILTIN PF_h2starteffect(progfuncs_t *prinst, struct globalvars_s
switch(efnum) switch(efnum)
{ {
case ce_rain: case ce_rain:
/*this effect is meant to be persistant (endeffect is never used)*/
//min = G_VECTOR(OFS_PARM1); //min = G_VECTOR(OFS_PARM1);
//max = G_VECTOR(OFS_PARM2); //max = G_VECTOR(OFS_PARM2);
//size = G_VECTOR(OFS_PARM3); //size = G_VECTOR(OFS_PARM3);
@ -6662,6 +6714,7 @@ static void QCBUILTIN PF_h2starteffect(progfuncs_t *prinst, struct globalvars_s
return; return;
break; break;
case ce_snow: case ce_snow:
/*this effect is meant to be persistant (endeffect is never used)*/
//min = G_VECTOR(OFS_PARM1); //min = G_VECTOR(OFS_PARM1);
//max = G_VECTOR(OFS_PARM2); //max = G_VECTOR(OFS_PARM2);
//flags = G_FLOAT(OFS_PARM3); //flags = G_FLOAT(OFS_PARM3);
@ -6672,6 +6725,7 @@ static void QCBUILTIN PF_h2starteffect(progfuncs_t *prinst, struct globalvars_s
return; return;
break; break;
case ce_fountain: case ce_fountain:
/*this effect is meant to be persistant (endeffect is never used)*/
//org = G_VECTOR(OFS_PARM1); //org = G_VECTOR(OFS_PARM1);
//angle = G_VECTOR(OFS_PARM2); //angle = G_VECTOR(OFS_PARM2);
//dir = G_VECTOR(OFS_PARM3); //dir = G_VECTOR(OFS_PARM3);
@ -6682,6 +6736,7 @@ static void QCBUILTIN PF_h2starteffect(progfuncs_t *prinst, struct globalvars_s
return; return;
break; break;
case ce_quake: case ce_quake:
/*this effect is meant to be persistant*/
org = G_VECTOR(OFS_PARM1); org = G_VECTOR(OFS_PARM1);
//radius = G_FLOAT(OFS_PARM2); /*discard: always 500/3 */ //radius = G_FLOAT(OFS_PARM2); /*discard: always 500/3 */
@ -6837,7 +6892,7 @@ static void QCBUILTIN PF_h2starteffect(progfuncs_t *prinst, struct globalvars_s
//angle = G_VECTOR(OFS_PARM3); /*discard: angle is a function of the dir*/ //angle = G_VECTOR(OFS_PARM3); /*discard: angle is a function of the dir*/
//avelocity = G_VECTOR(OFS_PARM4);/*discard: avelocity is a function of the dir*/ //avelocity = G_VECTOR(OFS_PARM4);/*discard: avelocity is a function of the dir*/
/*FIXME: persistant until removed*/ /*FIXME: meant to be persistant until removed*/
if (h2customtents[efnum] != -1) if (h2customtents[efnum] != -1)
{ {
SV_CustomTEnt_Spawn(h2customtents[efnum], org, NULL, 1, dir); SV_CustomTEnt_Spawn(h2customtents[efnum], org, NULL, 1, dir);
@ -6867,121 +6922,14 @@ static void QCBUILTIN PF_h2starteffect(progfuncs_t *prinst, struct globalvars_s
} }
Con_Printf("FTE-H2 FIXME: Effect %i doesn't have an effect registered\nTell Spike!\n", efnum); Con_Printf("FTE-H2 FIXME: Effect %i doesn't have an effect registered\nTell Spike!\n", efnum);
#if 0
switch((int)G_FLOAT(OFS_PARM0))
{
case 4: //white_smoke
SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/whtsmk1.spr"), 0, 5, 1/G_FLOAT(OFS_PARM3));
break;
case 6: //yellowspark
SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/spark.spr"), 0, 10, 20);
break;
case 7: //sm_circle
SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/fcircle.spr"), 0, 6, 20);
break;
case 9: //sm_white_flash
SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/sm_white.spr"), 0, 3, 20);
break;
case 11: //yellowred_flash
SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/yr_flsh.spr"), 0, 21, 20);
break;
case 13: //sm_blue_flash
SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/bluflash.spr"), 0, 5, 20);
break;
case 14: //red_flash
SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/redspt.spr"), 0, 5, 20);
break;
case 15: //sm_explosion
SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/sm_expld.spr"), 0, 12, 20);
break;
case 16: //lg_explosion
SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/bg_expld.spr"), 0, 12, 20);
break;
case 17: //floor_explosion
SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/fl_expld.spr"), 0, 20, 20);
break;
case 20: //green_smoke
//parm1 = vel
SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/grnsmk1.spr"), 0, 8, 1/G_FLOAT(OFS_PARM3));
break;
case 24: //redspark
SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/rspark.spr"), 0, 10, 20);
break;
case 25: //greenspark
SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/gspark.spr"), 0, 10, 20);
break;
case 26: //telesmk1
SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/telesmk1.spr"), 0, 4, 1/G_FLOAT(OFS_PARM3));
break;
case 28: //icehit
SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/icehit.spr"), 0, 6, 20);
break;
case 33: //new_explosion
SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/gen_expl.spr"), 0, 14, 20);
break;
case 34: //magic_missile_explosion
SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/mm_explod.spr"), 0, 50, 20);
break;
case 42: //flamestream
SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/flamestr.spr"), 0, 12, 20);
break;
case 45: //bldrn_expl
SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/xplsn_1.spr"), 0, 7, 20);
break;
case 47: //acid_hit
SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/axplsn_2.spr"), 0, 14, 20);
break;
case 48: //firewall_small
SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/firewal1.spr"), 0, 18, 20);
break;
case 49: //firewall_medium
SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/firewal5.spr"), 0, 30, 20);
break;
case 50: //firewall_large
SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/firewal4.spr"), 0, 29, 20);
break;
case 54: //fboom
SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/fboom.spr"), 0, 14, 20);
break;
case 56: //bomb
SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/pow.spr"), 0, 6, 20);
break;
case 5: //bluespark
case 43: //snow
case 46: //acid_muzzfl
case 51: //lball_expl
case 52: //acid_splat
case 53: //acid_expl
case 57: //brn_bounce
case 58: //lshock
case 38: //teleporterpuffs
case 39: //teleporterbody
case 62: //onfire
break;
case 40: //boneshard
// SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/boneshot.mdl"), 0, 50, 20);
// break;
case 2: //fountain
case 55: //chunk
Con_DPrintf("Start unsupported effect %i\n", (int)G_FLOAT(OFS_PARM0));
break;
default:
Con_Printf("Start effect %i\n", (int)G_FLOAT(OFS_PARM0));
break;
}
#endif
} }
static void QCBUILTIN PF_h2endeffect(progfuncs_t *prinst, struct globalvars_s *pr_globals) static void QCBUILTIN PF_h2endeffect(progfuncs_t *prinst, struct globalvars_s *pr_globals)
{ {
Con_DPrintf("Stop effect %i\n", (int)G_FLOAT(OFS_PARM0)); int ign = G_FLOAT(OFS_PARM0);
int index = G_FLOAT(OFS_PARM1);
Con_DPrintf("Stop effect %i\n", index);
} }
static void QCBUILTIN PF_h2rain_go(progfuncs_t *prinst, struct globalvars_s *pr_globals) static void QCBUILTIN PF_h2rain_go(progfuncs_t *prinst, struct globalvars_s *pr_globals)
@ -6994,7 +6942,7 @@ static void QCBUILTIN PF_h2rain_go(progfuncs_t *prinst, struct globalvars_s *pr_
float colour = G_FLOAT(OFS_PARM4); float colour = G_FLOAT(OFS_PARM4);
float count = G_FLOAT(OFS_PARM5); float count = G_FLOAT(OFS_PARM5);
*/ */
Con_DPrintf("rain go\n"); Con_DPrintf("FTE-H2 FIXME: rain_go not implemented\n");
} }
static void QCBUILTIN PF_h2StopSound(progfuncs_t *prinst, struct globalvars_s *pr_globals) static void QCBUILTIN PF_h2StopSound(progfuncs_t *prinst, struct globalvars_s *pr_globals)
@ -7010,7 +6958,7 @@ static void QCBUILTIN PF_h2StopSound(progfuncs_t *prinst, struct globalvars_s *p
static void QCBUILTIN PF_h2updatesoundpos(progfuncs_t *prinst, struct globalvars_s *pr_globals) static void QCBUILTIN PF_h2updatesoundpos(progfuncs_t *prinst, struct globalvars_s *pr_globals)
{ {
Con_DPrintf("updatesoundpos\n"); Con_DPrintf("FTE-H2 FIXME: updatesoundpos not implemented\n");
} }
static void QCBUILTIN PF_h2whiteflash(progfuncs_t *prinst, struct globalvars_s *pr_globals) static void QCBUILTIN PF_h2whiteflash(progfuncs_t *prinst, struct globalvars_s *pr_globals)
@ -7019,7 +6967,7 @@ static void QCBUILTIN PF_h2whiteflash(progfuncs_t *prinst, struct globalvars_s *
broadcast a stuffcmd, I guess, to flash the screen white broadcast a stuffcmd, I guess, to flash the screen white
Only seen this occur once: after killing pravus. Only seen this occur once: after killing pravus.
*/ */
Con_DPrintf("white flash\n"); Con_DPrintf("FTE-H2 FIXME: whiteflash not implemented\n");
} }
static void QCBUILTIN PF_h2getstring(progfuncs_t *prinst, struct globalvars_s *pr_globals) static void QCBUILTIN PF_h2getstring(progfuncs_t *prinst, struct globalvars_s *pr_globals)
@ -7150,8 +7098,8 @@ static void QCBUILTIN PF_CustomTEnt(progfuncs_t *prinst, struct globalvars_s *pr
static void QCBUILTIN PF_sv_particleeffectnum(progfuncs_t *prinst, struct globalvars_s *pr_globals) static void QCBUILTIN PF_sv_particleeffectnum(progfuncs_t *prinst, struct globalvars_s *pr_globals)
{ {
#ifdef PEXT_CSQC #ifdef PEXT_CSQC
#ifdef _MSC_VER #ifdef warningmsg
#pragma message("PF_sv_particleeffectnum: which effect index values to use?") #pragma warningmsg("PF_sv_particleeffectnum: which effect index values to use?")
#endif #endif
char *efname = PR_GetStringOfs(prinst, OFS_PARM0); char *efname = PR_GetStringOfs(prinst, OFS_PARM0);
G_FLOAT(OFS_RETURN) = COM_Effectinfo_ForName(efname); G_FLOAT(OFS_RETURN) = COM_Effectinfo_ForName(efname);
@ -7338,14 +7286,19 @@ static void QCBUILTIN PF_Fork(progfuncs_t *prinst, struct globalvars_s *pr_globa
{ {
qcstate_t *state; qcstate_t *state;
struct qcthread_s *thread; struct qcthread_s *thread;
float sleeptime;
if (*svprogfuncs->callargc >= 1)
sleeptime = G_FLOAT(OFS_PARM0);
else
sleeptime = 0;
thread = svprogfuncs->Fork(svprogfuncs); thread = svprogfuncs->Fork(svprogfuncs);
state = svprogfuncs->parms->memalloc(sizeof(qcstate_t)); state = svprogfuncs->parms->memalloc(sizeof(qcstate_t));
state->next = qcthreads; state->next = qcthreads;
qcthreads = state; qcthreads = state;
state->resumetime = sv.time; state->resumetime = sv.time + sleeptime;
state->self = NUM_FOR_EDICT(svprogfuncs, PROG_TO_EDICT(svprogfuncs, pr_global_struct->self)); state->self = NUM_FOR_EDICT(svprogfuncs, PROG_TO_EDICT(svprogfuncs, pr_global_struct->self));
state->other = NUM_FOR_EDICT(svprogfuncs, PROG_TO_EDICT(svprogfuncs, pr_global_struct->other)); state->other = NUM_FOR_EDICT(svprogfuncs, PROG_TO_EDICT(svprogfuncs, pr_global_struct->other));
state->thread = thread; state->thread = thread;
@ -8250,8 +8203,8 @@ static void QCBUILTIN PF_sv_gettaginfo(progfuncs_t *prinst, struct globalvars_s
if (ent->xv->tag_entity) if (ent->xv->tag_entity)
{ {
#ifdef _MSC_VER #ifdef warningmsg
#pragma message("PF_sv_gettaginfo: This function doesn't honour attachments") #pragma warningmsg("PF_sv_gettaginfo: This function doesn't honour attachments")
#endif #endif
Con_Printf("PF_sv_gettaginfo doesn't support attachments\n"); Con_Printf("PF_sv_gettaginfo doesn't support attachments\n");
} }
@ -8300,8 +8253,8 @@ static void QCBUILTIN PF_runclientphys(progfuncs_t *prinst, struct globalvars_s
unsigned int msecs; unsigned int msecs;
edict_t *ent = G_EDICT(prinst, OFS_PARM0); edict_t *ent = G_EDICT(prinst, OFS_PARM0);
edict_t *touched; edict_t *touched;
if (pr_nqglobal_struct->clientcommandframe) if (pr_global_ptrs->clientcommandframe)
pmove.sequence = *pr_nqglobal_struct->clientcommandframe; pmove.sequence = *pr_global_ptrs->clientcommandframe;
else else
pmove.sequence = 0; pmove.sequence = 0;
if (host_client && host_client->edict == ent) if (host_client && host_client->edict == ent)

View file

@ -1368,7 +1368,7 @@ qboolean PR_LoadQ1QVM(void)
sv.world.Event_Touch = Q1QVM_Event_Touch; sv.world.Event_Touch = Q1QVM_Event_Touch;
sv.world.Event_Think = Q1QVM_Event_Think; sv.world.Event_Think = Q1QVM_Event_Think;
sv.world.GetCModel = SVPR_GetCModel; sv.world.Get_CModel = SVPR_GetCModel;
sv.world.num_edicts = 0; //we're not ready for most of the builtins yet sv.world.num_edicts = 0; //we're not ready for most of the builtins yet
sv.world.max_edicts = 0; //so clear these out, just in case sv.world.max_edicts = 0; //so clear these out, just in case
@ -1414,12 +1414,12 @@ qboolean PR_LoadQ1QVM(void)
//WARNING: global is not remapped yet... //WARNING: global is not remapped yet...
//This code is written evilly, but works well enough //This code is written evilly, but works well enough
#define globalint(required, name) pr_nqglobal_struct->name = (int*)((char*)VM_MemoryBase(q1qvm)+(qintptr_t)&gd->global->name) //the logic of this is somewhat crazy #define globalint(required, name) pr_global_ptrs->name = (int*)((char*)VM_MemoryBase(q1qvm)+(qintptr_t)&gd->global->name) //the logic of this is somewhat crazy
#define globalfloat(required, name) pr_nqglobal_struct->name = (float*)((char*)VM_MemoryBase(q1qvm)+(qintptr_t)&gd->global->name) #define globalfloat(required, name) pr_global_ptrs->name = (float*)((char*)VM_MemoryBase(q1qvm)+(qintptr_t)&gd->global->name)
#define globalstring(required, name) pr_nqglobal_struct->name = (string_t*)((char*)VM_MemoryBase(q1qvm)+(qintptr_t)&gd->global->name) #define globalstring(required, name) pr_global_ptrs->name = (string_t*)((char*)VM_MemoryBase(q1qvm)+(qintptr_t)&gd->global->name)
#define globalvec(required, name) pr_nqglobal_struct->V_##name = (vec3_t*)((char*)VM_MemoryBase(q1qvm)+(qintptr_t)&gd->global->name) #define globalvec(required, name) pr_global_ptrs->V_##name = (vec3_t*)((char*)VM_MemoryBase(q1qvm)+(qintptr_t)&gd->global->name)
#define globalfunc(required, name) pr_nqglobal_struct->name = (int*)((char*)VM_MemoryBase(q1qvm)+(qintptr_t)&gd->global->name) #define globalfunc(required, name) pr_global_ptrs->name = (int*)((char*)VM_MemoryBase(q1qvm)+(qintptr_t)&gd->global->name)
#define globalfloatnull(required, name) pr_nqglobal_struct->name = NULL #define globalfloatnull(required, name) pr_global_ptrs->name = NULL
globalint (true, self); //we need the qw ones, but any in standard quake and not quakeworld, we don't really care about. globalint (true, self); //we need the qw ones, but any in standard quake and not quakeworld, we don't really care about.
globalint (true, other); globalint (true, other);
globalint (true, world); globalint (true, world);
@ -1463,15 +1463,15 @@ qboolean PR_LoadQ1QVM(void)
globalfunc (false, SetNewParms); globalfunc (false, SetNewParms);
globalfunc (false, SetChangeParms); globalfunc (false, SetChangeParms);
pr_nqglobal_struct->trace_surfaceflags = &writable; pr_global_ptrs->trace_surfaceflags = &writable;
pr_nqglobal_struct->trace_endcontents = &writable; pr_global_ptrs->trace_endcontents = &writable;
pr_nqglobal_struct->dimension_send = &dimensionsend; pr_global_ptrs->dimension_send = &dimensionsend;
dimensionsend = 255; dimensionsend = 255;
for (i = 0; i < 16; i++) for (i = 0; i < 16; i++)
spawnparamglobals[i] = (float*)((char*)VM_MemoryBase(q1qvm)+(qintptr_t)(&gd->global->parm1 + i)); pr_global_ptrs->spawnparamglobals[i] = (float*)((char*)VM_MemoryBase(q1qvm)+(qintptr_t)(&gd->global->parm1 + i));
for (; i < NUM_SPAWN_PARMS; i++) for (; i < NUM_SPAWN_PARMS; i++)
spawnparamglobals[i] = NULL; pr_global_ptrs->spawnparamglobals[i] = NULL;
sv.world.progs = &q1qvmprogfuncs; sv.world.progs = &q1qvmprogfuncs;

View file

@ -35,6 +35,7 @@ typedef struct globalvars_s
} param[8]; } param[8];
} globalvars_t; } globalvars_t;
#define NUM_SPAWN_PARMS 64
typedef struct nqglobalvars_s typedef struct nqglobalvars_s
{ {
int *self; int *self;
@ -81,13 +82,14 @@ typedef struct nqglobalvars_s
float *cycle_wrapped; float *cycle_wrapped;
float *dimension_send; float *dimension_send;
float *physics_mode;
float *clientcommandframe; float *clientcommandframe;
float *input_timelength; float *input_timelength;
vec3_t *input_angles; vec3_t *input_angles;
vec3_t *input_movevalues; vec3_t *input_movevalues;
float *input_buttons; float *input_buttons;
} nqglobalvars_t; float *spawnparamglobals[NUM_SPAWN_PARMS];
} globalptrs_t;
#define P_VEC(v) (pr_global_struct->V_##v) #define P_VEC(v) (pr_global_struct->V_##v)
@ -229,7 +231,7 @@ and the extension fields are added on the end and can have extra vm-specific stu
comfieldfloat(glow_size);\ comfieldfloat(glow_size);\
comfieldfloat(glow_color);\ comfieldfloat(glow_color);\
comfieldfloat(glow_trail);\ comfieldfloat(glow_trail);\
comfieldvector(color);\ comfieldvector(color);/*Hexen2 has a .float color, the warnings should be benign*/ \
comfieldfloat(light_lev);\ comfieldfloat(light_lev);\
comfieldfloat(style);\ comfieldfloat(style);\
comfieldfloat(pflags);\ comfieldfloat(pflags);\

View file

@ -26,9 +26,6 @@ struct edict_s;
#define MAX_PROGS 64 #define MAX_PROGS 64
#define MAXADDONS 16 #define MAXADDONS 16
#define NUM_SPAWN_PARMS 64 //moved from server.h because of include ordering :(.
void SVQ1_CvarChanged(cvar_t *var); void SVQ1_CvarChanged(cvar_t *var);
#define NewGetEdictFieldValue GetEdictFieldValue #define NewGetEdictFieldValue GetEdictFieldValue
void Q_SetProgsParms(qboolean forcompiler); void Q_SetProgsParms(qboolean forcompiler);
@ -104,12 +101,9 @@ typedef struct edict_s
#include "progslib.h" #include "progslib.h"
#undef pr_global_struct #undef pr_global_struct
//#define pr_nqglobal_struct *((nqglobalvars_t*)pr_globals) #define pr_global_struct *pr_global_ptrs
#define pr_global_struct *pr_nqglobal_struct
float *spawnparamglobals[NUM_SPAWN_PARMS]; extern globalptrs_t *pr_global_ptrs;
extern nqglobalvars_t *pr_nqglobal_struct;
extern progfuncs_t *svprogfuncs; //instance extern progfuncs_t *svprogfuncs; //instance
extern progparms_t svprogparms; extern progparms_t svprogparms;

View file

@ -330,12 +330,12 @@ void SV_Loadgame_f(void)
if (version == 5) if (version == 5)
{ {
progstype = PROG_NQ; progstype = PROG_NQ;
Cvar_Set ("progs", "progs.dat"); //NQ's progs. Cvar_SetVar (pr_ssqc_progs, "progs.dat"); //NQ's progs.
} }
else else
{ {
progstype = PROG_QW; progstype = PROG_QW;
Cvar_Set ("progs", "spprogs.dat"); //zquake's single player qw progs. Cvar_SetVar (&pr_ssqc_progs, "spprogs.dat"); //zquake's single player qw progs.
} }
pt = 0; pt = 0;
} }
@ -722,8 +722,8 @@ qboolean SV_LoadLevelCache(char *savename, char *level, char *startspot, qboolea
e2->_float = 1; e2->_float = 1;
for (j=0 ; j< NUM_SPAWN_PARMS ; j++) for (j=0 ; j< NUM_SPAWN_PARMS ; j++)
{ {
if (spawnparamglobals[j]) if (pr_global_ptrs->spawnparamglobals[j])
*spawnparamglobals[j] = host_client->spawn_parms[j]; *pr_global_ptrs->spawnparamglobals[j] = host_client->spawn_parms[j];
} }
pr_global_struct->time = sv.world.physicstime; pr_global_struct->time = sv.world.physicstime;
pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, ent); pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, ent);
@ -911,7 +911,6 @@ void SV_Savegame (char *savename)
extern cvar_t temp1; extern cvar_t temp1;
extern cvar_t noexit; extern cvar_t noexit;
extern cvar_t pr_maxedicts; extern cvar_t pr_maxedicts;
extern cvar_t progs;
client_t *cl; client_t *cl;
@ -989,7 +988,7 @@ void SV_Savegame (char *savename)
VFS_PRINTF (f, "temp1 \"%s\"\n", temp1.string); VFS_PRINTF (f, "temp1 \"%s\"\n", temp1.string);
VFS_PRINTF (f, "noexit \"%s\"\n", noexit.string); VFS_PRINTF (f, "noexit \"%s\"\n", noexit.string);
VFS_PRINTF (f, "pr_maxedicts\t \"%s\"\n", pr_maxedicts.string); VFS_PRINTF (f, "pr_maxedicts\t \"%s\"\n", pr_maxedicts.string);
VFS_PRINTF (f, "progs \"%s\"\n", progs.string); VFS_PRINTF (f, "progs \"%s\"\n", pr_ssqc_progs.string);
VFS_PRINTF (f, "set nextserver \"%s\"\n", Cvar_Get("nextserver", "", 0, "")->string); VFS_PRINTF (f, "set nextserver \"%s\"\n", Cvar_Get("nextserver", "", 0, "")->string);
VFS_PRINTF (f, "}\n"); VFS_PRINTF (f, "}\n");

View file

@ -515,6 +515,7 @@ typedef struct client_s
SCP_QUAKE3, SCP_QUAKE3,
//all the below are considered netquake clients. //all the below are considered netquake clients.
SCP_NETQUAKE, SCP_NETQUAKE,
SCP_FITZ666,
SCP_DARKPLACES6, SCP_DARKPLACES6,
SCP_DARKPLACES7 //extra prediction stuff SCP_DARKPLACES7 //extra prediction stuff
//note, nq is nq+ //note, nq is nq+
@ -842,10 +843,10 @@ typedef struct
//define EF_BRIGHTFIELD 1 //define EF_BRIGHTFIELD 1
//define EF_MUZZLEFLASH 2 //define EF_MUZZLEFLASH 2
#define EF_BRIGHTLIGHT 4 //#define EF_BRIGHTLIGHT (1<<2)
#define EF_DIMLIGHT 8 //#define EF_DIMLIGHT (1<<4)
#define EF_FULLBRIGHT 512 //#define EF_FULLBRIGHT 512
#define SPAWNFLAG_NOT_EASY (1<<8) #define SPAWNFLAG_NOT_EASY (1<<8)
@ -895,6 +896,7 @@ extern cvar_t sv_antilag_frac;
extern netadr_t master_adr[MAX_MASTERS]; // address of the master server extern netadr_t master_adr[MAX_MASTERS]; // address of the master server
extern cvar_t pr_ssqc_progs;
extern cvar_t spawn; extern cvar_t spawn;
extern cvar_t teamplay; extern cvar_t teamplay;
extern cvar_t deathmatch; extern cvar_t deathmatch;

View file

@ -41,32 +41,6 @@ cvar_t sv_cheats = SCVARF("sv_cheats", "0", CVAR_LATCH);
extern cvar_t sv_public; extern cvar_t sv_public;
void deleetstring(char *match, char *leet)
{
char *s = match;
char *s2 = leet;
while(*s2)
{
*s = *s2 & ~128;
s2++;
if (*s == '3')
*s = 'e';
else if (*s == '4')
*s = 'a';
else if (*s == '1' || *s == '7')
*s = 'l';
else if (*s >= 18 && *s < 27)
*s = *s - 18 + '0';
else if (*s >= 'A' && *s <= 'Z')
*s = *s - 'A' + 'a';
else if (*s == ' ' || *s == '~')
continue;
s++;
}
*s = '\0';
}
//generic helper function for naming players. //generic helper function for naming players.
client_t *SV_GetClientForString(char *name, int *id) client_t *SV_GetClientForString(char *name, int *id)
{ {
@ -511,7 +485,15 @@ void SV_Map_f (void)
issamelevel = true; issamelevel = true;
if (!*level) if (!*level)
{
sv.mapchangelocked = true;
if (Cmd_AliasExist("startmap_dm", RESTRICT_LOCAL))
{
Cbuf_AddText("startmap_dm", Cmd_ExecLevel);
return;
}
Q_strncpyz(level, "start", sizeof(level)); Q_strncpyz(level, "start", sizeof(level));
}
//override the startspot //override the startspot
Q_strncpyz(spot, Info_ValueForKey(svs.info, "*startspot"), sizeof(spot)); Q_strncpyz(spot, Info_ValueForKey(svs.info, "*startspot"), sizeof(spot));

View file

@ -582,7 +582,7 @@ void SV_WriteDelta (entity_state_t *from, entity_state_t *to, sizebuf_t *msg, qb
evenmorebits |= U_ENTITYDBL2; evenmorebits |= U_ENTITYDBL2;
if (to->number >= 2048) if (to->number >= 2048)
SV_Error ("Entity number >= 2048"); return;
} }
else else
evenmorebits |= U_ENTITYDBL; evenmorebits |= U_ENTITYDBL;
@ -872,10 +872,10 @@ void SV_EmitPacketEntities (client_t *client, packet_entities_t *to, sizebuf_t *
void SVDP_EmitEntityDelta(entity_state_t *from, entity_state_t *to, sizebuf_t *msg, qboolean isnew) void SVDP_EmitEntityDelta(entity_state_t *from, entity_state_t *to, sizebuf_t *msg, qboolean isnew)
{ {
int bits; int bits;
if (!isnew && !memcmp(from, to, sizeof(entity_state_t))) // if (!isnew && !memcmp(from, to, sizeof(entity_state_t)))
{ // {
return; //didn't change // return; //didn't change
} // }
bits = 0; bits = 0;
if (isnew) if (isnew)
@ -883,6 +883,10 @@ void SVDP_EmitEntityDelta(entity_state_t *from, entity_state_t *to, sizebuf_t *m
bits |= E5_FULLUPDATE; bits |= E5_FULLUPDATE;
} }
bits |= E5_MODEL;
bits |= E5_ORIGIN;
bits |= E5_FRAME;
if (!VectorEquals(from->origin, to->origin)) if (!VectorEquals(from->origin, to->origin))
bits |= E5_ORIGIN; bits |= E5_ORIGIN;
if (!VectorEquals(from->angles, to->angles)) if (!VectorEquals(from->angles, to->angles))
@ -1049,14 +1053,14 @@ void SVDP_EmitEntitiesUpdate (client_t *client, packet_entities_t *to, sizebuf_t
client->netchan.incoming_sequence++; client->netchan.incoming_sequence++;
// this is the frame that we are going to delta update from // this is the frame that we are going to delta update from
fromframe = &client->frameunion.frames[(client->netchan.incoming_sequence-2) & UPDATE_MASK]; fromframe = &client->frameunion.frames[client->delta_sequence & UPDATE_MASK];
from = &fromframe->entities; from = &fromframe->entities;
oldmax = from->num_entities; oldmax = from->num_entities;
// Con_Printf ("frame %i\n", client->netchan.incoming_sequence); // Con_Printf ("frame %i\n", client->netchan.incoming_sequence);
MSG_WriteByte(msg, svcdp_entities); MSG_WriteByte(msg, svcdp_entities);
MSG_WriteLong(msg, 0); MSG_WriteLong(msg, client->netchan.incoming_sequence);
if (client->protocol == SCP_DARKPLACES7) if (client->protocol == SCP_DARKPLACES7)
MSG_WriteLong(msg, client->last_sequence); MSG_WriteLong(msg, client->last_sequence);
@ -1841,7 +1845,6 @@ void SV_WritePlayersToClient (client_t *client, client_frame_t *frame, edict_t *
ClientReliableWrite_Short(client, pflags); ClientReliableWrite_Short(client, pflags);
if (pflags & 1) if (pflags & 1)
ClientReliableWrite_Short(client, client->otherclientsknown[j].vweap); ClientReliableWrite_Short(client, client->otherclientsknown[j].vweap);
ClientReliable_FinishWrite(client);
} }
} }
} }
@ -2256,8 +2259,8 @@ void SV_Snapshot_BuildStateQ1(entity_state_t *state, edict_t *ent, client_t *cli
} }
} }
if (state->effects & 0x00400000) //DP's EF_LOWPRECISION if (state->effects & DPEF_LOWPRECISION)
state->effects &= ~0x00400000; //we don't support it, nor does dp any more. strip it. state->effects &= DPEF_LOWPRECISION; //we don't support it, nor does dp any more. strip it.
if (state->effects & EF_FULLBRIGHT) //wrap the field for fte clients (this is horrible) if (state->effects & EF_FULLBRIGHT) //wrap the field for fte clients (this is horrible)
{ {
@ -2538,14 +2541,10 @@ void SV_Snapshot_BuildQ1(client_t *client, packet_entities_t *pack, qbyte *pvs,
//the entity would mess up the client and possibly disconnect them. //the entity would mess up the client and possibly disconnect them.
//FIXME: add an option to drop clients... entity fog could be killed in this way. //FIXME: add an option to drop clients... entity fog could be killed in this way.
if (!ISDPCLIENT(client)) if (e >= client->max_net_ents)
{ continue;
if (e >= client->max_net_ents) if (ent->v->modelindex >= client->maxmodels)
continue; continue;
if (ent->v->modelindex >= client->maxmodels)
continue;
}
#ifdef DEPTHOPTIMISE #ifdef DEPTHOPTIMISE
if (clent) if (clent)
{ {

View file

@ -380,21 +380,21 @@ void SV_SaveSpawnparms (qboolean dontsave)
Q1QVM_SetChangeParms(); Q1QVM_SetChangeParms();
for (j=0 ; j<NUM_SPAWN_PARMS ; j++) for (j=0 ; j<NUM_SPAWN_PARMS ; j++)
{ {
if (spawnparamglobals[j]) if (pr_global_ptrs->spawnparamglobals[j])
host_client->spawn_parms[j] = *spawnparamglobals[j]; host_client->spawn_parms[j] = *pr_global_ptrs->spawnparamglobals[j];
else else
host_client->spawn_parms[j] = 0; host_client->spawn_parms[j] = 0;
} }
} }
#endif #endif
else if (pr_nqglobal_struct->SetChangeParms) else if (pr_global_ptrs->SetChangeParms)
{ {
pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, host_client->edict); pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, host_client->edict);
PR_ExecuteProgram (svprogfuncs, pr_global_struct->SetChangeParms); PR_ExecuteProgram (svprogfuncs, pr_global_struct->SetChangeParms);
for (j=0 ; j<NUM_SPAWN_PARMS ; j++) for (j=0 ; j<NUM_SPAWN_PARMS ; j++)
{ {
if (spawnparamglobals[j]) if (pr_global_ptrs->spawnparamglobals[j])
host_client->spawn_parms[j] = *spawnparamglobals[j]; host_client->spawn_parms[j] = *pr_global_ptrs->spawnparamglobals[j];
else else
host_client->spawn_parms[j] = 0; host_client->spawn_parms[j] = 0;
} }
@ -414,8 +414,8 @@ void SV_SaveSpawnparms (qboolean dontsave)
host_client->deaths=0; host_client->deaths=0;
for (j=0 ; j<NUM_SPAWN_PARMS ; j++) for (j=0 ; j<NUM_SPAWN_PARMS ; j++)
{ {
if (spawnparamglobals[j]) if (pr_global_ptrs->spawnparamglobals[j])
rs.parm[j] = *spawnparamglobals[j]; rs.parm[j] = *pr_global_ptrs->spawnparamglobals[j];
else else
rs.parm[j] = 0; rs.parm[j] = 0;
} }
@ -612,7 +612,6 @@ clients along with it.
This is only called from the SV_Map_f() function. This is only called from the SV_Map_f() function.
================ ================
*/ */
extern cvar_t progs;
void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean usecinematic) void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean usecinematic)
{ {
func_t f; func_t f;
@ -713,6 +712,11 @@ void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean us
r_worldentity.model = NULL; r_worldentity.model = NULL;
if (0) if (0)
cls.state = ca_connected; cls.state = ca_connected;
if (R_PreNewMap)
R_PreNewMap();
#ifdef VM_CG
CG_Stop();
#endif
#endif #endif
#ifdef Q3SERVER #ifdef Q3SERVER
@ -956,7 +960,7 @@ void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean us
else else
#endif #endif
#ifdef Q2SERVER #ifdef Q2SERVER
if ((sv.world.worldmodel->fromgame == fg_quake2 || sv.world.worldmodel->fromgame == fg_quake3) && !*progs.string && SVQ2_InitGameProgs()) //these are the rules for running a q2 server if ((sv.world.worldmodel->fromgame == fg_quake2 || sv.world.worldmodel->fromgame == fg_quake3) && !*pr_ssqc_progs.string && SVQ2_InitGameProgs()) //these are the rules for running a q2 server
newgametype = GT_QUAKE2; //we loaded the dll newgametype = GT_QUAKE2; //we loaded the dll
else else
#endif #endif
@ -1250,9 +1254,9 @@ void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean us
} }
else else
{ {
if (pr_nqglobal_struct->coop && coop.value) if (pr_global_ptrs->coop && coop.value)
pr_global_struct->coop = coop.value; pr_global_struct->coop = coop.value;
else if (pr_nqglobal_struct->deathmatch) else if (pr_global_ptrs->deathmatch)
pr_global_struct->deathmatch = deathmatch.value; pr_global_struct->deathmatch = deathmatch.value;
} }
@ -1497,8 +1501,8 @@ void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean us
// copy spawn parms out of the client_t // copy spawn parms out of the client_t
for (j=0 ; j< NUM_SPAWN_PARMS ; j++) for (j=0 ; j< NUM_SPAWN_PARMS ; j++)
{ {
if (spawnparamglobals[j]) if (pr_global_ptrs->spawnparamglobals[j])
*spawnparamglobals[j] = host_client->spawn_parms[j]; *pr_global_ptrs->spawnparamglobals[j] = host_client->spawn_parms[j];
} }
SV_SetUpClientEdict(host_client, sv_player); SV_SetUpClientEdict(host_client, sv_player);

View file

@ -124,19 +124,19 @@ cvar_t allow_download_anymap = CVAR("allow_download_pakmaps", "0");
cvar_t allow_download_pakcontents = CVAR("allow_download_pakcontents", "1"); cvar_t allow_download_pakcontents = CVAR("allow_download_pakcontents", "1");
cvar_t allow_download_root = CVAR("allow_download_root", "0"); cvar_t allow_download_root = CVAR("allow_download_root", "0");
cvar_t allow_download_textures = CVAR("allow_download_textures", "1"); cvar_t allow_download_textures = CVAR("allow_download_textures", "1");
cvar_t allow_download_pk3s = CVAR("allow_download_pk3s", "1"); cvar_t allow_download_packages = CVAR("allow_download_packages", "1");
cvar_t allow_download_wads = CVAR("allow_download_wads", "1"); cvar_t allow_download_wads = CVAR("allow_download_wads", "1");
cvar_t allow_download_configs = CVAR("allow_download_configs", "0"); cvar_t allow_download_configs = CVAR("allow_download_configs", "0");
cvar_t sv_public = CVAR("sv_public", "0"); cvar_t sv_public = CVAR("sv_public", "0");
cvar_t sv_listen_qw = CVARAF("sv_listen_qw", "1", "sv_listen", 0); cvar_t sv_listen_qw = CVARAF("sv_listen_qw", "1", "sv_listen", 0);
cvar_t sv_listen_nq = CVAR("sv_listen_nq", "0"); cvar_t sv_listen_nq = CVAR("sv_listen_nq", "0");
cvar_t sv_listen_dp = CVAR("sv_listen_dp", "1"); cvar_t sv_listen_dp = CVAR("sv_listen_dp", "0"); /*kinda fucked right now*/
cvar_t sv_listen_q3 = CVAR("sv_listen_q3", "0"); cvar_t sv_listen_q3 = CVAR("sv_listen_q3", "0");
cvar_t sv_reportheartbeats = CVAR("sv_reportheartbeats", "1"); cvar_t sv_reportheartbeats = CVAR("sv_reportheartbeats", "1");
cvar_t sv_highchars = CVAR("sv_highchars", "1"); cvar_t sv_highchars = CVAR("sv_highchars", "1");
cvar_t sv_loadentfiles = CVAR("sv_loadentfiles", "1"); cvar_t sv_loadentfiles = CVAR("sv_loadentfiles", "1");
cvar_t sv_maxrate = CVAR("sv_maxrate", "10000"); cvar_t sv_maxrate = CVAR("sv_maxrate", "30000");
cvar_t sv_maxdrate = CVARAF("sv_maxdrate", "100000", cvar_t sv_maxdrate = CVARAF("sv_maxdrate", "100000",
"sv_maxdownloadrate", 0); "sv_maxdownloadrate", 0);
cvar_t sv_minping = CVARF("sv_minping", "0", CVAR_SERVERINFO); cvar_t sv_minping = CVARF("sv_minping", "0", CVAR_SERVERINFO);
@ -162,7 +162,7 @@ cvar_t sv_port_tcp = CVARC("sv_port_tcp", "", SV_Tcpport_Callback);
cvar_t sv_port_tcp6 = CVARC("sv_port_tcp6", "", SV_Tcpport6_Callback); cvar_t sv_port_tcp6 = CVARC("sv_port_tcp6", "", SV_Tcpport6_Callback);
#endif #endif
#endif #endif
cvar_t sv_port = CVARC("sv_port", "27500", SV_Port_Callback); cvar_t sv_port_ipv4 = CVARC("sv_port", "27500", SV_Port_Callback);
#ifdef IPPROTO_IPV6 #ifdef IPPROTO_IPV6
cvar_t sv_port_ipv6 = CVARC("sv_port_ipv6", "27500", SV_PortIPv6_Callback); cvar_t sv_port_ipv6 = CVARC("sv_port_ipv6", "27500", SV_PortIPv6_Callback);
#endif #endif
@ -193,8 +193,8 @@ cvar_t skill = CVARF("skill", "" , CVAR_SERVERINFO); // 0, 1, 2 or 3
cvar_t spawn = CVARF("spawn", "" , CVAR_SERVERINFO); cvar_t spawn = CVARF("spawn", "" , CVAR_SERVERINFO);
cvar_t watervis = CVARF("watervis", "" , CVAR_SERVERINFO); cvar_t watervis = CVARF("watervis", "" , CVAR_SERVERINFO);
cvar_t rearview = CVARF("rearview", "" , CVAR_SERVERINFO); cvar_t rearview = CVARF("rearview", "" , CVAR_SERVERINFO);
cvar_t allow_fish = CVARF("allow_fish", "0", CVAR_SERVERINFO);
cvar_t allow_luma = CVARF("allow_luma", "1", CVAR_SERVERINFO); cvar_t allow_luma = CVARF("allow_luma", "1", CVAR_SERVERINFO);
#pragma warningmsg("Remove this some time")
cvar_t allow_bump = CVARF("allow_bump", "1", CVAR_SERVERINFO); cvar_t allow_bump = CVARF("allow_bump", "1", CVAR_SERVERINFO);
cvar_t allow_skybox = CVARF("allow_skybox", "", CVAR_SERVERINFO); cvar_t allow_skybox = CVARF("allow_skybox", "", CVAR_SERVERINFO);
cvar_t sv_allow_splitscreen = CVARF("allow_splitscreen","",CVAR_SERVERINFO); cvar_t sv_allow_splitscreen = CVARF("allow_splitscreen","",CVAR_SERVERINFO);
@ -418,6 +418,7 @@ void SV_DropClient (client_t *drop)
break; break;
case SCP_QUAKEWORLD: case SCP_QUAKEWORLD:
case SCP_NETQUAKE: case SCP_NETQUAKE:
case SCP_FITZ666:
case SCP_DARKPLACES6: case SCP_DARKPLACES6:
case SCP_DARKPLACES7: case SCP_DARKPLACES7:
MSG_WriteByte (&drop->netchan.message, svc_disconnect); MSG_WriteByte (&drop->netchan.message, svc_disconnect);
@ -454,11 +455,11 @@ void SV_DropClient (client_t *drop)
drop->kills=0; drop->kills=0;
drop->deaths=0; drop->deaths=0;
pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, drop->edict); pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, drop->edict);
if (pr_nqglobal_struct->SetChangeParms) if (pr_global_ptrs->SetChangeParms)
PR_ExecuteProgram (svprogfuncs, pr_global_struct->SetChangeParms); PR_ExecuteProgram (svprogfuncs, pr_global_struct->SetChangeParms);
for (j=0 ; j<NUM_RANK_SPAWN_PARMS ; j++) for (j=0 ; j<NUM_RANK_SPAWN_PARMS ; j++)
if (spawnparamglobals[j]) if (pr_global_ptrs->spawnparamglobals[j])
rs.parm[j] = *spawnparamglobals[j]; rs.parm[j] = *pr_global_ptrs->spawnparamglobals[j];
Rank_SetPlayerStats(drop->rankid, &rs); Rank_SetPlayerStats(drop->rankid, &rs);
} }
} }
@ -556,8 +557,8 @@ void SV_DropClient (client_t *drop)
if (drop->netchan.remote_address.type == NA_LOOPBACK) if (drop->netchan.remote_address.type == NA_LOOPBACK)
{ {
Netchan_Transmit(&drop->netchan, 0, "", SV_RateForClient(drop)); Netchan_Transmit(&drop->netchan, 0, "", SV_RateForClient(drop));
#ifdef _MSC_VER #ifdef warningmsg
#pragma message("This mans that we may not see the reason we kicked ourselves.") #pragma warningmsg("This mans that we may not see the reason we kicked ourselves.")
#endif #endif
CL_Disconnect(); CL_Disconnect();
drop->state = cs_free; //don't do zombie stuff drop->state = cs_free; //don't do zombie stuff
@ -777,6 +778,7 @@ int SV_CalcPing (client_t *cl, qboolean forcecalc)
case SCP_DARKPLACES6: case SCP_DARKPLACES6:
case SCP_DARKPLACES7: case SCP_DARKPLACES7:
case SCP_NETQUAKE: case SCP_NETQUAKE:
case SCP_FITZ666:
case SCP_QUAKEWORLD: case SCP_QUAKEWORLD:
ping = 0; ping = 0;
count = 0; count = 0;
@ -877,8 +879,8 @@ void SV_FullClientUpdate (client_t *client, sizebuf_t *buf, unsigned int ftepext
MSG_WriteByte (buf, i); MSG_WriteByte (buf, i);
MSG_WriteFloat (buf, realtime - client->connection_started); MSG_WriteFloat (buf, realtime - client->connection_started);
#ifdef _MSC_VER #ifdef warningmsg
#pragma message("this is a bug: it can be broadcast to all qw clients") #pragma warningmsg("this is a bug: it can be broadcast to all qw clients")
#endif #endif
if (ftepext & PEXT_BIGUSERINFOS) if (ftepext & PEXT_BIGUSERINFOS)
Q_strncpyz (info, client->userinfo, sizeof(info)); Q_strncpyz (info, client->userinfo, sizeof(info));
@ -1462,13 +1464,13 @@ void SV_GetNewSpawnParms(client_t *cl)
else else
#endif #endif
{ {
if (pr_nqglobal_struct->SetNewParms) if (pr_global_ptrs->SetNewParms)
PR_ExecuteProgram (svprogfuncs, pr_global_struct->SetNewParms); PR_ExecuteProgram (svprogfuncs, pr_global_struct->SetNewParms);
} }
for (i=0 ; i<NUM_SPAWN_PARMS ; i++) for (i=0 ; i<NUM_SPAWN_PARMS ; i++)
{ {
if (spawnparamglobals[i]) if (pr_global_ptrs->spawnparamglobals[i])
cl->spawn_parms[i] = *spawnparamglobals[i]; cl->spawn_parms[i] = *pr_global_ptrs->spawnparamglobals[i];
else else
cl->spawn_parms[i] = 0; cl->spawn_parms[i] = 0;
} }
@ -1546,6 +1548,7 @@ void VARGS SV_RejectMessage(int protocol, char *format, ...)
{ {
#ifdef NQPROT #ifdef NQPROT
case SCP_NETQUAKE: case SCP_NETQUAKE:
case SCP_FITZ666:
string[4] = CCREP_REJECT; string[4] = CCREP_REJECT;
vsnprintf (string+5,sizeof(string)-1-5, format,argptr); vsnprintf (string+5,sizeof(string)-1-5, format,argptr);
len = strlen(string+4)+1+4; len = strlen(string+4)+1+4;
@ -1597,14 +1600,18 @@ void SV_AcceptMessage(int protocol)
{ {
#ifdef NQPROT #ifdef NQPROT
case SCP_NETQUAKE: case SCP_NETQUAKE:
SZ_Clear(&sb); case SCP_FITZ666:
MSG_WriteLong(&sb, 0); if (net_from.type != NA_LOOPBACK)
MSG_WriteByte(&sb, CCREP_ACCEPT); {
NET_LocalAddressForRemote(svs.sockets, &net_from, &localaddr, 0); SZ_Clear(&sb);
MSG_WriteLong(&sb, ShortSwap(localaddr.port)); MSG_WriteLong(&sb, 0);
*(int*)sb.data = BigLong(NETFLAG_CTL|sb.cursize); MSG_WriteByte(&sb, CCREP_ACCEPT);
NET_SendPacket(NS_SERVER, sb.cursize, sb.data, net_from); NET_LocalAddressForRemote(svs.sockets, &net_from, &localaddr, 0);
return; MSG_WriteLong(&sb, ShortSwap(localaddr.port));
*(int*)sb.data = BigLong(NETFLAG_CTL|sb.cursize);
NET_SendPacket(NS_SERVER, sb.cursize, sb.data, net_from);
return;
}
case SCP_DARKPLACES6: case SCP_DARKPLACES6:
case SCP_DARKPLACES7: case SCP_DARKPLACES7:
strcpy(string, "accept"); strcpy(string, "accept");
@ -1677,6 +1684,7 @@ client_t *SVC_DirectConnect(void)
int challenge; int challenge;
int huffcrc = 0; int huffcrc = 0;
char guid[128] = ""; char guid[128] = "";
char basic[80];
qboolean redirect = false; qboolean redirect = false;
int maxpacketentities; int maxpacketentities;
@ -1925,6 +1933,7 @@ client_t *SVC_DirectConnect(void)
newcl->protocol = protocol; newcl->protocol = protocol;
Q_strncpyz(newcl->guid, guid, sizeof(newcl->guid)); Q_strncpyz(newcl->guid, guid, sizeof(newcl->guid));
newcl->maxmodels = 256;
if (protocol == SCP_QUAKEWORLD) //readd? if (protocol == SCP_QUAKEWORLD) //readd?
{ {
newcl->max_net_ents = 512; newcl->max_net_ents = 512;
@ -1932,9 +1941,15 @@ client_t *SVC_DirectConnect(void)
newcl->max_net_ents += 512; newcl->max_net_ents += 512;
if (newcl->fteprotocolextensions & PEXT_ENTITYDBL2) if (newcl->fteprotocolextensions & PEXT_ENTITYDBL2)
newcl->max_net_ents += 1024; newcl->max_net_ents += 1024;
if (newcl->fteprotocolextensions & PEXT_MODELDBL)
newcl->maxmodels = MAX_MODELS;
} }
else if (ISDPCLIENT(newcl)) else if (ISDPCLIENT(newcl))
{
newcl->max_net_ents = 32767; newcl->max_net_ents = 32767;
newcl->maxmodels = 1024;
}
else else
newcl->max_net_ents = 600; newcl->max_net_ents = 600;
@ -2025,21 +2040,9 @@ client_t *SVC_DirectConnect(void)
SV_FixupName(name, temp.namebuf, sizeof(temp.namebuf)); SV_FixupName(name, temp.namebuf, sizeof(temp.namebuf));
name = temp.namebuf; name = temp.namebuf;
if (!*name) deleetstring(basic, name);
{ if (!*basic || strstr(basic, "console"))
name = "unnamed"; name = "unnamed"; //have fun dudes.
}
else if (!stricmp(name, "console"))
name = "Not Console"; //have fun dudes.
else
{
char *t = name;
//work around an ezquake bug that has been there since the beginning in one form or another.
while (*(unsigned char*)t == 0xff)
t++;
if (!*t)
name = "invisible";
}
// count up the clients and spectators // count up the clients and spectators
clients = 0; clients = 0;
@ -2835,8 +2838,16 @@ qboolean SV_ConnectionlessPacket (void)
else if (!strcmp(c, "realip")) else if (!strcmp(c, "realip"))
SVC_RealIP (); SVC_RealIP ();
else if (!PR_GameCodePacket(net_message.data+4)) else if (!PR_GameCodePacket(net_message.data+4))
Con_Printf ("bad connectionless packet from %s:\n%s\n" {
, NET_AdrToString (adr, sizeof(adr), net_from), s); static unsigned int lt;
unsigned int ct = Sys_Milliseconds();
if (ct - lt > 5*1000)
{
Con_Printf ("bad connectionless packet from %s: \"%s\"\n"
, NET_AdrToString (adr, sizeof(adr), net_from), c);
lt = ct;
}
}
return false; return false;
} }
@ -2858,8 +2869,6 @@ void SVNQ_ConnectionlessPacket(void)
if (!sv_listen_nq.value) if (!sv_listen_nq.value)
return; return;
if (svs.netprim.coordsize != 2)
return; //no, start using dp7 instead.
MSG_BeginReading(svs.netprim); MSG_BeginReading(svs.netprim);
header = LongSwap(MSG_ReadLong()); header = LongSwap(MSG_ReadLong());
@ -3127,6 +3136,8 @@ qboolean SV_ReadPackets (float *delay)
laggedpacket_t *lp; laggedpacket_t *lp;
char *banreason; char *banreason;
qboolean received = false; qboolean received = false;
int giveup = 5000; /*we're fucked if we need this to be this high, but at least we can retain some clients if we're really running that slow*/
int cookie = 0;
for (i = 0; i < MAX_CLIENTS; i++) //fixme: shouldn't we be using svs.allocated_client_slots ? for (i = 0; i < MAX_CLIENTS; i++) //fixme: shouldn't we be using svs.allocated_client_slots ?
{ {
@ -3177,9 +3188,9 @@ qboolean SV_ReadPackets (float *delay)
} }
#ifdef SERVER_DEMO_PLAYBACK #ifdef SERVER_DEMO_PLAYBACK
while (SV_GetPacket()) while (giveup-- > 0 && SV_GetPacket())
#else #else
while (NET_GetPacket (NS_SERVER)) while (giveup-- > 0 && (cookie=NET_GetPacket (NS_SERVER, cookie)) >= 0)
#endif #endif
{ {
banreason = SV_BannedReason (&net_from); banreason = SV_BannedReason (&net_from);
@ -3241,8 +3252,8 @@ qboolean SV_ReadPackets (float *delay)
#ifdef Q3SERVER #ifdef Q3SERVER
if (ISQ3CLIENT(cl)) if (ISQ3CLIENT(cl))
{ {
#ifdef _MSC_VER #ifdef warningmsg
#pragma message("qwoverq3: fixme: this will block qw+q3 clients from the same ip") #pragma warningmsg("qwoverq3: fixme: this will block qw+q3 clients from the same ip")
#endif #endif
if (cl->state != cs_zombie) if (cl->state != cs_zombie)
{ {
@ -3405,24 +3416,37 @@ void SV_GetConsoleCommands (void)
} }
} }
#define MINDRATE 500
#define MINRATE 500
int SV_RateForClient(client_t *cl) int SV_RateForClient(client_t *cl)
{ {
int rate; int rate;
if (cl->download && cl->drate) if (cl->download)
{ {
rate = cl->drate; rate = cl->drate;
if (rate > sv_maxdrate.value) if (sv_maxdrate.ival)
rate = sv_maxdrate.value; {
if (!rate || rate > sv_maxdrate.value)
rate = sv_maxdrate.value;
else if (rate < MINDRATE)
rate = MINDRATE;
}
else if (rate >= 1 && rate < MINDRATE)
rate = MINDRATE;
} }
else else
{ {
rate = cl->rate; rate = cl->rate;
if (rate > sv_maxrate.value) if (sv_maxrate.ival)
rate = sv_maxrate.value; {
if (rate > sv_maxrate.value)
rate = sv_maxrate.value;
else if (rate < MINRATE)
rate = MINRATE;
}
else if (rate >= 1 && rate < MINRATE)
rate = MINRATE;
} }
if (rate < 500)
rate = 500;
return rate; return rate;
} }
@ -3800,7 +3824,7 @@ void SV_InitLocal (void)
extern cvar_t sv_wateraccelerate; extern cvar_t sv_wateraccelerate;
extern cvar_t sv_friction; extern cvar_t sv_friction;
extern cvar_t sv_waterfriction; extern cvar_t sv_waterfriction;
extern cvar_t sv_sound_watersplash; extern cvar_t sv_sound_watersplash, sv_sound_land;
extern cvar_t pr_allowbutton1; extern cvar_t pr_allowbutton1;
extern cvar_t pm_bunnyspeedcap; extern cvar_t pm_bunnyspeedcap;
@ -3848,7 +3872,6 @@ void SV_InitLocal (void)
Cvar_Register (&watervis, cvargroup_serverinfo); Cvar_Register (&watervis, cvargroup_serverinfo);
Cvar_Register (&rearview, cvargroup_serverinfo); Cvar_Register (&rearview, cvargroup_serverinfo);
Cvar_Register (&mirrors, cvargroup_serverinfo); Cvar_Register (&mirrors, cvargroup_serverinfo);
Cvar_Register (&allow_fish, cvargroup_serverinfo);
Cvar_Register (&allow_luma, cvargroup_serverinfo); Cvar_Register (&allow_luma, cvargroup_serverinfo);
Cvar_Register (&allow_bump, cvargroup_serverinfo); Cvar_Register (&allow_bump, cvargroup_serverinfo);
Cvar_Register (&allow_skybox, cvargroup_serverinfo); Cvar_Register (&allow_skybox, cvargroup_serverinfo);
@ -3871,7 +3894,8 @@ void SV_InitLocal (void)
Cvar_Register (&sv_wateraccelerate, cvargroup_serverphysics); Cvar_Register (&sv_wateraccelerate, cvargroup_serverphysics);
Cvar_Register (&sv_friction, cvargroup_serverphysics); Cvar_Register (&sv_friction, cvargroup_serverphysics);
Cvar_Register (&sv_waterfriction, cvargroup_serverphysics); Cvar_Register (&sv_waterfriction, cvargroup_serverphysics);
Cvar_Register (&sv_sound_watersplash, cvargroup_serverphysics); Cvar_Register (&sv_sound_watersplash, cvargroup_serverphysics);
Cvar_Register (&sv_sound_land, cvargroup_serverphysics);
Cvar_Register (&sv_bigcoords, cvargroup_serverphysics); Cvar_Register (&sv_bigcoords, cvargroup_serverphysics);
@ -3915,8 +3939,8 @@ void SV_InitLocal (void)
Cvar_Register (&sv_port_ipx, cvargroup_servercontrol); Cvar_Register (&sv_port_ipx, cvargroup_servercontrol);
sv_port_ipx.restriction = RESTRICT_MAX; sv_port_ipx.restriction = RESTRICT_MAX;
#endif #endif
Cvar_Register (&sv_port, cvargroup_servercontrol); Cvar_Register (&sv_port_ipv4, cvargroup_servercontrol);
sv_port.restriction = RESTRICT_MAX; sv_port_ipv4.restriction = RESTRICT_MAX;
Cvar_Register (&sv_reportheartbeats, cvargroup_servercontrol); Cvar_Register (&sv_reportheartbeats, cvargroup_servercontrol);
@ -3940,7 +3964,7 @@ void SV_InitLocal (void)
Cvar_Register (&allow_download_pakcontents, cvargroup_serverpermissions); Cvar_Register (&allow_download_pakcontents, cvargroup_serverpermissions);
Cvar_Register (&allow_download_textures,cvargroup_serverpermissions); Cvar_Register (&allow_download_textures,cvargroup_serverpermissions);
Cvar_Register (&allow_download_configs, cvargroup_serverpermissions); Cvar_Register (&allow_download_configs, cvargroup_serverpermissions);
Cvar_Register (&allow_download_pk3s, cvargroup_serverpermissions); Cvar_Register (&allow_download_packages,cvargroup_serverpermissions);
Cvar_Register (&allow_download_wads, cvargroup_serverpermissions); Cvar_Register (&allow_download_wads, cvargroup_serverpermissions);
Cvar_Register (&allow_download_root, cvargroup_serverpermissions); Cvar_Register (&allow_download_root, cvargroup_serverpermissions);
Cvar_Register (&secure, cvargroup_serverpermissions); Cvar_Register (&secure, cvargroup_serverpermissions);
@ -4092,7 +4116,7 @@ void SV_InitLocal (void)
int port = atoi(com_argv[p+1]); int port = atoi(com_argv[p+1]);
if (!port) if (!port)
port = PORT_QWSERVER; port = PORT_QWSERVER;
Cvar_SetValue(&sv_port, port); Cvar_SetValue(&sv_port_ipv4, port);
#ifdef IPPROTO_IPV6 #ifdef IPPROTO_IPV6
Cvar_SetValue(&sv_port_ipv6, port); Cvar_SetValue(&sv_port_ipv6, port);
#endif #endif
@ -4398,11 +4422,11 @@ qboolean ReloadRanking(client_t *cl, char *newname)
cl->kills=0; cl->kills=0;
cl->deaths=0; cl->deaths=0;
pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, cl->edict); pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, cl->edict);
if (pr_nqglobal_struct->SetChangeParms) if (pr_global_ptrs->SetChangeParms)
PR_ExecuteProgram (svprogfuncs, pr_global_struct->SetChangeParms); PR_ExecuteProgram (svprogfuncs, pr_global_struct->SetChangeParms);
for (j=0 ; j<NUM_RANK_SPAWN_PARMS ; j++) for (j=0 ; j<NUM_RANK_SPAWN_PARMS ; j++)
if (spawnparamglobals[j]) if (pr_global_ptrs->spawnparamglobals[j])
rs.parm[j] = *spawnparamglobals[j]; rs.parm[j] = *pr_global_ptrs->spawnparamglobals[j];
Rank_SetPlayerStats(cl->rankid, &rs); Rank_SetPlayerStats(cl->rankid, &rs);
cl->rankid = 0; cl->rankid = 0;
} }
@ -4442,7 +4466,7 @@ void SV_ExtractFromUserinfo (client_t *cl)
int i; int i;
client_t *client; client_t *client;
int dupc = 1; int dupc = 1;
char newname[80]; char newname[80], basic[80];
val = Info_ValueForKey (cl->userinfo, "team"); val = Info_ValueForKey (cl->userinfo, "team");
Q_strncpyz (cl->team, val, sizeof(cl->teambuf)); Q_strncpyz (cl->team, val, sizeof(cl->teambuf));
@ -4459,12 +4483,9 @@ void SV_ExtractFromUserinfo (client_t *cl)
else else
newname[0] = 0; newname[0] = 0;
if (!newname[0] && cl->protocol != SCP_BAD) deleetstring(basic, newname);
if ((!basic[0] && cl->protocol != SCP_BAD) || strstr(basic, "console"))
strcpy(newname, "unnamed"); strcpy(newname, "unnamed");
else if (!stricmp(val, "console"))
{
strcpy(newname, "Not Console");
}
// check to see if another user by the same name exists // check to see if another user by the same name exists
while (1) { while (1) {
@ -4561,7 +4582,7 @@ void SV_ExtractFromUserinfo (client_t *cl)
if (strlen(val)) if (strlen(val))
cl->drate = atoi(val); cl->drate = atoi(val);
else else
cl->drate = 0; //0 disables the downloading check cl->drate = cl->rate; //0 disables the downloading check
val = Info_ValueForKey (cl->userinfo, "cl_playerclass"); val = Info_ValueForKey (cl->userinfo, "cl_playerclass");
if (val) if (val)

View file

@ -24,10 +24,10 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "pr_common.h" #include "pr_common.h"
#ifdef _MSC_VER #ifdef warningmsg
#pragma message("fixme, fix this up before adding to csqc") #pragma warningmsg("fixme, fix this up before adding to csqc")
#endif #endif
extern nqglobalvars_t realpr_nqglobal_struct; extern globalptrs_t realpr_global_ptrs;
/* /*
@ -1899,7 +1899,8 @@ void WPhys_RunEntity (world_t *w, wedict_t *ent)
World_LinkEdict (w, ent, true); World_LinkEdict (w, ent, true);
break; break;
default: default:
SV_Error ("SV_Physics: bad movetype %i on %s", (int)ent->v->movetype, PR_GetString(w->progs, ent->v->classname)); // SV_Error ("SV_Physics: bad movetype %i on %s", (int)ent->v->movetype, PR_GetString(w->progs, ent->v->classname));
break;
} }
if (movechain != w->edicts) if (movechain != w->edicts)
@ -2003,6 +2004,27 @@ void World_Physics_Frame(world_t *w)
qboolean retouch; qboolean retouch;
wedict_t *ent; wedict_t *ent;
i = *w->g.physics_mode;
if (i == 0)
{
/*physics mode 0 = none*/
return;
}
if (i == 1)
{
/*physics mode 1 = thinks only*/
for (i=0 ; i<w->num_edicts ; i++)
{
ent = (wedict_t*)EDICT_NUM(w->progs, i);
if (ent->isfree)
continue;
WPhys_RunThink (w, ent);
}
return;
}
/*physics mode 2 = normal movetypes*/
retouch = (w->g.force_retouch && (*w->g.force_retouch >= 1)); retouch = (w->g.force_retouch && (*w->g.force_retouch >= 1));
// //
@ -2041,7 +2063,7 @@ void World_Physics_Frame(world_t *w)
} }
if (retouch) if (retouch)
w->g.force_retouch-=1; *w->g.force_retouch-=1;
} }
/* /*
@ -2102,13 +2124,16 @@ qboolean SV_Physics (void)
usercmd_t ucmd; usercmd_t ucmd;
static int old_bot_time; //I hate using floats for timers. static int old_bot_time; //I hate using floats for timers.
int newbottime, ms;
client_t *oldhost; client_t *oldhost;
edict_t *oldplayer; edict_t *oldplayer;
host_frametime = (Sys_Milliseconds() - old_bot_time) / 1000.0f; host_frametime = (Sys_Milliseconds() - old_bot_time) / 1000.0f;
if (1 || host_frametime >= 1 / 72.0f) if (1 || host_frametime >= 1 / 72.0f)
{ {
memset(&ucmd, 0, sizeof(ucmd)); memset(&ucmd, 0, sizeof(ucmd));
old_bot_time = Sys_Milliseconds(); newbottime = Sys_Milliseconds();
ms = newbottime - old_bot_time;
old_bot_time = newbottime;
for (i = 1; i <= sv.allocated_client_slots; i++) for (i = 1; i <= sv.allocated_client_slots; i++)
{ {
if (svs.clients[i-1].state && svs.clients[i-1].protocol == SCP_BAD) if (svs.clients[i-1].state && svs.clients[i-1].protocol == SCP_BAD)
@ -2116,6 +2141,7 @@ qboolean SV_Physics (void)
oldhost = host_client; oldhost = host_client;
oldplayer = sv_player; oldplayer = sv_player;
host_client = &svs.clients[i-1]; host_client = &svs.clients[i-1];
host_client->isindependant = true;
sv_player = host_client->edict; sv_player = host_client->edict;
SV_PreRunCmd(); SV_PreRunCmd();
@ -2124,11 +2150,11 @@ qboolean SV_Physics (void)
ucmd.msec = host_frametime*1000; ucmd.msec = host_frametime*1000;
#else #else
// FIXME: Something very weird is going on here! // FIXME: Something very weird is going on here!
ucmd.msec = 0; ucmd.msec = ms;
#endif #endif
ucmd.angles[0] = (int)(sv_player->v->angles[0] * (65535/360.0f)); ucmd.angles[0] = (int)(sv_player->v->v_angle[0] * (65535/360.0f));
ucmd.angles[1] = (int)(sv_player->v->angles[1] * (65535/360.0f)); ucmd.angles[1] = (int)(sv_player->v->v_angle[1] * (65535/360.0f));
ucmd.angles[2] = (int)(sv_player->v->angles[2] * (65535/360.0f)); ucmd.angles[2] = (int)(sv_player->v->v_angle[2] * (65535/360.0f));
ucmd.forwardmove = sv_player->xv->movement[0]; ucmd.forwardmove = sv_player->xv->movement[0];
ucmd.sidemove = sv_player->xv->movement[1]; ucmd.sidemove = sv_player->xv->movement[1];
ucmd.upmove = sv_player->xv->movement[2]; ucmd.upmove = sv_player->xv->movement[2];

View file

@ -253,6 +253,7 @@ void SV_PrintToClient(client_t *cl, int level, char *string)
case SCP_DARKPLACES6: case SCP_DARKPLACES6:
case SCP_DARKPLACES7: case SCP_DARKPLACES7:
case SCP_NETQUAKE: case SCP_NETQUAKE:
case SCP_FITZ666:
#ifdef NQPROT #ifdef NQPROT
ClientReliableWrite_Begin (cl, svc_print, strlen(string)+3); ClientReliableWrite_Begin (cl, svc_print, strlen(string)+3);
if (level == PRINT_CHAT) if (level == PRINT_CHAT)
@ -578,6 +579,7 @@ void SV_MulticastProtExt(vec3_t origin, multicast_t to, int dimension_mask, int
break; break;
#ifdef NQPROT #ifdef NQPROT
case SCP_NETQUAKE: case SCP_NETQUAKE:
case SCP_FITZ666:
case SCP_DARKPLACES6: case SCP_DARKPLACES6:
case SCP_DARKPLACES7: case SCP_DARKPLACES7:
if (reliable) if (reliable)
@ -711,6 +713,7 @@ void SV_MulticastProtExt(vec3_t origin, multicast_t to, int dimension_mask, int
#ifdef NQPROT #ifdef NQPROT
case SCP_NETQUAKE: case SCP_NETQUAKE:
case SCP_FITZ666:
case SCP_DARKPLACES6: case SCP_DARKPLACES6:
case SCP_DARKPLACES7: //extra prediction stuff case SCP_DARKPLACES7: //extra prediction stuff
if (reliable) if (reliable)
@ -985,9 +988,9 @@ void SV_FindModelNumbers (void)
{ {
if (!sv.strings.model_precache[i]) if (!sv.strings.model_precache[i])
break; break;
if (!strcmp(sv.strings.model_precache[i],"progs/spike.mdl")) if (!strcmp(sv.strings.model_precache[i],"progs/spike.mdl") && sv.multicast.prim.coordsize == 2)
sv_nailmodel = i; sv_nailmodel = i;
if (!strcmp(sv.strings.model_precache[i],"progs/s_spike.mdl")) if (!strcmp(sv.strings.model_precache[i],"progs/s_spike.mdl") && sv.multicast.prim.coordsize == 2)
sv_supernailmodel = i; sv_supernailmodel = i;
if (!strcmp(sv.strings.model_precache[i],"progs/player.mdl")) if (!strcmp(sv.strings.model_precache[i],"progs/player.mdl"))
sv_playermodel = i; sv_playermodel = i;
@ -1492,7 +1495,7 @@ void SV_CalcClientStats(client_t *client, int statsi[MAX_CL_STATS], float statsf
if (!client->spectator) if (!client->spectator)
{ {
statsi[STAT_ACTIVEWEAPON] = ent->v->weapon; statsi[STAT_ACTIVEWEAPON] = ent->v->weapon;
if (client->csqcactive) if (client->csqcactive || client->protocol != SCP_QUAKEWORLD)
statsi[STAT_WEAPONFRAME] = ent->v->weaponframe; statsi[STAT_WEAPONFRAME] = ent->v->weaponframe;
} }
@ -2121,7 +2124,7 @@ void SV_SendClientMessages (void)
int i, j; int i, j;
client_t *c; client_t *c;
int sentbytes, fnum; int sentbytes, fnum;
float pt = sv.world.physicstime; float pt = sv.paused?realtime:sv.world.physicstime;
#ifdef Q3SERVER #ifdef Q3SERVER
if (svs.gametype == GT_QUAKE3) if (svs.gametype == GT_QUAKE3)
@ -2262,14 +2265,14 @@ void SV_SendClientMessages (void)
if (c->state == cs_connected && !c->datagram.cursize && !c->netchan.message.cursize) if (c->state == cs_connected && !c->datagram.cursize && !c->netchan.message.cursize)
{ {
if (c->nextservertimeupdate < sv.world.physicstime) if (c->nextservertimeupdate < pt)
{ //part of the nq protocols allowed downloading content over isdn { //part of the nq protocols allowed downloading content over isdn
//the nop requirement of the protocol persisted to prevent timeouts when content loading is otherwise slow.. //the nop requirement of the protocol persisted to prevent timeouts when content loading is otherwise slow..
//aditionally we might need this for lost packets, not sure //aditionally we might need this for lost packets, not sure
//but the client isn't able to respond unless we send an occasional datagram //but the client isn't able to respond unless we send an occasional datagram
if (c->nextservertimeupdate) if (c->nextservertimeupdate)
MSG_WriteByte(&c->datagram, svc_nop); MSG_WriteByte(&c->datagram, svc_nop);
c->nextservertimeupdate = sv.world.physicstime+5; c->nextservertimeupdate = pt+5;
} }
} }
} }

View file

@ -49,12 +49,13 @@ cvar_t sv_antilag = CVARFD("sv_antilag", "1", CVAR_SERVERINFO, "Attempt to bac
cvar_t sv_antilag_frac = CVARF("sv_antilag_frac", "1", CVAR_SERVERINFO); cvar_t sv_antilag_frac = CVARF("sv_antilag_frac", "1", CVAR_SERVERINFO);
cvar_t sv_cheatpc = CVAR("sv_cheatpc", "125"); cvar_t sv_cheatpc = CVAR("sv_cheatpc", "125");
cvar_t sv_cheatspeedchecktime = CVAR("sv_cheatspeedchecktime", "30"); cvar_t sv_cheatspeedchecktime = CVAR("sv_cheatspeedchecktime", "30");
cvar_t sv_playermodelchecks = CVAR("sv_playermodelchecks", "1"); cvar_t sv_playermodelchecks = CVAR("sv_playermodelchecks", "0");
cvar_t sv_cmdlikercon = SCVAR("sv_cmdlikercon", "0"); //set to 1 to allow a password of username:password instead of the correct rcon password. cvar_t sv_cmdlikercon = SCVAR("sv_cmdlikercon", "0"); //set to 1 to allow a password of username:password instead of the correct rcon password.
cvar_t cmd_allowaccess = SCVAR("cmd_allowaccess", "0"); //set to 1 to allow cmd to execute console commands on the server. cvar_t cmd_allowaccess = SCVAR("cmd_allowaccess", "0"); //set to 1 to allow cmd to execute console commands on the server.
cvar_t cmd_gamecodelevel = SCVAR("cmd_gamecodelevel", "50"); //execution level which gamecode is told about (for unrecognised commands) cvar_t cmd_gamecodelevel = SCVAR("cmd_gamecodelevel", "50"); //execution level which gamecode is told about (for unrecognised commands)
cvar_t sv_pure = CVARFD("sv_pure", "", CVAR_SERVERINFO, "The most evil cvar in the world.");
cvar_t sv_nomsec = CVARD("sv_nomsec", "0", "Ignore client msec times, runs using NQ physics instead."); cvar_t sv_nomsec = CVARD("sv_nomsec", "0", "Ignore client msec times, runs using NQ physics instead.");
cvar_t sv_edgefriction = CVARAF("sv_edgefriction", "2", cvar_t sv_edgefriction = CVARAF("sv_edgefriction", "2",
"edgefriction", 0); "edgefriction", 0);
@ -377,15 +378,13 @@ void SV_New_f (void)
// send server info string // send server info string
if (sv.demostatevalid) if (sv.demostatevalid)
{ {
ClientReliableCheckBlock(host_client, 20 + strlen(sv.demoinfo)); ClientReliableWrite_Begin(host_client, svc_stufftext, 20 + strlen(sv.demoinfo));
ClientReliableWrite_Byte (host_client, svc_stufftext);
ClientReliableWrite_String (host_client, va("fullserverinfo \"%s\"\n", sv.demoinfo) ); ClientReliableWrite_String (host_client, va("fullserverinfo \"%s\"\n", sv.demoinfo) );
} }
else else
#endif #endif
{ {
ClientReliableCheckBlock(host_client, 20 + strlen(svs.info)); ClientReliableWrite_Begin(host_client, svc_stufftext, 20 + strlen(svs.info));
ClientReliableWrite_Byte (host_client, svc_stufftext);
ClientReliableWrite_String (host_client, va("fullserverinfo \"%s\"\n", svs.info) ); ClientReliableWrite_String (host_client, va("fullserverinfo \"%s\"\n", svs.info) );
} }
@ -395,9 +394,7 @@ void SV_New_f (void)
SV_CheckRealIP(host_client, false); SV_CheckRealIP(host_client, false);
// send music // send music
ClientReliableCheckBlock(host_client, 2); ClientReliableWrite_Begin(host_client, svc_cdtrack, 2);
ClientReliableWrite_Byte (host_client, svc_cdtrack);
if (progstype == PROG_H2) if (progstype == PROG_H2)
ClientReliableWrite_Byte (host_client, sv.h2cdtrack); ClientReliableWrite_Byte (host_client, sv.h2cdtrack);
else if (svprogfuncs) else if (svprogfuncs)
@ -406,7 +403,26 @@ void SV_New_f (void)
ClientReliableWrite_Byte (host_client, 0); ClientReliableWrite_Byte (host_client, 0);
SV_LogPlayer(host_client, "new (QW)"); SV_LogPlayer(host_client, "new (QW)");
{
char buffer[1024];
FS_GetPackNames(buffer, sizeof(buffer), false, true); /*retain extensions, or we'd have to assume pk3*/
ClientReliableWrite_Begin(host_client, svc_stufftext, 1+11+strlen(buffer)+1+1);
ClientReliableWrite_SZ(host_client, "//paknames ", 11);
ClientReliableWrite_SZ(host_client, buffer, strlen(buffer));
ClientReliableWrite_String(host_client, "\n");
FS_GetPackHashes(buffer, sizeof(buffer), false);
ClientReliableWrite_Begin(host_client, svc_stufftext, 1+7+strlen(buffer)+1+1);
ClientReliableWrite_SZ(host_client, "//paks ", 7);
ClientReliableWrite_SZ(host_client, buffer, strlen(buffer));
ClientReliableWrite_String(host_client, "\n");
}
} }
#define GAME_DEATHMATCH 0 #define GAME_DEATHMATCH 0
#define GAME_COOP 1 #define GAME_COOP 1
void SVNQ_New_f (void) void SVNQ_New_f (void)
@ -476,8 +492,30 @@ void SVNQ_New_f (void)
{ {
#ifdef NQPROT #ifdef NQPROT
case SCP_NETQUAKE: case SCP_NETQUAKE:
case SCP_FITZ666:
SV_LogPlayer(host_client, "new (NQ)"); SV_LogPlayer(host_client, "new (NQ)");
MSG_WriteLong (&host_client->netchan.message, NQ_PROTOCOL_VERSION); if (sv.nqdatagram.prim.anglesize != 1 || sv.nqdatagram.prim.coordsize != 2)
{
int rmqfl =
((sv.nqdatagram.prim.coordsize==4)?RMQFL_FLOATCOORD:0) |
((sv.nqdatagram.prim.anglesize==2)?RMQFL_SHORTANGLE:0);
host_client->protocol = SCP_FITZ666; /*mneh, close enough, the rmq stuff is just modifiers*/
if (rmqfl)
{
MSG_WriteLong (&host_client->netchan.message, RMQ_PROTOCOL_VERSION);
MSG_WriteLong (&host_client->netchan.message, rmqfl);
}
else
{
MSG_WriteLong (&host_client->netchan.message, FITZ_PROTOCOL_VERSION);
}
}
else
{
host_client->protocol = SCP_NETQUAKE;
MSG_WriteLong (&host_client->netchan.message, NQ_PROTOCOL_VERSION);
}
MSG_WriteByte (&host_client->netchan.message, (sv.allocated_client_slots>16)?16:sv.allocated_client_slots); MSG_WriteByte (&host_client->netchan.message, (sv.allocated_client_slots>16)?16:sv.allocated_client_slots);
break; break;
case SCP_DARKPLACES6: case SCP_DARKPLACES6:
@ -974,6 +1012,7 @@ void SV_Modellist_f (void)
{ {
unsigned int i; unsigned int i;
unsigned int n; unsigned int n;
qboolean initial;
if (host_client->state != cs_connected) if (host_client->state != cs_connected)
{ {
@ -999,40 +1038,6 @@ void SV_Modellist_f (void)
return; return;
} }
if (n == 0 && (host_client->zquake_extensions & Z_EXT_VWEP))
{
char mname[MAX_QPATH];
char vweaplist[1024] = "//vwep";
//int pos = strlen(vweaplist); // warning: unused variable pos
for (i = 0; sv.strings.vw_model_precache[i]; i++)
{
//grab the model name... without a progs/ prefix if it has one
if (!strncmp(sv.strings.vw_model_precache[i], "progs/", 6))
Q_strncpy(mname, sv.strings.vw_model_precache[i]+6, sizeof(mname));
else
Q_strncpy(mname, sv.strings.vw_model_precache[i], sizeof(mname));
//strip .mdl extensions
if (!strcmp(COM_FileExtension(mname), "mdl"))
COM_StripExtension(mname, mname, sizeof(mname));
//add it to the vweap command, taking care of any remaining spaces in names.
if (strchr(mname, ' '))
Q_strncatz(vweaplist, va(" \"%s\"", mname), sizeof(vweaplist));
else
Q_strncatz(vweaplist, va(" %s", mname), sizeof(vweaplist));
}
if (strlen(vweaplist) <= sizeof(vweaplist)-2)
{
Q_strncatz(vweaplist, "\n", sizeof(vweaplist));
ClientReliableWrite_Begin(host_client, svc_stufftext, 2+strlen(vweaplist));
ClientReliableWrite_String(host_client, vweaplist);
}
}
//NOTE: This doesn't go through ClientReliableWrite since it's before the user //NOTE: This doesn't go through ClientReliableWrite since it's before the user
//spawns. These functions are written to not overflow //spawns. These functions are written to not overflow
if (host_client->num_backbuf) if (host_client->num_backbuf)
@ -1044,6 +1049,8 @@ void SV_Modellist_f (void)
return; return;
} }
initial = (n==0);
#ifdef PEXT_MODELDBL #ifdef PEXT_MODELDBL
if (n > 255) if (n > 255)
{ {
@ -1057,12 +1064,6 @@ void SV_Modellist_f (void)
MSG_WriteByte (&host_client->netchan.message, n); MSG_WriteByte (&host_client->netchan.message, n);
} }
host_client->maxmodels = 256;
#ifdef PEXT_MODELDBL
if (host_client->fteprotocolextensions & PEXT_MODELDBL)
host_client->maxmodels = MAX_MODELS;
#endif
#ifdef SERVER_DEMO_PLAYBACK #ifdef SERVER_DEMO_PLAYBACK
if (sv.democausesreconnect) //read the list from somewhere else if (sv.democausesreconnect) //read the list from somewhere else
{ {
@ -1096,6 +1097,41 @@ void SV_Modellist_f (void)
// next msg // next msg
MSG_WriteByte (&host_client->netchan.message, n & 0xff); MSG_WriteByte (&host_client->netchan.message, n & 0xff);
if (initial && (host_client->zquake_extensions & Z_EXT_VWEP))
{
char mname[MAX_QPATH];
char vweaplist[1024] = "//vwep";
//int pos = strlen(vweaplist); // warning: unused variable pos
for (i = 0; sv.strings.vw_model_precache[i]; i++)
{
//grab the model name... without a progs/ prefix if it has one
if (!strncmp(sv.strings.vw_model_precache[i], "progs/", 6))
Q_strncpy(mname, sv.strings.vw_model_precache[i]+6, sizeof(mname));
else
Q_strncpy(mname, sv.strings.vw_model_precache[i], sizeof(mname));
//strip .mdl extensions
if (!strcmp(COM_FileExtension(mname), "mdl"))
COM_StripExtension(mname, mname, sizeof(mname));
//add it to the vweap command, taking care of any remaining spaces in names.
if (strchr(mname, ' '))
Q_strncatz(vweaplist, va(" \"%s\"", mname), sizeof(vweaplist));
else
Q_strncatz(vweaplist, va(" %s", mname), sizeof(vweaplist));
}
if (strlen(vweaplist) <= sizeof(vweaplist)-2)
{
Q_strncatz(vweaplist, "\n", sizeof(vweaplist));
ClientReliableWrite_Begin(host_client, svc_stufftext, 2+strlen(vweaplist));
ClientReliableWrite_String(host_client, vweaplist);
}
}
} }
/* /*
@ -1103,7 +1139,7 @@ void SV_Modellist_f (void)
SV_PreSpawn_f SV_PreSpawn_f
================== ==================
*/ */
void SV_PreSpawn_f (void) void SVQW_PreSpawn_f (void)
{ {
unsigned buf, bufs; unsigned buf, bufs;
unsigned check; unsigned check;
@ -1262,6 +1298,10 @@ void SV_PreSpawn_f (void)
MSG_WriteAngle(&host_client->netchan.message, 0); MSG_WriteAngle(&host_client->netchan.message, 0);
} }
} }
else if (state->number >= host_client->max_net_ents || state->modelindex >= host_client->maxmodels)
{
/*can't send this ent*/
}
else if (host_client->fteprotocolextensions & PEXT_SPAWNSTATIC2) else if (host_client->fteprotocolextensions & PEXT_SPAWNSTATIC2)
{ {
MSG_WriteByte(&host_client->netchan.message, svcfte_spawnbaseline2); MSG_WriteByte(&host_client->netchan.message, svcfte_spawnbaseline2);
@ -1594,8 +1634,8 @@ void SV_Begin_Core(client_t *split)
// copy spawn parms out of the client_t // copy spawn parms out of the client_t
for (i=0 ; i< NUM_SPAWN_PARMS ; i++) for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
{ {
if (spawnparamglobals[i]) if (pr_global_ptrs->spawnparamglobals[i])
*spawnparamglobals[i] = split->spawn_parms[i]; *pr_global_ptrs->spawnparamglobals[i] = split->spawn_parms[i];
} }
// call the spawn function // call the spawn function
@ -1625,8 +1665,8 @@ void SV_Begin_Core(client_t *split)
eval2->_float = 1; eval2->_float = 1;
for (j=0 ; j< NUM_SPAWN_PARMS ; j++) for (j=0 ; j< NUM_SPAWN_PARMS ; j++)
{ {
if (spawnparamglobals[j]) if (pr_global_ptrs->spawnparamglobals[j])
*spawnparamglobals[j] = split->spawn_parms[j]; *pr_global_ptrs->spawnparamglobals[j] = split->spawn_parms[j];
} }
pr_global_struct->time = sv.world.physicstime; pr_global_struct->time = sv.world.physicstime;
pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, ent); pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, ent);
@ -1638,8 +1678,8 @@ void SV_Begin_Core(client_t *split)
// copy spawn parms out of the client_t // copy spawn parms out of the client_t
for (i=0 ; i< NUM_SPAWN_PARMS ; i++) for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
{ {
if (spawnparamglobals[i]) if (pr_global_ptrs->spawnparamglobals[i])
*spawnparamglobals[i] = split->spawn_parms[i]; *pr_global_ptrs->spawnparamglobals[i] = split->spawn_parms[i];
} }
// call the spawn function // call the spawn function
@ -2411,7 +2451,7 @@ qboolean SV_AllowDownload (const char *name)
extern cvar_t allow_download_demos; extern cvar_t allow_download_demos;
extern cvar_t allow_download_maps; extern cvar_t allow_download_maps;
extern cvar_t allow_download_textures; extern cvar_t allow_download_textures;
extern cvar_t allow_download_pk3s; extern cvar_t allow_download_packages;
extern cvar_t allow_download_wads; extern cvar_t allow_download_wads;
extern cvar_t allow_download_root; extern cvar_t allow_download_root;
extern cvar_t allow_download_configs; extern cvar_t allow_download_configs;
@ -2430,6 +2470,17 @@ qboolean SV_AllowDownload (const char *name)
if (strchr(name, '\\')) //no windows paths - grow up lame windows users. if (strchr(name, '\\')) //no windows paths - grow up lame windows users.
return false; return false;
if (!strncmp(name, "package/", 8))
{
if (!strcmp("pk4", COM_FileExtension(name)) || !strcmp("pk3", COM_FileExtension(name)) || !strcmp("pak", COM_FileExtension(name)))
{
/*do not permit 'id1/pak1.pak' or 'baseq3/pak0.pk3' or any similarly named packages. such packages would violate copyright, and must be obtained through other means (like buying the damn game)*/
//if (!strstr(name, "/pak"))
return !!allow_download_packages.value;
}
return false;
}
if (strncmp(name, "maps/", 5) == 0) if (strncmp(name, "maps/", 5) == 0)
return !!allow_download_maps.value; return !!allow_download_maps.value;
@ -2457,10 +2508,10 @@ qboolean SV_AllowDownload (const char *name)
if (!strcmp("wad", COM_FileExtension(name))) if (!strcmp("wad", COM_FileExtension(name)))
return !!allow_download_wads.value; return !!allow_download_wads.value;
//pk3s. //pak/pk3s.
if (!strcmp("pk3", COM_FileExtension(name)) || !strcmp("pak", COM_FileExtension(name))) if (!strcmp("pk4", COM_FileExtension(name)) || !strcmp("pk3", COM_FileExtension(name)) || !strcmp("pak", COM_FileExtension(name)))
if (strnicmp(name, "pak", 3)) //don't give out q3 pk3 files. if (strnicmp(name, "pak", 3)) //don't give out q3 pk3 files.
return !!allow_download_pk3s.value; return !!allow_download_packages.value;
if (!strcmp("cfg", COM_FileExtension(name))) if (!strcmp("cfg", COM_FileExtension(name)))
return !!allow_download_configs.value; return !!allow_download_configs.value;
@ -2494,6 +2545,8 @@ static int SV_LocateDownload(char *name, flocation_t *loc, char **replacementnam
*p = (char)tolower(*p); *p = (char)tolower(*p);
} }
if (!SV_AllowDownload(name)) if (!SV_AllowDownload(name))
return -2; //not permitted (even if it exists). return -2; //not permitted (even if it exists).
@ -2519,7 +2572,19 @@ static int SV_LocateDownload(char *name, flocation_t *loc, char **replacementnam
if (!strncmp(name, "demos/", 6)) if (!strncmp(name, "demos/", 6))
name = va("%s/%s", sv_demoDir.string, name+6); name = va("%s/%s", sv_demoDir.string, name+6);
found = FS_FLocateFile(name, FSLFRT_IFFOUND, loc); if (!strncmp(name, "package/", 8))
{
vfsfile_t *f;
f = FS_OpenVFS(name+8, "rb", FS_ROOT);
if (f)
{
VFS_CLOSE(f);
return -5; //found package
}
return -1; //not found
}
else
found = FS_FLocateFile(name, FSLFRT_IFFOUND, loc);
//nexuiz names certain files as .wav but they're really .ogg on disk. //nexuiz names certain files as .wav but they're really .ogg on disk.
if (!found && replacementname) if (!found && replacementname)
@ -2604,23 +2669,24 @@ void SV_DownloadSize_f(void)
switch(SV_LocateDownload(name, &loc, &redirected, true)) switch(SV_LocateDownload(name, &loc, &redirected, true))
{ {
case -4: case -4: /*redirect*/
name = va("dlsize \"%s\" r \"%s\"\n", name, redirected); name = va("dlsize \"%s\" r \"%s\"\n", name, redirected);
ClientReliableWrite_Begin (host_client, svc_stufftext, 2+strlen(name)); ClientReliableWrite_Begin (host_client, svc_stufftext, 2+strlen(name));
ClientReliableWrite_String (host_client, name); ClientReliableWrite_String (host_client, name);
break; break;
default: default:
case -1: case -1: /*not found*/
name = va("dlsize \"%s\" e\n", name); name = va("dlsize \"%s\" e\n", name);
ClientReliableWrite_Begin (host_client, svc_stufftext, 2+strlen(name)); ClientReliableWrite_Begin (host_client, svc_stufftext, 2+strlen(name));
ClientReliableWrite_String (host_client, name); ClientReliableWrite_String (host_client, name);
break; break;
case -2: case -2: /*permission*/
name = va("dlsize \"%s\" p\n", name); name = va("dlsize \"%s\" p\n", name);
ClientReliableWrite_Begin (host_client, svc_stufftext, 2+strlen(name)); ClientReliableWrite_Begin (host_client, svc_stufftext, 2+strlen(name));
ClientReliableWrite_String (host_client, name); ClientReliableWrite_String (host_client, name);
break; break;
case 0: case -5: /*package*/
case 0: /*exists*/
name = va("dlsize \"%s\" %u\n", name, loc.len); name = va("dlsize \"%s\" %u\n", name, loc.len);
ClientReliableWrite_Begin (host_client, svc_stufftext, 2+strlen(name)); ClientReliableWrite_Begin (host_client, svc_stufftext, 2+strlen(name));
ClientReliableWrite_String (host_client, name); ClientReliableWrite_String (host_client, name);
@ -2648,26 +2714,36 @@ void SV_BeginDownload_f(void)
return; return;
} }
result = SV_LocateDownload(name, &loc, &redirection, false);
*host_client->downloadfn = 0; *host_client->downloadfn = 0;
if (host_client->download) if (host_client->download)
{ {
VFS_CLOSE (host_client->download); VFS_CLOSE (host_client->download);
host_client->download = NULL; host_client->download = NULL;
} }
//redirection protocol-specific code goes here. result = SV_LocateDownload(name, &loc, &redirection, false);
if (result == -4)
if (result == -5)
{ {
result = 0;
host_client->download = FS_OpenVFS(name+8, "rb", FS_ROOT);
}
else
{
//redirection protocol-specific code goes here.
if (result == -4)
{
}
if (result == 0)
{ //if we are allowed and could find it
host_client->download = FS_OpenReadLocation(&loc);
}
} }
if (result == 0) if (!host_client->download)
{ //if we are allowed and could find it result = -1; //this isn't likely, but hey.
host_client->download = FS_OpenReadLocation(&loc);
if (!host_client->download)
result = -1; //this isn't likely, but hey.
}
//handle errors //handle errors
if (result != 0) if (result != 0)
@ -3353,7 +3429,8 @@ void SV_Rate_f (void)
return; return;
} }
host_client->rate = atoi(Cmd_Argv(1)); Info_SetValueForKey (host_client->userinfo, "rate", Cmd_Argv(1), sizeof(host_client->userinfo));
SV_ExtractFromUserinfo (host_client);
SV_ClientTPrintf (host_client, PRINT_HIGH, STL_RATESETTO, SV_RateForClient(host_client)); SV_ClientTPrintf (host_client, PRINT_HIGH, STL_RATESETTO, SV_RateForClient(host_client));
} }
@ -4003,12 +4080,12 @@ void Cmd_Join_f (void)
// FIXME, bump the client's userid? // FIXME, bump the client's userid?
// call the progs to get default spawn parms for the new client // call the progs to get default spawn parms for the new client
if (pr_nqglobal_struct->SetNewParms) if (pr_global_ptrs->SetNewParms)
PR_ExecuteProgram (svprogfuncs, pr_global_struct->SetNewParms); PR_ExecuteProgram (svprogfuncs, pr_global_struct->SetNewParms);
for (i=0 ; i<NUM_SPAWN_PARMS ; i++) for (i=0 ; i<NUM_SPAWN_PARMS ; i++)
{ {
if (spawnparamglobals[i]) if (pr_global_ptrs->spawnparamglobals[i])
host_client->spawn_parms[i] = *spawnparamglobals[i]; host_client->spawn_parms[i] = *pr_global_ptrs->spawnparamglobals[i];
else else
host_client->spawn_parms[i] = 0; host_client->spawn_parms[i] = 0;
} }
@ -4095,12 +4172,12 @@ void Cmd_Observe_f (void)
// FIXME, bump the client's userid? // FIXME, bump the client's userid?
// call the progs to get default spawn parms for the new client // call the progs to get default spawn parms for the new client
if (pr_nqglobal_struct->SetNewParms) if (pr_global_ptrs->SetNewParms)
PR_ExecuteProgram (svprogfuncs, pr_global_struct->SetNewParms); PR_ExecuteProgram (svprogfuncs, pr_global_struct->SetNewParms);
for (i=0 ; i<NUM_SPAWN_PARMS ; i++) for (i=0 ; i<NUM_SPAWN_PARMS ; i++)
{ {
if (spawnparamglobals[i]) if (pr_global_ptrs->spawnparamglobals[i])
host_client->spawn_parms[i] = *spawnparamglobals[i]; host_client->spawn_parms[i] = *pr_global_ptrs->spawnparamglobals[i];
else else
host_client->spawn_parms[i] = 0; host_client->spawn_parms[i] = 0;
} }
@ -4333,8 +4410,8 @@ void SVNQ_Begin_f (void)
// copy spawn parms out of the client_t // copy spawn parms out of the client_t
for (i=0 ; i< NUM_SPAWN_PARMS ; i++) for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
{ {
if (spawnparamglobals[i]) if (pr_global_ptrs->spawnparamglobals[i])
*spawnparamglobals[i] = host_client->spawn_parms[i]; *pr_global_ptrs->spawnparamglobals[i] = host_client->spawn_parms[i];
} }
// call the spawn function // call the spawn function
@ -4348,8 +4425,8 @@ void SVNQ_Begin_f (void)
// copy spawn parms out of the client_t // copy spawn parms out of the client_t
for (i=0 ; i< NUM_SPAWN_PARMS ; i++) for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
{ {
if (spawnparamglobals[i]) if (pr_global_ptrs->spawnparamglobals[i])
*spawnparamglobals[i] = host_client->spawn_parms[i]; *pr_global_ptrs->spawnparamglobals[i] = host_client->spawn_parms[i];
} }
// call the spawn function // call the spawn function
@ -4423,76 +4500,110 @@ void SVNQ_PreSpawn_f (void)
edict_t *ent; edict_t *ent;
entity_state_t *state; entity_state_t *state;
int i, e; int i, e;
int buf = atoi(Cmd_Argv(1));
int st;
if (host_client->state != cs_connected) if (host_client->state != cs_connected)
{ {
Con_Printf ("prespawn not valid -- already spawned\n"); Con_Printf ("prespawn not valid -- already spawned\n");
return; return;
} }
for (e = 1; e < sv.world.num_edicts && e < host_client->max_net_ents; e++) st = 0;
if (buf >= st)
{ {
ent = EDICT_NUM(svprogfuncs, e); while (host_client->netchan.message.cursize < (host_client->netchan.message.maxsize/2)) //baselines
state = &ent->baseline;
if (!state->number || !state->modelindex)
{ //ent doesn't have a baseline
continue;
}
if (!ent)
{ {
MSG_WriteByte(&host_client->netchan.message, svc_spawnbaseline); e = buf-st;
if (e >= sv.world.num_edicts)
MSG_WriteShort (&host_client->netchan.message, e);
MSG_WriteByte (&host_client->netchan.message, 0);
MSG_WriteByte (&host_client->netchan.message, 0);
MSG_WriteByte (&host_client->netchan.message, 0);
MSG_WriteByte (&host_client->netchan.message, 0);
for (i=0 ; i<3 ; i++)
{ {
MSG_WriteCoord(&host_client->netchan.message, 0); if (e < sv.world.max_edicts)
MSG_WriteAngle(&host_client->netchan.message, 0); buf += sv.world.max_edicts - sv.world.num_edicts;
break;
} }
} buf++;
else
{
if (ISDPCLIENT(host_client) && (state->modelindex > 255 || state->frame > 255))
{
MSG_WriteByte(&host_client->netchan.message, svcdp_spawnbaseline2);
MSG_WriteShort (&host_client->netchan.message, e); ent = EDICT_NUM(svprogfuncs, e);
state = &ent->baseline;
MSG_WriteShort (&host_client->netchan.message, state->modelindex); if (!state->number || !state->modelindex)
MSG_WriteShort (&host_client->netchan.message, state->frame); { //ent doesn't have a baseline
continue;
} }
else
if (!ent)
{ {
MSG_WriteByte(&host_client->netchan.message, svc_spawnbaseline); MSG_WriteByte(&host_client->netchan.message, svc_spawnbaseline);
MSG_WriteShort (&host_client->netchan.message, e); MSG_WriteShort (&host_client->netchan.message, e);
MSG_WriteByte (&host_client->netchan.message, state->modelindex&255); MSG_WriteByte (&host_client->netchan.message, 0);
MSG_WriteByte (&host_client->netchan.message, state->frame&255);
}
MSG_WriteByte (&host_client->netchan.message, (int)state->colormap); MSG_WriteByte (&host_client->netchan.message, 0);
MSG_WriteByte (&host_client->netchan.message, (int)state->skinnum); MSG_WriteByte (&host_client->netchan.message, 0);
for (i=0 ; i<3 ; i++) MSG_WriteByte (&host_client->netchan.message, 0);
for (i=0 ; i<3 ; i++)
{
MSG_WriteCoord(&host_client->netchan.message, 0);
MSG_WriteAngle(&host_client->netchan.message, 0);
}
}
else
{ {
MSG_WriteCoord(&host_client->netchan.message, state->origin[i]); if (ISDPCLIENT(host_client) && (state->modelindex > 255 || state->frame > 255))
MSG_WriteAngle(&host_client->netchan.message, state->angles[i]); {
MSG_WriteByte(&host_client->netchan.message, svcdp_spawnbaseline2);
MSG_WriteShort (&host_client->netchan.message, e);
MSG_WriteShort (&host_client->netchan.message, state->modelindex);
MSG_WriteShort (&host_client->netchan.message, state->frame);
}
else
{
MSG_WriteByte(&host_client->netchan.message, svc_spawnbaseline);
MSG_WriteShort (&host_client->netchan.message, e);
MSG_WriteByte (&host_client->netchan.message, state->modelindex&255);
MSG_WriteByte (&host_client->netchan.message, state->frame&255);
}
MSG_WriteByte (&host_client->netchan.message, (int)state->colormap);
MSG_WriteByte (&host_client->netchan.message, (int)state->skinnum);
for (i=0 ; i<3 ; i++)
{
MSG_WriteCoord(&host_client->netchan.message, state->origin[i]);
MSG_WriteAngle(&host_client->netchan.message, state->angles[i]);
}
} }
} }
} }
st += sv.world.max_edicts;
for (i = 0; i < sv.num_signon_buffers; i++) if (buf >= st)
SZ_Write (&host_client->netchan.message, sv.signon_buffers[i], sv.signon_buffer_size[i]); {
while (host_client->netchan.message.cursize < (host_client->netchan.message.maxsize/2))
MSG_WriteByte (&host_client->netchan.message, svc_signonnum); {
MSG_WriteByte (&host_client->netchan.message, 2); i = buf-st;
if (i >= sv.num_signon_buffers)
break;
buf++;
SZ_Write (&host_client->netchan.message, sv.signon_buffers[i], sv.signon_buffer_size[i]);
}
}
st += sv.num_signon_buffers;
if (st == buf)
{
MSG_WriteByte (&host_client->netchan.message, svc_signonnum);
MSG_WriteByte (&host_client->netchan.message, 2);
}
else
{
char *s = va("cmd prespawn %i\n", buf);
ClientReliableWrite_Begin (host_client, svc_stufftext, 2+strlen(s));
ClientReliableWrite_String (host_client, s);
}
host_client->send_message = true; host_client->send_message = true;
} }
@ -4674,7 +4785,7 @@ ucmd_t ucmds[] =
{"pk3list", SV_PK3List_f, true}, {"pk3list", SV_PK3List_f, true},
{"modellist", SV_Modellist_f, true}, {"modellist", SV_Modellist_f, true},
{"soundlist", SV_Soundlist_f, true}, {"soundlist", SV_Soundlist_f, true},
{"prespawn", SV_PreSpawn_f, true}, {"prespawn", SVQW_PreSpawn_f, true},
{"spawn", SV_Spawn_f, true}, {"spawn", SV_Spawn_f, true},
{"begin", SV_Begin_f, true}, {"begin", SV_Begin_f, true},
@ -4778,7 +4889,7 @@ ucmd_t nqucmds[] =
{"god", Cmd_God_f}, {"god", Cmd_God_f},
{"give", Cmd_Give_f}, {"give", Cmd_Give_f},
{"notarget", Cmd_Notarget_f}, {"notarget", Cmd_Notarget_f},
{"fly", NULL}, {"fly", Cmd_Fly_f},
{"noclip", Cmd_Noclip_f}, {"noclip", Cmd_Noclip_f},
{"pings", SV_Pings_f}, {"pings", SV_Pings_f},
@ -4798,10 +4909,11 @@ ucmd_t nqucmds[] =
{"ban", NULL}, {"ban", NULL},
{"vote", SV_Vote_f}, {"vote", SV_Vote_f},
{"dlsize", SV_DownloadSize_f},
{"download", SV_BeginDownload_f}, {"download", SV_BeginDownload_f},
{"sv_startdownload", SVDP_StartDownload_f}, {"sv_startdownload", SVDP_StartDownload_f},
{"setinfo", SV_SetInfo_f}, {"setinfo", SV_SetInfo_f},
{"playermodel", NULL}, {"playermodel", NULL},
{"playerskin", NULL}, {"playerskin", NULL},
{"rate", SV_Rate_f}, {"rate", SV_Rate_f},
@ -4810,13 +4922,14 @@ ucmd_t nqucmds[] =
{"topten", Rank_ListTop10_f}, {"topten", Rank_ListTop10_f},
#endif #endif
{"pext", SV_Pext_f}, {"pext", SV_Pext_f},
{"enablecsqc", SV_EnableClientsCSQC},
{"disablecsqc", SV_DisableClientsCSQC},
#ifdef VOICECHAT #ifdef VOICECHAT
{"voicetarg", SV_Voice_Target_f}, {"voicetarg", SV_Voice_Target_f},
{"vignore", SV_Voice_Ignore_f}, /*ignore/mute specific player*/ {"vignore", SV_Voice_Ignore_f}, /*ignore/mute specific player*/
{"muteall", SV_Voice_MuteAll_f}, /*disables*/ {"muteall", SV_Voice_MuteAll_f}, /*disables*/
{"unmuteall", SV_Voice_UnmuteAll_f}, /*reenables*/ {"unmuteall", SV_Voice_UnmuteAll_f}, /*reenables*/
#endif #endif
{NULL, NULL} {NULL, NULL}
@ -5418,7 +5531,7 @@ void SV_RunCmd (usercmd_t *ucmd, qboolean recurse)
sv_player->v->button0 = ucmd->buttons & 1; sv_player->v->button0 = ucmd->buttons & 1;
sv_player->v->button2 = (ucmd->buttons >> 1) & 1; sv_player->v->button2 = (ucmd->buttons >> 1) & 1;
if (pr_allowbutton1.value) //many mods use button1 - it's just a wasted field to many mods. So only work it if the cvar allows. if (pr_allowbutton1.ival) //many mods use button1 - it's just a wasted field to many mods. So only work it if the cvar allows.
sv_player->v->button1 = ((ucmd->buttons >> 2) & 1); sv_player->v->button1 = ((ucmd->buttons >> 2) & 1);
// DP_INPUTBUTTONS // DP_INPUTBUTTONS
sv_player->xv->button3 = ((ucmd->buttons >> 2) & 1); sv_player->xv->button3 = ((ucmd->buttons >> 2) & 1);
@ -5843,10 +5956,18 @@ void SV_ReadQCRequest(void)
} }
done: done:
args[i] = 0;
rname = MSG_ReadString(); rname = MSG_ReadString();
f = PR_FindFunction(svprogfuncs, va("Cmd_%s_%s", rname, args), PR_ANY); if (i)
rname = va("Cmd_%s_%s", rname, args);
else
rname = va("Cmd_%s", rname);
f = PR_FindFunction(svprogfuncs, rname, PR_ANY);
if (f) if (f)
{
pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, sv_player);
PR_ExecuteProgram(svprogfuncs, f); PR_ExecuteProgram(svprogfuncs, f);
}
else else
SV_ClientPrintf(host_client, PRINT_HIGH, "qcrequest \"%s\" not supported\n", rname); SV_ClientPrintf(host_client, PRINT_HIGH, "qcrequest \"%s\" not supported\n", rname);
} }
@ -5916,8 +6037,8 @@ void SV_ExecuteClientMessage (client_t *cl)
if (temp1.ival) if (temp1.ival)
frame = &cl->frameunion.frames[(cl->netchan.incoming_acknowledged+temp1.ival) & UPDATE_MASK]; frame = &cl->frameunion.frames[(cl->netchan.incoming_acknowledged+temp1.ival) & UPDATE_MASK];
*/ */
#ifdef _MSC_VER #ifdef warningmsg
#pragma message("FIXME: make antilag optionally support non-player ents too") #pragma warningmsg("FIXME: make antilag optionally support non-player ents too")
#endif #endif
for (i = 0; i < sv.allocated_client_slots; i++) for (i = 0; i < sv.allocated_client_slots; i++)
{ {
@ -6082,7 +6203,7 @@ haveannothergo:
sv_player->v->button0 = newcmd.buttons & 1; sv_player->v->button0 = newcmd.buttons & 1;
sv_player->v->button2 = (newcmd.buttons >> 1) & 1; sv_player->v->button2 = (newcmd.buttons >> 1) & 1;
if (pr_allowbutton1.value) //many mods use button1 - it's just a wasted field to many mods. So only work it if the cvar allows. if (pr_allowbutton1.ival) //many mods use button1 - it's just a wasted field to many mods. So only work it if the cvar allows.
sv_player->v->button1 = ((newcmd.buttons >> 2) & 1); sv_player->v->button1 = ((newcmd.buttons >> 2) & 1);
// DP_INPUTBUTTONS // DP_INPUTBUTTONS
sv_player->xv->button3 = ((newcmd.buttons >> 2) & 1); sv_player->xv->button3 = ((newcmd.buttons >> 2) & 1);
@ -6453,7 +6574,7 @@ void SVNQ_ReadClientMove (usercmd_t *move)
host_client->edict->v->button0 = bits & 1; host_client->edict->v->button0 = bits & 1;
host_client->edict->v->button2 = (bits >> 1) & 1; host_client->edict->v->button2 = (bits >> 1) & 1;
if (pr_allowbutton1.value) //many mods use button1 - it's just a wasted field to many mods. So only work it if the cvar allows. if (pr_allowbutton1.ival) //many mods use button1 - it's just a wasted field to many mods. So only work it if the cvar allows.
host_client->edict->v->button1 = ((bits >> 2) & 1); host_client->edict->v->button1 = ((bits >> 2) & 1);
// DP_INPUTBUTTONS // DP_INPUTBUTTONS
host_client->edict->xv->button3 = ((bits >> 2) & 1); host_client->edict->xv->button3 = ((bits >> 2) & 1);
@ -6532,9 +6653,9 @@ void SVNQ_ExecuteClientMessage (client_t *cl)
case clc_nop: case clc_nop:
break; break;
case clc_delta: // case clc_delta:
cl->delta_sequence = MSG_ReadByte (); // cl->delta_sequence = MSG_ReadByte ();
break; // break;
case clc_move: case clc_move:
SVNQ_ReadClientMove (&host_client->lastcmd); SVNQ_ReadClientMove (&host_client->lastcmd);
@ -6550,11 +6671,11 @@ void SVNQ_ExecuteClientMessage (client_t *cl)
sv_player = cl->edict; sv_player = cl->edict;
break; break;
case 50: case clcdp_ackframe:
MSG_ReadLong(); cl->delta_sequence = MSG_ReadLong();
break; break;
case clcdp_ackdownloaddata: case clcdp_ackdownloaddata:
SV_DarkPlacesDownloadAck(host_client); SV_DarkPlacesDownloadAck(cl);
break; break;
#ifdef VOICECHAT #ifdef VOICECHAT
@ -6601,6 +6722,7 @@ void SV_UserInit (void)
Cvar_Register (&sv_pushplayers, cvargroup_servercontrol); Cvar_Register (&sv_pushplayers, cvargroup_servercontrol);
Cvar_Register (&sv_pure, cvargroup_servercontrol);
Cvar_Register (&sv_floodprotect, cvargroup_servercontrol); Cvar_Register (&sv_floodprotect, cvargroup_servercontrol);
Cvar_Register (&sv_floodprotect_interval, cvargroup_servercontrol); Cvar_Register (&sv_floodprotect_interval, cvargroup_servercontrol);
Cvar_Register (&sv_floodprotect_messages, cvargroup_servercontrol); Cvar_Register (&sv_floodprotect_messages, cvargroup_servercontrol);

View file

@ -1112,10 +1112,7 @@ void SVHL_Physics_Step (hledict_t *ent)
{ {
if (hitsound) if (hitsound)
{ {
if (progstype == PROG_H2) SVHL_StartSound (ent, 0, "demon/dland2.wav", 255, 1);
SVHL_StartSound (ent, 0, "fx/thngland.wav", 255, 1);
else
SVHL_StartSound (ent, 0, "demon/dland2.wav", 255, 1);
} }
} }
} }

View file

@ -45,6 +45,7 @@ texture_t r_notexture_mip_real;
texture_t *r_notexture_mip = &r_notexture_mip_real; texture_t *r_notexture_mip = &r_notexture_mip_real;
cvar_t sv_nogetlight = SCVAR("sv_nogetlight", "0"); cvar_t sv_nogetlight = SCVAR("sv_nogetlight", "0");
cvar_t dpcompat_psa_ungroup = SCVAR ("dpcompat_psa_ungroup", "0");
unsigned *model_checksum; unsigned *model_checksum;
@ -199,6 +200,7 @@ void Mod_Init (void)
{ {
memset (mod_novis, 0xff, sizeof(mod_novis)); memset (mod_novis, 0xff, sizeof(mod_novis));
Cvar_Register(&sv_nogetlight, "Memory preservation"); Cvar_Register(&sv_nogetlight, "Memory preservation");
Cvar_Register (&dpcompat_psa_ungroup, "Darkplaces compatibility");
} }
/* /*
@ -873,28 +875,34 @@ qboolean Mod_LoadSubmodels (lump_t *l)
Mod_LoadEdges Mod_LoadEdges
================= =================
*/ */
qboolean Mod_LoadEdges (lump_t *l) qboolean Mod_LoadEdges (lump_t *l, qboolean lm)
{ {
dedge_t *in;
medge_t *out; medge_t *out;
int i, count; int i, count;
in = (void *)(mod_base + l->fileofs); if (lm)
if (l->filelen % sizeof(*in))
{ {
Con_Printf ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name); #pragma warningmsg("bsp2 todo")
return false;
} }
count = l->filelen / sizeof(*in); else
out = Hunk_AllocName ( (count + 1) * sizeof(*out), loadname);
loadmodel->edges = out;
loadmodel->numedges = count;
for ( i=0 ; i<count ; i++, in++, out++)
{ {
out->v[0] = (unsigned short)LittleShort(in->v[0]); dsedge_t *in = (void *)(mod_base + l->fileofs);
out->v[1] = (unsigned short)LittleShort(in->v[1]); if (l->filelen % sizeof(*in))
{
Con_Printf ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
return false;
}
count = l->filelen / sizeof(*in);
out = Hunk_AllocName ( (count + 1) * sizeof(*out), loadname);
loadmodel->edges = out;
loadmodel->numedges = count;
for ( i=0 ; i<count ; i++, in++, out++)
{
out->v[0] = (unsigned short)LittleShort(in->v[0]);
out->v[1] = (unsigned short)LittleShort(in->v[1]);
}
} }
return true; return true;
} }
@ -1028,20 +1036,28 @@ void CalcSurfaceExtents (msurface_t *s);
Mod_LoadFaces Mod_LoadFaces
================= =================
*/ */
qboolean Mod_LoadFaces (lump_t *l) qboolean Mod_LoadFaces (lump_t *l, qboolean lm)
{ {
dface_t *in; dsface_t *in;
msurface_t *out; msurface_t *out;
int i, count, surfnum; int i, count, surfnum;
int planenum, side; int planenum, side;
in = (void *)(mod_base + l->fileofs); if (lm)
if (l->filelen % sizeof(*in))
{ {
Con_Printf ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name); in = NULL;
return false; #pragma warningmsg("bsp2 fixme")
}
else
{
in = (void *)(mod_base + l->fileofs);
if (l->filelen % sizeof(*in))
{
Con_Printf ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
return false;
}
count = l->filelen / sizeof(*in);
} }
count = l->filelen / sizeof(*in);
out = Hunk_AllocName ( count*sizeof(*out), loadname); out = Hunk_AllocName ( count*sizeof(*out), loadname);
loadmodel->surfaces = out; loadmodel->surfaces = out;
@ -1049,8 +1065,15 @@ qboolean Mod_LoadFaces (lump_t *l)
for ( surfnum=0 ; surfnum<count ; surfnum++, in++, out++) for ( surfnum=0 ; surfnum<count ; surfnum++, in++, out++)
{ {
out->firstedge = LittleLong(in->firstedge); if (lm)
out->numedges = LittleShort(in->numedges); {
#pragma warningmsg("bsp2 fixme")
}
else
{
out->firstedge = LittleLong(in->firstedge);
out->numedges = LittleShort(in->numedges);
}
out->flags = 0; out->flags = 0;
planenum = LittleShort(in->planenum); planenum = LittleShort(in->planenum);
@ -1119,48 +1142,54 @@ void Mod_SetParent (mnode_t *node, mnode_t *parent)
Mod_LoadNodes Mod_LoadNodes
================= =================
*/ */
qboolean Mod_LoadNodes (lump_t *l) qboolean Mod_LoadNodes (lump_t *l, qboolean lm)
{ {
int i, j, count, p; int i, j, count, p;
dnode_t *in; dsnode_t *in;
mnode_t *out; mnode_t *out;
in = (void *)(mod_base + l->fileofs); if (lm)
if (l->filelen % sizeof(*in))
{ {
Con_Printf (CON_ERROR "MOD_LoadBmodel: funny lump size in %s\n",loadmodel->name); #pragma warningmsg("bsp2 fixme")
return false;
} }
count = l->filelen / sizeof(*in); else
out = Hunk_AllocName ( count*sizeof(*out), loadname);
loadmodel->nodes = out;
loadmodel->numnodes = count;
for ( i=0 ; i<count ; i++, in++, out++)
{ {
for (j=0 ; j<3 ; j++) in = (void *)(mod_base + l->fileofs);
if (l->filelen % sizeof(*in))
{ {
out->minmaxs[j] = LittleShort (in->mins[j]); Con_Printf (CON_ERROR "MOD_LoadBmodel: funny lump size in %s\n",loadmodel->name);
out->minmaxs[3+j] = LittleShort (in->maxs[j]); return false;
} }
count = l->filelen / sizeof(*in);
out = Hunk_AllocName ( count*sizeof(*out), loadname);
p = LittleLong(in->planenum); loadmodel->nodes = out;
out->plane = loadmodel->planes + p; loadmodel->numnodes = count;
out->firstsurface = LittleShort (in->firstface); for ( i=0 ; i<count ; i++, in++, out++)
out->numsurfaces = LittleShort (in->numfaces);
for (j=0 ; j<2 ; j++)
{ {
p = LittleShort (in->children[j]); for (j=0 ; j<3 ; j++)
if (p >= 0) {
out->children[j] = loadmodel->nodes + p; out->minmaxs[j] = LittleShort (in->mins[j]);
else out->minmaxs[3+j] = LittleShort (in->maxs[j]);
out->children[j] = (mnode_t *)(loadmodel->leafs + (-1 - p)); }
p = LittleLong(in->planenum);
out->plane = loadmodel->planes + p;
out->firstsurface = LittleShort (in->firstface);
out->numsurfaces = LittleShort (in->numfaces);
for (j=0 ; j<2 ; j++)
{
p = LittleShort (in->children[j]);
if (p >= 0)
out->children[j] = loadmodel->nodes + p;
else
out->children[j] = (mnode_t *)(loadmodel->leafs + (-1 - p));
}
} }
} }
Mod_SetParent (loadmodel->nodes, NULL); // sets nodes and leafs Mod_SetParent (loadmodel->nodes, NULL); // sets nodes and leafs
return true; return true;
@ -1171,47 +1200,54 @@ qboolean Mod_LoadNodes (lump_t *l)
Mod_LoadLeafs Mod_LoadLeafs
================= =================
*/ */
qboolean Mod_LoadLeafs (lump_t *l) qboolean Mod_LoadLeafs (lump_t *l, qboolean lm)
{ {
dleaf_t *in; dsleaf_t *in;
mleaf_t *out; mleaf_t *out;
int i, j, count, p; int i, j, count, p;
in = (void *)(mod_base + l->fileofs); if (lm)
if (l->filelen % sizeof(*in))
{ {
Con_Printf (CON_ERROR "MOD_LoadBmodel: funny lump size in %s\n",loadmodel->name); #pragma warningmsg("bsp2 fixme")
return false;
} }
count = l->filelen / sizeof(*in); else
out = Hunk_AllocName ( count*sizeof(*out), loadname);
loadmodel->leafs = out;
loadmodel->numleafs = count;
for ( i=0 ; i<count ; i++, in++, out++)
{ {
for (j=0 ; j<3 ; j++) in = (void *)(mod_base + l->fileofs);
if (l->filelen % sizeof(*in))
{ {
out->minmaxs[j] = LittleShort (in->mins[j]); Con_Printf (CON_ERROR "MOD_LoadBmodel: funny lump size in %s\n",loadmodel->name);
out->minmaxs[3+j] = LittleShort (in->maxs[j]); return false;
} }
count = l->filelen / sizeof(*in);
out = Hunk_AllocName ( count*sizeof(*out), loadname);
p = LittleLong(in->contents); loadmodel->leafs = out;
out->contents = p; loadmodel->numleafs = count;
out->firstmarksurface = loadmodel->marksurfaces + for ( i=0 ; i<count ; i++, in++, out++)
(unsigned short)LittleShort(in->firstmarksurface); {
out->nummarksurfaces = (unsigned short)LittleShort(in->nummarksurfaces); for (j=0 ; j<3 ; j++)
{
out->minmaxs[j] = LittleShort (in->mins[j]);
out->minmaxs[3+j] = LittleShort (in->maxs[j]);
}
p = LittleLong(in->visofs); p = LittleLong(in->contents);
if (p == -1) out->contents = p;
out->compressed_vis = NULL;
else
out->compressed_vis = loadmodel->visdata + p;
for (j=0 ; j<4 ; j++) out->firstmarksurface = loadmodel->marksurfaces +
out->ambient_sound_level[j] = in->ambient_level[j]; (unsigned short)LittleShort(in->firstmarksurface);
out->nummarksurfaces = (unsigned short)LittleShort(in->nummarksurfaces);
p = LittleLong(in->visofs);
if (p == -1)
out->compressed_vis = NULL;
else
out->compressed_vis = loadmodel->visdata + p;
for (j=0 ; j<4 ; j++)
out->ambient_sound_level[j] = in->ambient_level[j];
}
} }
return true; return true;
@ -1222,26 +1258,110 @@ qboolean Mod_LoadLeafs (lump_t *l)
Mod_LoadClipnodes Mod_LoadClipnodes
================= =================
*/ */
qboolean Mod_LoadClipnodes (lump_t *l) qboolean Mod_LoadClipnodes (lump_t *l, qboolean lm)
{ {
dclipnode_t *in; dsclipnode_t *in;
mclipnode_t *out; mclipnode_t *out;
int i, count; int i, count;
hull_t *hull; hull_t *hull;
in = (void *)(mod_base + l->fileofs); if (lm)
if (l->filelen % sizeof(*in))
{ {
Con_Printf (CON_ERROR "MOD_LoadBmodel: funny lump size in %s\n",loadmodel->name); #pragma warningmsg("bsp2 fixme")
return false; in = NULL;
}
else
{
in = (void *)(mod_base + l->fileofs);
if (l->filelen % sizeof(*in))
{
Con_Printf (CON_ERROR "MOD_LoadBmodel: funny lump size in %s\n",loadmodel->name);
return false;
}
count = l->filelen / sizeof(*in);
} }
count = l->filelen / sizeof(*in);
out = Hunk_AllocName ( count*sizeof(*out), loadname); out = Hunk_AllocName ( count*sizeof(*out), loadname);
loadmodel->clipnodes = out; loadmodel->clipnodes = out;
loadmodel->numclipnodes = count; loadmodel->numclipnodes = count;
if (loadmodel->fromgame == fg_halflife) if (hexen2map)
{ //hexen2.
hexen2map=false;
hull = &loadmodel->hulls[1];
hull->clipnodes = out;
hull->firstclipnode = 0;
hull->lastclipnode = count-1;
hull->planes = loadmodel->planes;
hull->clip_mins[0] = -16;
hull->clip_mins[1] = -16;
hull->clip_mins[2] = -24;
hull->clip_maxs[0] = 16;
hull->clip_maxs[1] = 16;
hull->clip_maxs[2] = 32;
hull->available = true;
hull = &loadmodel->hulls[2];
hull->clipnodes = out;
hull->firstclipnode = 0;
hull->lastclipnode = count-1;
hull->planes = loadmodel->planes;
hull->clip_mins[0] = -24;
hull->clip_mins[1] = -24;
hull->clip_mins[2] = -20;
hull->clip_maxs[0] = 24;
hull->clip_maxs[1] = 24;
hull->clip_maxs[2] = 20;
hull->available = true;
hull = &loadmodel->hulls[3];
hull->clipnodes = out;
hull->firstclipnode = 0;
hull->lastclipnode = count-1;
hull->planes = loadmodel->planes;
hull->clip_mins[0] = -16;
hull->clip_mins[1] = -16;
hull->clip_mins[2] = -12;
hull->clip_maxs[0] = 16;
hull->clip_maxs[1] = 16;
hull->clip_maxs[2] = 16;
hull->available = true;
/*
There is some mission-pack weirdness here
in the missionpack, hull 4 is meant to be '-8 -8 -8' '8 8 8'
in the original game, hull 4 is '-40 -40 -42' '40 40 42'
*/
hull = &loadmodel->hulls[4];
hull->clipnodes = out;
hull->firstclipnode = 0;
hull->lastclipnode = count-1;
hull->planes = loadmodel->planes;
hull->clip_mins[0] = -8;
hull->clip_mins[1] = -8;
hull->clip_mins[2] = -8;
hull->clip_maxs[0] = 8;
hull->clip_maxs[1] = 8;
hull->clip_maxs[2] = 8;
hull->available = true;
hull = &loadmodel->hulls[5];
hull->clipnodes = out;
hull->firstclipnode = 0;
hull->lastclipnode = count-1;
hull->planes = loadmodel->planes;
hull->clip_mins[0] = -48;
hull->clip_mins[1] = -48;
hull->clip_mins[2] = -50;
hull->clip_maxs[0] = 48;
hull->clip_maxs[1] = 48;
hull->clip_maxs[2] = 50;
hull->available = true;
//6 isn't used.
//7 isn't used.
}
else if (loadmodel->fromgame == fg_halflife)
{ {
hull = &loadmodel->hulls[1]; hull = &loadmodel->hulls[1];
hull->clipnodes = out; hull->clipnodes = out;
@ -1324,11 +1444,18 @@ qboolean Mod_LoadClipnodes (lump_t *l)
hull->available = false; hull->available = false;
} }
for (i=0 ; i<count ; i++, out++, in++) if (lm)
{ {
out->planenum = LittleLong(in->planenum); #pragma warningmsg("bsp2 fixme")
out->children[0] = LittleShort(in->children[0]); }
out->children[1] = LittleShort(in->children[1]); else
{
for (i=0 ; i<count ; i++, out++, in++)
{
out->planenum = LittleLong(in->planenum);
out->children[0] = LittleShort(in->children[0]);
out->children[1] = LittleShort(in->children[1]);
}
} }
return true; return true;
@ -1486,6 +1613,7 @@ qboolean Mod_LoadBrushModel (model_t *mod, void *buffer)
unsigned int chksum; unsigned int chksum;
int start; int start;
qboolean noerrors; qboolean noerrors;
qboolean longm = false;
start = Hunk_LowMark(); start = Hunk_LowMark();
@ -1496,7 +1624,12 @@ qboolean Mod_LoadBrushModel (model_t *mod, void *buffer)
i = LittleLong (header->version); i = LittleLong (header->version);
if (i == BSPVERSION || i == BSPVERSIONPREREL) if (i == BSPVERSION_LONG)
{
loadmodel->fromgame = fg_quake;
longm = true;
}
else if (i == BSPVERSION || i == BSPVERSIONPREREL)
loadmodel->fromgame = fg_quake; loadmodel->fromgame = fg_quake;
else if (i == BSPVERSIONHL) else if (i == BSPVERSIONHL)
loadmodel->fromgame = fg_halflife; loadmodel->fromgame = fg_halflife;
@ -1541,7 +1674,7 @@ qboolean Mod_LoadBrushModel (model_t *mod, void *buffer)
if (!sv_nogetlight.value) if (!sv_nogetlight.value)
{ {
noerrors = noerrors && Mod_LoadVertexes (&header->lumps[LUMP_VERTEXES]); noerrors = noerrors && Mod_LoadVertexes (&header->lumps[LUMP_VERTEXES]);
noerrors = noerrors && Mod_LoadEdges (&header->lumps[LUMP_EDGES]); noerrors = noerrors && Mod_LoadEdges (&header->lumps[LUMP_EDGES], longm);
noerrors = noerrors && Mod_LoadSurfedges (&header->lumps[LUMP_SURFEDGES]); noerrors = noerrors && Mod_LoadSurfedges (&header->lumps[LUMP_SURFEDGES]);
///*/on server?*/ Mod_LoadTextures (&header->lumps[LUMP_TEXTURES]); ///*/on server?*/ Mod_LoadTextures (&header->lumps[LUMP_TEXTURES]);
noerrors = noerrors && Mod_LoadLighting (&header->lumps[LUMP_LIGHTING]); noerrors = noerrors && Mod_LoadLighting (&header->lumps[LUMP_LIGHTING]);
@ -1551,14 +1684,14 @@ qboolean Mod_LoadBrushModel (model_t *mod, void *buffer)
if (!sv_nogetlight.value) if (!sv_nogetlight.value)
{ {
noerrors = noerrors && Mod_LoadTexinfo (&header->lumps[LUMP_TEXINFO]); noerrors = noerrors && Mod_LoadTexinfo (&header->lumps[LUMP_TEXINFO]);
noerrors = noerrors && Mod_LoadFaces (&header->lumps[LUMP_FACES]); noerrors = noerrors && Mod_LoadFaces (&header->lumps[LUMP_FACES], longm);
} }
// Mod_LoadMarksurfaces (&header->lumps[LUMP_MARKSURFACES]); // Mod_LoadMarksurfaces (&header->lumps[LUMP_MARKSURFACES]);
if (noerrors) if (noerrors)
Mod_LoadVisibility (&header->lumps[LUMP_VISIBILITY]); Mod_LoadVisibility (&header->lumps[LUMP_VISIBILITY]);
noerrors = noerrors && Mod_LoadLeafs (&header->lumps[LUMP_LEAFS]); noerrors = noerrors && Mod_LoadLeafs (&header->lumps[LUMP_LEAFS], longm);
noerrors = noerrors && Mod_LoadNodes (&header->lumps[LUMP_NODES]); noerrors = noerrors && Mod_LoadNodes (&header->lumps[LUMP_NODES], longm);
noerrors = noerrors && Mod_LoadClipnodes (&header->lumps[LUMP_CLIPNODES]); noerrors = noerrors && Mod_LoadClipnodes (&header->lumps[LUMP_CLIPNODES], longm);
if (noerrors) if (noerrors)
{ {
Mod_LoadEntities (&header->lumps[LUMP_ENTITIES]); Mod_LoadEntities (&header->lumps[LUMP_ENTITIES]);

View file

@ -637,7 +637,7 @@ static model_t *SVQ2_GetCModel(world_t *w, int modelindex)
void SVQ2_InitWorld(void) void SVQ2_InitWorld(void)
{ {
sv.world.GetCModel = SVQ2_GetCModel; sv.world.Get_CModel = SVQ2_GetCModel;
} }
qboolean SVQ2_InitGameProgs(void) qboolean SVQ2_InitGameProgs(void)

View file

@ -66,6 +66,7 @@ static int q3_num_snapshot_entities;
static int q3_next_snapshot_entities; static int q3_next_snapshot_entities;
static q3entityState_t *q3_snapshot_entities; static q3entityState_t *q3_snapshot_entities;
static q3entityState_t *q3_baselines; static q3entityState_t *q3_baselines;
extern cvar_t sv_pure;
#define NUM_FOR_GENTITY(ge) (((char*)ge - (char*)q3_entarray) / sizeofq3gentity) #define NUM_FOR_GENTITY(ge) (((char*)ge - (char*)q3_entarray) / sizeofq3gentity)
#define NUM_FOR_SENTITY(se) (se - q3_sentities) #define NUM_FOR_SENTITY(se) (se - q3_sentities)
@ -1676,8 +1677,6 @@ qboolean SVQ3_InitGame(void)
char buffer[8192]; char buffer[8192];
char *str; char *str;
char sysinfo[8192]; char sysinfo[8192];
extern cvar_t progs;
cvar_t *sv_pure;
if (sv.world.worldmodel->type == mod_heightmap) if (sv.world.worldmodel->type == mod_heightmap)
{ {
@ -1688,7 +1687,7 @@ qboolean SVQ3_InitGame(void)
return false; //always fail on q1bsp return false; //always fail on q1bsp
} }
if (*progs.string) //don't load q3 gamecode if we're explicitally told to load a progs. if (*pr_ssqc_progs.string) //don't load q3 gamecode if we're explicitally told to load a progs.
return false; return false;
@ -1705,11 +1704,13 @@ qboolean SVQ3_InitGame(void)
q3_sentities = Z_Malloc(sizeof(q3serverEntity_t)*MAX_GENTITIES); q3_sentities = Z_Malloc(sizeof(q3serverEntity_t)*MAX_GENTITIES);
/*qw serverinfo settings are not normally visible in the q3 serverinfo*/
strcpy(buffer, svs.info); strcpy(buffer, svs.info);
Info_SetValueForKey(buffer, "map", "", sizeof(buffer)); Info_SetValueForKey(buffer, "map", "", sizeof(buffer));
Info_SetValueForKey(buffer, "maxclients", "", sizeof(buffer)); Info_SetValueForKey(buffer, "maxclients", "", sizeof(buffer));
Info_SetValueForKey(buffer, "mapname", sv.name, sizeof(buffer)); Info_SetValueForKey(buffer, "mapname", sv.name, sizeof(buffer));
Info_SetValueForKey(buffer, "sv_maxclients", "32", sizeof(buffer)); Info_SetValueForKey(buffer, "sv_maxclients", "32", sizeof(buffer));
Info_SetValueForKey(buffer, "sv_pure", "", sizeof(buffer));
SVQ3_SetConfigString(0, buffer); SVQ3_SetConfigString(0, buffer);
Cvar_Set(Cvar_Get("sv_running", "0", 0, "Q3 compatability"), "1"); Cvar_Set(Cvar_Get("sv_running", "0", 0, "Q3 compatability"), "1");
@ -1720,17 +1721,16 @@ qboolean SVQ3_InitGame(void)
str = FS_GetPackHashes(buffer, sizeof(buffer), false); str = FS_GetPackHashes(buffer, sizeof(buffer), false);
Info_SetValueForKey(sysinfo, "sv_paks", str, MAX_SERVERINFO_STRING); Info_SetValueForKey(sysinfo, "sv_paks", str, MAX_SERVERINFO_STRING);
str = FS_GetPackNames(buffer, sizeof(buffer), false); str = FS_GetPackNames(buffer, sizeof(buffer), false, false);
Info_SetValueForKey(sysinfo, "sv_pakNames", str, MAX_SERVERINFO_STRING); Info_SetValueForKey(sysinfo, "sv_pakNames", str, MAX_SERVERINFO_STRING);
str = FS_GetPackHashes(buffer, sizeof(buffer), true); str = FS_GetPackHashes(buffer, sizeof(buffer), true);
Info_SetValueForKey(sysinfo, "sv_referencedPaks", str, MAX_SERVERINFO_STRING); Info_SetValueForKey(sysinfo, "sv_referencedPaks", str, MAX_SERVERINFO_STRING);
str = FS_GetPackNames(buffer, sizeof(buffer), true); str = FS_GetPackNames(buffer, sizeof(buffer), true, false);
Info_SetValueForKey(sysinfo, "sv_referencedPakNames", str, MAX_SERVERINFO_STRING); Info_SetValueForKey(sysinfo, "sv_referencedPakNames", str, MAX_SERVERINFO_STRING);
sv_pure = Cvar_Get("sv_pure", "1", 0, "Q3 compatability"); Info_SetValueForKey(sysinfo, "sv_pure", sv_pure.string, MAX_SERVERINFO_STRING);
Info_SetValueForKey(sysinfo, "sv_pure", sv_pure->string, MAX_SERVERINFO_STRING);
SVQ3_SetConfigString(1, sysinfo); SVQ3_SetConfigString(1, sysinfo);
@ -2133,8 +2133,8 @@ q3playerState_t *SVQ3Q1_BuildPlayerState(client_t *client)
memset(&state, 0, sizeof(state)); memset(&state, 0, sizeof(state));
#ifdef _MSC_VER #ifdef warningmsg
#pragma message("qwoverq3: other things will need to be packed into here.") #pragma warningmsg("qwoverq3: other things will need to be packed into here.")
#endif #endif
state.commandTime = client->lastcmd.servertime; state.commandTime = client->lastcmd.servertime;
@ -2346,8 +2346,8 @@ void SVQ3_BuildClientSnapshot( client_t *client )
void SVQ3Q1_ConvertEntStateQ1ToQ3(entity_state_t *q1, q3entityState_t *q3) void SVQ3Q1_ConvertEntStateQ1ToQ3(entity_state_t *q1, q3entityState_t *q3)
{ {
#ifdef _MSC_VER #ifdef warningmsg
#pragma message("qwoverq3: This _WILL_ need extending") #pragma warningmsg("qwoverq3: This _WILL_ need extending")
#endif #endif
q3->number = q1->number; q3->number = q1->number;
@ -2862,8 +2862,8 @@ void SVQ3_ParseUsercmd(client_t *client, qboolean delta)
{ {
usercmd_t temp; usercmd_t temp;
temp = client->lastcmd; temp = client->lastcmd;
#ifdef _MSC_VER #ifdef warningmsg
#pragma message("qwoverq3: you need to be aware of this if you're making a compatible cgame") #pragma warningmsg("qwoverq3: you need to be aware of this if you're making a compatible cgame")
#endif #endif
//if you read the q3 code, you'll see that the speed value used is 64 for walking, and 127 for running (full speed). //if you read the q3 code, you'll see that the speed value used is 64 for walking, and 127 for running (full speed).
//so we map full to full here. //so we map full to full here.

View file

@ -1021,7 +1021,7 @@ static trace_t World_ClipMoveToEntity (world_t *w, wedict_t *ent, vec3_t eorg, v
// get the clipping hull // get the clipping hull
if (ent->v->solid == SOLID_BSP) if (ent->v->solid == SOLID_BSP)
{ {
model = w->GetCModel(w, ent->v->modelindex); model = w->Get_CModel(w, ent->v->modelindex);
if (!model || (model->type != mod_brush && model->type != mod_heightmap)) if (!model || (model->type != mod_brush && model->type != mod_heightmap))
Host_Error("SOLID_BSP with non bsp model (classname: %s)", PR_GetString(w->progs, ent->v->classname)); Host_Error("SOLID_BSP with non bsp model (classname: %s)", PR_GetString(w->progs, ent->v->classname));
} }
@ -1056,7 +1056,7 @@ static trace_t World_ClipMoveToEntity (world_t *w, wedict_t *ent, vec3_t eorg, v
model_t *model; model_t *model;
if (ent->v->modelindex < 1 || ent->v->modelindex >= MAX_MODELS) if (ent->v->modelindex < 1 || ent->v->modelindex >= MAX_MODELS)
Host_Error("SV_ClipMoveToEntity: modelindex out of range\n"); Host_Error("SV_ClipMoveToEntity: modelindex out of range\n");
model = w->GetCModel(w, ent->v->modelindex); model = w->Get_CModel(w, ent->v->modelindex);
if (model && model->funcs.Trace) if (model && model->funcs.Trace)
{ {
@ -1081,7 +1081,7 @@ static trace_t WorldQ2_ClipMoveToEntity (world_t *w, q2edict_t *ent, vec3_t star
// get the clipping hull // get the clipping hull
if (ent->s.solid == Q2SOLID_BSP) if (ent->s.solid == Q2SOLID_BSP)
{ {
model = w->GetCModel(w, ent->s.modelindex); model = w->Get_CModel(w, ent->s.modelindex);
if (!model || model->type != mod_brush) if (!model || model->type != mod_brush)
SV_Error("SOLID_BSP with non bsp model"); SV_Error("SOLID_BSP with non bsp model");
} }
@ -1282,7 +1282,7 @@ static model_t *WorldQ2_ModelForEntity (world_t *w, q2edict_t *ent)
// decide which clipping hull to use, based on the size // decide which clipping hull to use, based on the size
if (ent->solid == Q2SOLID_BSP) if (ent->solid == Q2SOLID_BSP)
{ // explicit hulls in the BSP model { // explicit hulls in the BSP model
model = w->GetCModel(w, ent->s.modelindex); model = w->Get_CModel(w, ent->s.modelindex);
if (!model) if (!model)
SV_Error ("Q2SOLID_BSP with a non bsp model"); SV_Error ("Q2SOLID_BSP with a non bsp model");

View file

@ -53,6 +53,12 @@ game specifies which game you are trying to target. Explicitly supported values
/*set it to some server*/ /*set it to some server*/
fte.server = "192.168.0.1:27500"; fte.server = "192.168.0.1:27500";
/*explicitly activate it without requiring the user to click on it. only one plugin instance can be active at once. use with caution, or at least not on more than one plugin object on page site.*/ /*explicitly activate it without requiring the user to click on it. only one plugin instance can be active at once. use with caution, or at least not on more than one plugin object on page site.*/
fte.running = 1; // fte.running = 1;
document.write(fte.plugver); document.write(fte.plugver);
</script> </script>
<br/>
<a onclick="script:fte.running=1;">run</a><br/>
<a onclick="script:fte.width=640;fte.height=480;">640*480</a><br/>
<a onclick="script:fte.width=800;fte.height=600;">800*600</a><br/>
<a onclick="script:fte.width=1024;fte.height=768;">1024*768</a><br/>