-#define BUILDNUMBER 73
+#define BUILDNUMBER 75
int buildnumber = BUILDNUMBER;
if (ent->msgtime != cl.mtime[0])
{
ent->model = NULL;
+ // LordHavoc: free on the same frame, not the next
+ if (ent->forcelink)
+ R_RemoveEfrags (ent); // just became empty
continue;
}
+ // LordHavoc: animation interpolation, note: framegroups partially override this in the renderer
+ /*
+ if (ent->model != ent->lerp_model || ent->lerp_time > cl.time)
+ {
+ ent->lerp_frame1 = ent->lerp_frame2 = ent->frame;
+ ent->lerp_time = cl.time;
+ ent->lerp = 0;
+ }
+ else if (ent->frame != ent->lerp_frame2)
+ {
+ ent->lerp_frame1 = ent->lerpframe2;
+ ent->lerp_frame2 = ent->frame;
+ ent->lerp_time = cl.time;
+ ent->lerp = 0;
+ }
+ else
+ ent->lerp = bound(0, (cl.time - ent->lerp_time) * 10.0f, 1);
+ */
+
VectorCopy (ent->origin, oldorg);
if (ent->forcelink)
Host_Error ("CL_EntityNum: %i is an invalid number",num);
while (cl.num_entities<=num)
{
- cl_entities[cl.num_entities].colormap = 0; //vid.colormap;
+ cl_entities[cl.num_entities].colormap = -1; // no special coloring
cl.num_entities++;
}
}
ent->syncbase = model->synctype == ST_RAND ? (float)(rand()&0x7fff) / 0x7fff : 0.0;
else
forcelink = true; // hack to make null model players work
- if (num > 0 && num <= cl.maxclients)
- R_TranslatePlayerSkin(num - 1);
}
ent->frame = ((bits & U_FRAME) ? MSG_ReadByte() : (baseline->frame & 0xFF));
i = bits & U_COLORMAP ? MSG_ReadByte() : baseline->colormap;
ent->deltabaseline.colormap = i;
if (!i)
- ent->colormap = 0; //vid.colormap;
+ ent->colormap = -1; // no special coloring
else
{
if (i > cl.maxclients)
Host_Error ("i >= cl.maxclients");
- ent->colormap = i; //vid.colormap; // cl.scores[i-1].translations;
+ ent->colormap = cl.scores[i-1].colors; // color it
}
skin = bits & U_SKIN ? MSG_ReadByte() : baseline->skin;
if (skin != ent->skinnum)
{
ent->skinnum = skin;
- if (num > 0 && num <= cl.maxclients)
- R_TranslatePlayerSkin(num - 1);
}
ent->deltabaseline.skin = skin;
// copy it to the current state
ent->model = cl.model_precache[ent->baseline.modelindex];
ent->frame = ent->baseline.frame;
- ent->colormap = 0; //vid.colormap;
+ ent->colormap = -1; // no special coloring
ent->skinnum = ent->baseline.skin;
ent->effects = ent->baseline.effects;
ent->alpha = 1;
if (i >= cl.maxclients)
Host_Error ("CL_ParseServerMessage: svc_updatecolors > MAX_SCOREBOARD");
cl.scores[i].colors = MSG_ReadByte ();
- R_TranslatePlayerSkin(i);
break;
case svc_particle:
void R_ParticleCube (vec3_t mins, vec3_t maxs, vec3_t dir, int count, int colorbase, int gravity, int randomvel);
void R_ParticleRain (vec3_t mins, vec3_t maxs, vec3_t dir, int count, int colorbase, int type);
+// attempts to find the nearest non-solid location, used for explosions mainly
+void FindNonSolidLocation(vec3_t pos)
+{
+ if (SV_HullPointContents (cl.worldmodel->hulls, 0, pos) != CONTENTS_SOLID) return;
+ pos[0]-=1;if (SV_HullPointContents (cl.worldmodel->hulls, 0, pos) != CONTENTS_SOLID) return;
+ pos[0]+=2;if (SV_HullPointContents (cl.worldmodel->hulls, 0, pos) != CONTENTS_SOLID) return;
+ pos[0]-=1;
+ pos[1]-=1;if (SV_HullPointContents (cl.worldmodel->hulls, 0, pos) != CONTENTS_SOLID) return;
+ pos[1]+=2;if (SV_HullPointContents (cl.worldmodel->hulls, 0, pos) != CONTENTS_SOLID) return;
+ pos[1]-=1;
+ pos[2]-=1;if (SV_HullPointContents (cl.worldmodel->hulls, 0, pos) != CONTENTS_SOLID) return;
+ pos[2]+=2;if (SV_HullPointContents (cl.worldmodel->hulls, 0, pos) != CONTENTS_SOLID) return;
+ pos[2]-=1;
+}
+
/*
=================
CL_ParseTEnt
pos[0] = MSG_ReadCoord ();
pos[1] = MSG_ReadCoord ();
pos[2] = MSG_ReadCoord ();
+ FindNonSolidLocation(pos);
R_ParticleExplosion (pos, false);
// R_BlastParticles (pos, 120, 120);
dl = CL_AllocDlight (0);
pos[0] = MSG_ReadCoord ();
pos[1] = MSG_ReadCoord ();
pos[2] = MSG_ReadCoord ();
+ FindNonSolidLocation(pos);
R_ParticleExplosion (pos, false);
// R_BlastParticles (pos, 120, 480);
dl = CL_AllocDlight (0);
pos[0] = MSG_ReadCoord ();
pos[1] = MSG_ReadCoord ();
pos[2] = MSG_ReadCoord ();
+ FindNonSolidLocation(pos);
R_ParticleExplosion (pos, true);
dl = CL_AllocDlight (0);
VectorCopy (pos, dl->origin);
pos[0] = MSG_ReadCoord ();
pos[1] = MSG_ReadCoord ();
pos[2] = MSG_ReadCoord ();
+ FindNonSolidLocation(pos);
R_ParticleExplosion (pos, false);
// R_BlastParticles (pos, 120, 120);
dl = CL_AllocDlight (0);
pos[0] = MSG_ReadCoord ();
pos[1] = MSG_ReadCoord ();
pos[2] = MSG_ReadCoord ();
+ FindNonSolidLocation(pos);
R_ParticleExplosion (pos, false);
// R_BlastParticles (pos, 120, 120);
dl = CL_AllocDlight (0);
pos[0] = MSG_ReadCoord ();
pos[1] = MSG_ReadCoord ();
pos[2] = MSG_ReadCoord ();
+ FindNonSolidLocation(pos);
R_BlobExplosion (pos);
// R_BlastParticles (pos, 120, 120);
pos[0] = MSG_ReadCoord ();
pos[1] = MSG_ReadCoord ();
pos[2] = MSG_ReadCoord ();
+ FindNonSolidLocation(pos);
colorStart = MSG_ReadByte ();
colorLength = MSG_ReadByte ();
R_ParticleExplosion2 (pos, colorStart, colorLength);
cl_visedicts[cl_numvisedicts] = ent;
cl_numvisedicts++;
-// ent->colormap = vid.colormap;
- ent->colormap = 0;
+ ent->colormap = -1; // no special coloring
ent->scale = 1;
ent->alpha = 1;
ent->colormod[0] = ent->colormod[1] = ent->colormod[2] = 1;
float entertime;
int frags;
int colors; // two 4 bit fields
- byte translations[256]; // LordHavoc: major memory reduction (was VID_GRADES*256, and VID_GRADES is 64), and weirdness cleanup
+// byte translations[256]; // LordHavoc: major memory reduction (was VID_GRADES*256, and VID_GRADES is 64), and weirdness cleanup
} scoreboard_t;
typedef struct
#define SIGNONS 4 // signon messages to receive before connected
-// LordHavoc: 256 dynamic lights
-#define MAX_DLIGHTS 256
-typedef struct
-{
- vec3_t origin;
- float radius;
- float die; // stop lighting after this time
- float decay; // drop this each second
- float minlight; // don't add when contributing less
- int key;
- vec3_t color; // LordHavoc: colored lighting
- qboolean dark; // subtracts light instead of adding
-} dlight_t;
-
+#include "r_light.h"
#define MAX_BEAMS 24
typedef struct
if (dpprotocol)
MSG_WriteFloat(sb, f);
else
- MSG_WriteShort (sb, (int)(f*8));
+ MSG_WriteShort (sb, (int)(f*8.0f + 0.5f));
}
void MSG_WritePreciseAngle (sizebuf_t *sb, float f)
{
- MSG_WriteShort (sb, (int) (f*65536.0f/360) & 65535);
+ MSG_WriteShort (sb, (int)(f*(65536.0f/360.0f) + 0.5f) & 65535);
}
+// LordHavoc: round to nearest value, rather than rounding down, fixes crosshair problem
void MSG_WriteAngle (sizebuf_t *sb, float f)
{
- MSG_WriteByte (sb, ((int)f*256/360) & 255);
+ MSG_WriteByte (sb, (int)(f*(256.0f/360.0f) + 0.5f) & 255);
}
//
void Draw_Init (void);
void Draw_Character (int x, int y, int num);
+void Draw_GenericPic (int texnum, float red, float green, float blue, float alpha, float x, float y, float width, float height);
void Draw_Pic (int x, int y, qpic_t *pic);
void Draw_TransPic (int x, int y, qpic_t *pic);
void Draw_TransPicTranslate (int x, int y, qpic_t *pic, byte *translation);
extern unsigned char d_15to8table[65536];
cvar_t qsg_version = {"qsg_version", "1"};
-cvar_t gl_max_size = {"gl_max_size", "1024"};
-cvar_t gl_picmip = {"gl_picmip", "0"};
cvar_t gl_conalpha = {"gl_conalpha", "1"};
-cvar_t gl_lerpimages = {"gl_lerpimages", "1"};
byte *draw_chars; // 8*8 graphic characters
qpic_t *draw_disc;
-int translate_texture;
+//int translate_texture;
int char_texture;
typedef struct
byte conback_buffer[sizeof(qpic_t) + sizeof(glpic_t)];
qpic_t *conback = (qpic_t *)&conback_buffer;
-int gl_filter_min = GL_LINEAR_MIPMAP_LINEAR; //NEAREST;
-int gl_filter_max = GL_LINEAR;
-
-
-int texels;
-
-typedef struct
-{
- int texnum;
- char identifier[64];
- int width, height;
- qboolean mipmap;
-// LordHavoc: 32bit textures
- int bytesperpixel;
-// LordHavoc: CRC to identify cache mismatchs
- int crc;
- int lerped; // whether this texture was uploaded with or without interpolation
-} gltexture_t;
-
-#define MAX_GLTEXTURES 4096
-gltexture_t gltextures[MAX_GLTEXTURES];
-int numgltextures;
-
/*
=============================================================================
int scrap_allocated[MAX_SCRAPS][BLOCK_WIDTH];
byte scrap_texels[MAX_SCRAPS][BLOCK_WIDTH*BLOCK_HEIGHT*4];
qboolean scrap_dirty;
-int scrap_texnum;
// returns a texture number and the position inside it
int Scrap_AllocBlock (int w, int h, int *x, int *y)
}
int scrap_uploads;
+int scraptexnum[MAX_SCRAPS];
void Scrap_Upload (void)
{
scrap_uploads++;
for (texnum=0 ; texnum<MAX_SCRAPS ; texnum++)
- {
- glBindTexture(GL_TEXTURE_2D, scrap_texnum + texnum);
- GL_Upload8 (scrap_texels[texnum], BLOCK_WIDTH, BLOCK_HEIGHT, false, true);
- }
+ scraptexnum[texnum] = GL_LoadTexture (va("scrapslot%d", texnum), BLOCK_WIDTH, BLOCK_HEIGHT, scrap_texels[texnum], false, true, 1);
scrap_dirty = false;
}
for (i=0 ; i<p->height ; i++)
for (j=0 ; j<p->width ; j++, k++)
scrap_texels[texnum][(y+i)*BLOCK_WIDTH + x + j] = p->data[k];
- texnum += scrap_texnum;
- gl->texnum = texnum;
+ if (!scraptexnum[texnum])
+ scraptexnum[texnum] = GL_LoadTexture (va("scrapslot%d", texnum), BLOCK_WIDTH, BLOCK_HEIGHT, scrap_texels[texnum], false, true, 1);
+ gl->texnum = scraptexnum[texnum];
gl->sl = (x+0.01)/(float)BLOCK_WIDTH;
gl->sh = (x+p->width-0.01)/(float)BLOCK_WIDTH;
gl->tl = (y+0.01)/(float)BLOCK_WIDTH;
pic_count++;
pic_texels += p->width*p->height;
- // LordHavoc: LINEAR interpolation
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
else
{
gl->sh = 1;
gl->tl = 0;
gl->th = 1;
- // LordHavoc: LINEAR interpolation
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); //NEAREST);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); //NEAREST);
}
return p;
}
return &pic->pic;
}
-
+/*
void Draw_CharToConback (int num, byte *dest)
{
int row, col;
}
}
-
-typedef struct
-{
- char *name;
- int minimize, maximize;
-} glmode_t;
-
-glmode_t modes[] = {
- {"GL_NEAREST", GL_NEAREST, GL_NEAREST},
- {"GL_LINEAR", GL_LINEAR, GL_LINEAR},
- {"GL_NEAREST_MIPMAP_NEAREST", GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST},
- {"GL_LINEAR_MIPMAP_NEAREST", GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR},
- {"GL_NEAREST_MIPMAP_LINEAR", GL_NEAREST_MIPMAP_LINEAR, GL_NEAREST},
- {"GL_LINEAR_MIPMAP_LINEAR", GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR}
-};
-
-/*
-===============
-Draw_TextureMode_f
-===============
*/
-void Draw_TextureMode_f (void)
-{
- int i;
- gltexture_t *glt;
-
- if (Cmd_Argc() == 1)
- {
- for (i=0 ; i< 6 ; i++)
- if (gl_filter_min == modes[i].minimize)
- {
- Con_Printf ("%s\n", modes[i].name);
- return;
- }
- Con_Printf ("current filter is unknown???\n");
- return;
- }
-
- for (i=0 ; i< 6 ; i++)
- {
- if (!Q_strcasecmp (modes[i].name, Cmd_Argv(1) ) )
- break;
- }
- if (i == 6)
- {
- Con_Printf ("bad filter name\n");
- return;
- }
-
- gl_filter_min = modes[i].minimize;
- gl_filter_max = modes[i].maximize;
-
- // change all the existing mipmap texture objects
- for (i=0, glt=gltextures ; i<numgltextures ; i++, glt++)
- {
- if (glt->mipmap)
- {
- glBindTexture(GL_TEXTURE_2D, glt->texnum);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
- }
- }
-}
extern void LoadSky_f(void);
*/
void rmain_registercvars();
extern int buildnumber;
-void Draw_Init (void)
+
+void gl_draw_start()
{
int i;
- qpic_t *cb;
- byte *dest;
- int x, y;
- char ver[40];
glpic_t *gl;
- int start;
-
- Cvar_RegisterVariable (&qsg_version);
- Cvar_RegisterVariable (&gl_max_size);
- Cvar_RegisterVariable (&gl_picmip);
- Cvar_RegisterVariable (&gl_conalpha);
- Cvar_RegisterVariable (&gl_lerpimages);
-
- // 3dfx can only handle 256 wide textures
- if (!Q_strncasecmp ((char *)gl_renderer, "3dfx",4) ||
- strstr((char *)gl_renderer, "Glide"))
- Cvar_Set ("gl_max_size", "256");
-
- Cmd_AddCommand ("gl_texturemode", &Draw_TextureMode_f);
-
- Cmd_AddCommand ("loadsky", &LoadSky_f);
// load the console background and the charset
// by hand, because we need to write the version
// string into the background before turning
// it into a texture
- draw_chars = W_GetLumpName ("conchars");
- for (i=0 ; i<256*64 ; i++)
- if (draw_chars[i] == 0)
- draw_chars[i] = 255; // proper transparent color
+ char_texture = loadtextureimage ("conchars", 0, 0, false, false);
+ if (!char_texture)
+ {
+ draw_chars = W_GetLumpName ("conchars");
+ for (i=0 ; i<256*64 ; i++)
+ if (draw_chars[i] == 0)
+ draw_chars[i] = 255; // proper transparent color
- // now turn them into textures
- char_texture = GL_LoadTexture ("charset", 128, 128, draw_chars, false, true, 1);
+ // now turn them into textures
+ char_texture = GL_LoadTexture ("charset", 128, 128, draw_chars, false, true, 1);
+ }
- start = Hunk_LowMark();
+ gl = (glpic_t *)conback->data;
+ gl->texnum = loadtextureimage("gfx/conback", 0, 0, false, false);
+ gl->sl = 0;
+ gl->sh = 1;
+ gl->tl = 0;
+ gl->th = 1;
+ conback->width = vid.width;
+ conback->height = vid.height;
+
+ memset(scraptexnum, 0, sizeof(scraptexnum));
+
+ // get the other pics we need
+ draw_disc = Draw_PicFromWad ("disc");
+}
- cb = (qpic_t *)COM_LoadMallocFile ("gfx/conback.lmp", false);
- if (!cb)
- Sys_Error ("Couldn't load gfx/conback.lmp");
- SwapPic (cb);
+void gl_draw_shutdown()
+{
+}
+
+char engineversion[40];
+int engineversionx, engineversiony;
+
+extern void GL_Textures_Init();
+void GL_Draw_Init (void)
+{
+ int i;
+ Cvar_RegisterVariable (&qsg_version);
+ Cvar_RegisterVariable (&gl_conalpha);
+
+ Cmd_AddCommand ("loadsky", &LoadSky_f);
- // hack the version number directly into the pic
#ifdef NEHAHRA
#if defined(__linux__)
- sprintf (ver, "DPNehahra Linux GL %.2f build %5i", (float) VERSION, buildnumber);
+ sprintf (engineversion, "DPNehahra Linux GL %.2f build %3i", (float) VERSION, buildnumber);
#elif defined(WIN32)
- sprintf (ver, "DPNehahra Windows GL %.2f build %5i", (float) VERSION, buildnumber);
+ sprintf (engineversion, "DPNehahra Windows GL %.2f build %3i", (float) VERSION, buildnumber);
#else
- sprintf (ver, "DPNehahra Unknown GL %.2f build %5i", (float) VERSION, buildnumber);
+ sprintf (engineversion, "DPNehahra Unknown GL %.2f build %3i", (float) VERSION, buildnumber);
#endif
#else
#if defined(__linux__)
- sprintf (ver, "DarkPlaces Linux GL %.2f build %5i", (float) VERSION, buildnumber);
+ sprintf (engineversion, "DarkPlaces Linux GL %.2f build %3i", (float) VERSION, buildnumber);
#elif defined(WIN32)
- sprintf (ver, "DarkPlaces Windows GL %.2f build %5i", (float) VERSION, buildnumber);
+ sprintf (engineversion, "DarkPlaces Windows GL %.2f build %3i", (float) VERSION, buildnumber);
#else
- sprintf (ver, "DarkPlaces Unknown GL %.2f build %5i", (float) VERSION, buildnumber);
+ sprintf (engineversion, "DarkPlaces Unknown GL %.2f build %3i", (float) VERSION, buildnumber);
#endif
#endif
- dest = cb->data + 320*186 + 320 - 11 - 8*strlen(ver);
- y = strlen(ver);
- for (x=0 ; x<y ; x++)
- Draw_CharToConback (ver[x], dest+(x<<3));
-
- gl = (glpic_t *)conback->data;
- gl->texnum = GL_LoadTexture ("conback", cb->width, cb->height, cb->data, false, false, 1);
- gl->sl = 0;
- gl->sh = 1;
- gl->tl = 0;
- gl->th = 1;
- conback->width = vid.width;
- conback->height = vid.height;
-
- // free loaded console
- free(cb);
-
- // save a texture slot for translated picture
- translate_texture = texture_extension_number++;
+ for (i = 0;i < 40 && engineversion[i];i++)
+ engineversion[i] += 0x80; // shift to orange
+ engineversionx = vid.width - strlen(engineversion) * 8 - 8;
+ engineversiony = vid.height - 8;
- // save slots for scraps
- scrap_texnum = texture_extension_number;
- texture_extension_number += MAX_SCRAPS;
-
- //
- // get the other pics we need
- //
- draw_disc = Draw_PicFromWad ("disc");
-
- rmain_registercvars();
+ GL_Textures_Init();
+ R_RegisterModule("GL_Draw", gl_draw_start, gl_draw_shutdown);
}
-
/*
================
Draw_Character
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
+void Draw_GenericPic (int texnum, float red, float green, float blue, float alpha, float x, float y, float width, float height)
+{
+ glDisable(GL_ALPHA_TEST);
+// glEnable (GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+// glCullFace(GL_FRONT);
+ glColor4f(red,green,blue,alpha);
+ glBindTexture(GL_TEXTURE_2D, texnum);
+ glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+ glBegin (GL_QUADS);
+ glTexCoord2f (0, 0);
+ glVertex2f (x, y);
+ glTexCoord2f (1, 0);
+ glVertex2f (x+width, y);
+ glTexCoord2f (1, 1);
+ glVertex2f (x+width, y+height);
+ glTexCoord2f (0, 1);
+ glVertex2f (x, y+height);
+ glEnd ();
+ glColor3f(1,1,1);
+// glEnable(GL_ALPHA_TEST);
+// glDisable (GL_BLEND);
+}
+
/*
=============
Draw_AlphaPic
byte *src;
int p;
- glBindTexture(GL_TEXTURE_2D, translate_texture);
-
c = pic->width * pic->height;
dest = trans;
}
}
- glTexImage2D (GL_TEXTURE_2D, 0, 4, 64, 64, 0, GL_RGBA, GL_UNSIGNED_BYTE, trans);
-
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glBindTexture(GL_TEXTURE_2D, GL_LoadTexture ("translatedplayerpic", 64, 64, (void *) trans, false, true, 1));
glColor3f(0.8,0.8,0.8);
glBegin (GL_QUADS);
else
Draw_AlphaPic (0, lines - vid.height, conback, gl_conalpha.value*lines/vid.height);
// Draw_AlphaPic (0, lines - vid.height, conback, (float)(1.2 * lines)/y);
+ // LordHavoc: draw version
+ Draw_String(engineversionx, lines - vid.height + engineversiony, engineversion, 9999);
}
/*
for (i = 0;i < SHOWLMP_MAXLABELS;i++)
showlmp[i].isactive = false;
}
-
-//====================================================================
-
-/*
-================
-GL_FindTexture
-================
-*/
-int GL_FindTexture (char *identifier)
-{
- int i;
- gltexture_t *glt;
-
- for (i=0, glt=gltextures ; i<numgltextures ; i++, glt++)
- {
- if (!strcmp (identifier, glt->identifier))
- return gltextures[i].texnum;
- }
-
- return -1;
-}
-
-extern byte qgamma[];
-
-// LordHavoc: gamma correction and improved resampling
-void GL_ResampleTextureLerpLine (byte *in, byte *out, int inwidth, int outwidth)
-{
- int j, xi, oldx = 0;
- float f, fstep, l1, l2;
- fstep = (float) inwidth/outwidth;
- for (j = 0,f = 0;j < outwidth;j++, f += fstep)
- {
- xi = (int) f;
- if (xi != oldx)
- {
- in += (xi - oldx) * 4;
- oldx = xi;
- }
- if (xi < (inwidth-1))
- {
- l2 = f - xi;
- l1 = 1 - l2;
- *out++ = qgamma[(byte) (in[0] * l1 + in[4] * l2)];
- *out++ = qgamma[(byte) (in[1] * l1 + in[5] * l2)];
- *out++ = qgamma[(byte) (in[2] * l1 + in[6] * l2)];
- *out++ = (byte) (in[3] * l1 + in[7] * l2) ;
- }
- else // last pixel of the line has no pixel to lerp to
- {
- *out++ = qgamma[in[0]];
- *out++ = qgamma[in[1]];
- *out++ = qgamma[in[2]];
- *out++ = in[3] ;
- }
- }
-}
-
-/*
-================
-GL_ResampleTexture
-================
-*/
-void GL_ResampleTexture (void *indata, int inwidth, int inheight, void *outdata, int outwidth, int outheight)
-{
- // LordHavoc: gamma correction and greatly improved resampling
- if (gl_lerpimages.value)
- {
- int i, j, yi, oldy;
- byte *inrow, *out, *row1, *row2;
- float f, fstep, l1, l2;
- out = outdata;
- fstep = (float) inheight/outheight;
-
- row1 = malloc(outwidth*4);
- row2 = malloc(outwidth*4);
- inrow = indata;
- oldy = 0;
- GL_ResampleTextureLerpLine (inrow, row1, inwidth, outwidth);
- GL_ResampleTextureLerpLine (inrow + inwidth*4, row2, inwidth, outwidth);
- for (i = 0, f = 0;i < outheight;i++,f += fstep)
- {
- yi = (int) f;
- if (yi != oldy)
- {
- inrow = (byte *)((int)indata + inwidth*4*yi);
- if (yi == oldy+1)
- memcpy(row1, row2, outwidth*4);
- else
- GL_ResampleTextureLerpLine (inrow, row1, inwidth, outwidth);
- if (yi < (inheight-1))
- GL_ResampleTextureLerpLine (inrow + inwidth*4, row2, inwidth, outwidth);
- else
- memcpy(row2, row1, outwidth*4);
- oldy = yi;
- }
- if (yi < (inheight-1))
- {
- l2 = f - yi;
- l1 = 1 - l2;
- for (j = 0;j < outwidth;j++)
- {
- *out++ = (byte) (*row1++ * l1 + *row2++ * l2);
- *out++ = (byte) (*row1++ * l1 + *row2++ * l2);
- *out++ = (byte) (*row1++ * l1 + *row2++ * l2);
- *out++ = (byte) (*row1++ * l1 + *row2++ * l2);
- }
- row1 -= outwidth*4;
- row2 -= outwidth*4;
- }
- else // last line has no pixels to lerp to
- {
- for (j = 0;j < outwidth;j++)
- {
- *out++ = *row1++;
- *out++ = *row1++;
- *out++ = *row1++;
- *out++ = *row1++;
- }
- row1 -= outwidth*4;
- }
- }
- free(row1);
- free(row2);
- }
- else
- {
- int i, j;
- unsigned frac, fracstep;
- byte *inrow, *out, *inpix;
- out = outdata;
-
- fracstep = inwidth*0x10000/outwidth;
- for (i=0 ; i<outheight ; i++)
- {
- inrow = (byte *)indata + inwidth*(i*inheight/outheight)*4;
- frac = fracstep >> 1;
- for (j=0 ; j<outwidth ; j+=4)
- {
- inpix = inrow + ((frac >> 14) & ~3);*out++ = qgamma[*inpix++];*out++ = qgamma[*inpix++];*out++ = qgamma[*inpix++];*out++ = *inpix++ ;frac += fracstep;
- inpix = inrow + ((frac >> 14) & ~3);*out++ = qgamma[*inpix++];*out++ = qgamma[*inpix++];*out++ = qgamma[*inpix++];*out++ = *inpix++ ;frac += fracstep;
- inpix = inrow + ((frac >> 14) & ~3);*out++ = qgamma[*inpix++];*out++ = qgamma[*inpix++];*out++ = qgamma[*inpix++];*out++ = *inpix++ ;frac += fracstep;
- inpix = inrow + ((frac >> 14) & ~3);*out++ = qgamma[*inpix++];*out++ = qgamma[*inpix++];*out++ = qgamma[*inpix++];*out++ = *inpix++ ;frac += fracstep;
- }
- }
- }
-}
-
-/*
-================
-GL_Resample8BitTexture -- JACK
-================
-*/
-void GL_Resample8BitTexture (unsigned char *in, int inwidth, int inheight, unsigned char *out, int outwidth, int outheight)
-{
- int i, j;
- unsigned char *inrow;
- unsigned frac, fracstep;
-
- fracstep = inwidth*0x10000/outwidth;
- for (i=0 ; i<outheight ; i++, out += outwidth)
- {
- inrow = in + inwidth*(i*inheight/outheight);
- frac = fracstep >> 1;
- for (j=0 ; j<outwidth ; j+=4)
- {
- out[j] = inrow[frac>>16];
- frac += fracstep;
- out[j+1] = inrow[frac>>16];
- frac += fracstep;
- out[j+2] = inrow[frac>>16];
- frac += fracstep;
- out[j+3] = inrow[frac>>16];
- frac += fracstep;
- }
- }
-}
-
-
-/*
-================
-GL_MipMap
-
-Operates in place, quartering the size of the texture
-================
-*/
-void GL_MipMap (byte *in, int width, int height)
-{
- int i, j;
- byte *out;
-
- width <<=2;
- height >>= 1;
- out = in;
- for (i=0 ; i<height ; i++, in+=width)
- {
- for (j=0 ; j<width ; j+=8, out+=4, in+=8)
- {
- out[0] = (in[0] + in[4] + in[width+0] + in[width+4])>>2;
- out[1] = (in[1] + in[5] + in[width+1] + in[width+5])>>2;
- out[2] = (in[2] + in[6] + in[width+2] + in[width+6])>>2;
- out[3] = (in[3] + in[7] + in[width+3] + in[width+7])>>2;
- }
- }
-}
-
-/*
-================
-GL_MipMap8Bit
-
-Mipping for 8 bit textures
-================
-*/
-void GL_MipMap8Bit (byte *in, int width, int height)
-{
- int i, j;
- unsigned short r,g,b;
- byte *out, *at1, *at2, *at3, *at4;
-
- height >>= 1;
- out = in;
- for (i=0 ; i<height ; i++, in+=width)
- {
- for (j=0 ; j<width ; j+=2, out+=1, in+=2)
- {
- at1 = (byte *) (d_8to24table + in[0]);
- at2 = (byte *) (d_8to24table + in[1]);
- at3 = (byte *) (d_8to24table + in[width+0]);
- at4 = (byte *) (d_8to24table + in[width+1]);
-
- r = (at1[0]+at2[0]+at3[0]+at4[0]); r>>=5;
- g = (at1[1]+at2[1]+at3[1]+at4[1]); g>>=5;
- b = (at1[2]+at2[2]+at3[2]+at4[2]); b>>=5;
-
- out[0] = d_15to8table[(r<<0) + (g<<5) + (b<<10)];
- }
- }
-}
-
-/*
-===============
-GL_Upload32
-===============
-*/
-void GL_Upload32 (void *data, int width, int height, qboolean mipmap, qboolean alpha)
-{
- int samples, scaled_width, scaled_height, i;
- byte *in, *out, *scaled;
-
- for (scaled_width = 1 ; scaled_width < width ; scaled_width<<=1)
- ;
- for (scaled_height = 1 ; scaled_height < height ; scaled_height<<=1)
- ;
-
- scaled_width >>= (int)gl_picmip.value;
- scaled_height >>= (int)gl_picmip.value;
-
- if (scaled_width > gl_max_size.value)
- scaled_width = gl_max_size.value;
- if (scaled_height > gl_max_size.value)
- scaled_height = gl_max_size.value;
-
- if (alpha)
- {
- alpha = false;
- in = data;
- for (i = 3;i < width*height*4;i += 4)
- if (in[i] != 255)
- {
- alpha = true;
- break;
- }
- }
-
- samples = alpha ? gl_alpha_format : gl_solid_format;
-
-#if 0
- if (mipmap)
- gluBuild2DMipmaps (GL_TEXTURE_2D, samples, width, height, GL_RGBA, GL_UNSIGNED_BYTE, scaled);
- else if (scaled_width == width && scaled_height == height)
- glTexImage2D (GL_TEXTURE_2D, 0, samples, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaled);
- else
- {
- gluScaleImage (GL_RGBA, width, height, GL_UNSIGNED_BYTE, scaled, scaled_width, scaled_height, GL_UNSIGNED_BYTE, scaled);
- glTexImage2D (GL_TEXTURE_2D, 0, samples, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaled);
- }
-#else
-texels += scaled_width * scaled_height;
-
- scaled = malloc(scaled_width*scaled_height*4);
- if (scaled_width == width && scaled_height == height)
- {
- // LordHavoc: gamma correct while copying
- in = (byte *)data;
- out = (byte *)scaled;
- for (i = 0;i < width*height;i++)
- {
- *out++ = qgamma[*in++];
- *out++ = qgamma[*in++];
- *out++ = qgamma[*in++];
- *out++ = *in++;
- }
- }
- else
- GL_ResampleTexture (data, width, height, scaled, scaled_width, scaled_height);
-
- glTexImage2D (GL_TEXTURE_2D, 0, samples, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaled);
- if (mipmap)
- {
- int miplevel;
-
- miplevel = 0;
- while (scaled_width > 1 || scaled_height > 1)
- {
- GL_MipMap ((byte *)scaled, scaled_width, scaled_height);
- scaled_width >>= 1;
- scaled_height >>= 1;
- if (scaled_width < 1)
- scaled_width = 1;
- if (scaled_height < 1)
- scaled_height = 1;
- miplevel++;
- glTexImage2D (GL_TEXTURE_2D, miplevel, samples, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaled);
- }
- }
-#endif
-
-
- if (mipmap)
- {
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
- }
- else
- {
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_max);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
- }
- free(scaled);
-}
-
-void GL_Upload8_EXT (byte *data, int width, int height, qboolean mipmap)
-{
- int scaled_width, scaled_height;
- byte *scaled = NULL;
-
- for (scaled_width = 1 ; scaled_width < width ; scaled_width<<=1)
- ;
- for (scaled_height = 1 ; scaled_height < height ; scaled_height<<=1)
- ;
-
- scaled_width >>= (int)gl_picmip.value;
- scaled_height >>= (int)gl_picmip.value;
-
- if (scaled_width > gl_max_size.value)
- scaled_width = gl_max_size.value;
- if (scaled_height > gl_max_size.value)
- scaled_height = gl_max_size.value;
-
- texels += scaled_width * scaled_height;
-
- if (scaled_width == width && scaled_height == height)
- {
- if (!mipmap)
- {
- glTexImage2D (GL_TEXTURE_2D, 0, GL_COLOR_INDEX8_EXT, scaled_width, scaled_height, 0, GL_COLOR_INDEX , GL_UNSIGNED_BYTE, data);
- goto done;
- }
- scaled = malloc(scaled_width*scaled_height*4);
- memcpy (scaled, data, width*height);
- }
- else
- {
- scaled = malloc(scaled_width*scaled_height*4);
- GL_Resample8BitTexture (data, width, height, (void*) scaled, scaled_width, scaled_height);
- }
-
- glTexImage2D (GL_TEXTURE_2D, 0, GL_COLOR_INDEX8_EXT, scaled_width, scaled_height, 0, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, scaled);
- if (mipmap)
- {
- int miplevel;
-
- miplevel = 0;
- while (scaled_width > 1 || scaled_height > 1)
- {
- GL_MipMap8Bit ((byte *)scaled, scaled_width, scaled_height);
- scaled_width >>= 1;
- scaled_height >>= 1;
- if (scaled_width < 1)
- scaled_width = 1;
- if (scaled_height < 1)
- scaled_height = 1;
- miplevel++;
- glTexImage2D (GL_TEXTURE_2D, miplevel, GL_COLOR_INDEX8_EXT, scaled_width, scaled_height, 0, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, scaled);
- }
- }
-done: ;
-
-
- if (mipmap)
- {
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
- }
- else
- {
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_max);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
- }
- free(scaled);
-}
-
-qboolean VID_Is8bit();
-
-/*
-===============
-GL_Upload8
-===============
-*/
-void GL_Upload8 (byte *data, int width, int height, qboolean mipmap, qboolean alpha)
-{
- static unsigned *trans;
- int i, s;
- qboolean noalpha;
- int p;
- byte *indata;
- int *outdata;
-
- s = width*height;
- trans = malloc(s*4);
- // if there are no transparent pixels, make it a 3 component
- // texture even if it was specified as otherwise
- if (alpha)
- {
- noalpha = true;
- for (i=0 ; i<s ; i++)
- {
- p = data[i];
- if (p != 255)
- trans[i] = d_8to24table[p];
- else
- {
- trans[i] = 0; // force to black
- noalpha = false;
- }
- }
-
- if (noalpha)
- {
- if (VID_Is8bit() && (data!=scrap_texels[0]))
- {
- GL_Upload8_EXT (data, width, height, mipmap);
- free(trans);
- return;
- }
- alpha = false;
- }
- }
- else
- {
- // LordHavoc: dodge the copy if it will be uploaded as 8bit
- if (VID_Is8bit() && (data!=scrap_texels[0]))
- {
- GL_Upload8_EXT (data, width, height, mipmap);
- free(trans);
- return;
- }
- //if (s&3)
- // Sys_Error ("GL_Upload8: s&3");
- indata = data;
- outdata = trans;
- if (s&1)
- *outdata++ = d_8to24table[*indata++];
- if (s&2)
- {
- *outdata++ = d_8to24table[*indata++];
- *outdata++ = d_8to24table[*indata++];
- }
- for (i = 0;i < s;i+=4)
- {
- *outdata++ = d_8to24table[*indata++];
- *outdata++ = d_8to24table[*indata++];
- *outdata++ = d_8to24table[*indata++];
- *outdata++ = d_8to24table[*indata++];
- }
- }
-
- GL_Upload32 (trans, width, height, mipmap, alpha);
- free(trans);
-}
-
-/*
-================
-GL_LoadTexture
-================
-*/
-int GL_LoadTexture (char *identifier, int width, int height, byte *data, qboolean mipmap, qboolean alpha, int bytesperpixel)
-{
- unsigned short crc;
- int i;
- gltexture_t *glt;
-
- if (isDedicated)
- return 1;
-
- // LordHavoc: do a CRC to confirm the data really is the same as previous occurances.
- crc = CRC_Block(data, width*height*bytesperpixel);
- // see if the texture is already present
- if (identifier[0])
- {
- for (i=0, glt=gltextures ; i<numgltextures ; i++, glt++)
- {
- if (!strcmp (identifier, glt->identifier))
- {
- // LordHavoc: everyone hates cache mismatchs, so I fixed it
- if (crc != glt->crc || width != glt->width || height != glt->height)
- {
- Con_DPrintf("GL_LoadTexture: cache mismatch, replacing old texture\n");
- goto GL_LoadTexture_setup; // drop out with glt pointing to the texture to replace
- //Sys_Error ("GL_LoadTexture: cache mismatch");
- }
- if ((gl_lerpimages.value != 0) != glt->lerped)
- goto GL_LoadTexture_setup; // drop out with glt pointing to the texture to replace
- return glt->texnum;
- }
- }
- }
- // LordHavoc: although this could be an else condition as it was in the original id code,
- // it is more clear this way
- // LordHavoc: check if there are still slots available
- if (numgltextures >= MAX_GLTEXTURES)
- Sys_Error ("GL_LoadTexture: ran out of texture slots (%d)\n", MAX_GLTEXTURES);
- glt = &gltextures[numgltextures++];
-
- strcpy (glt->identifier, identifier);
- glt->texnum = texture_extension_number;
- texture_extension_number++;
-// LordHavoc: label to drop out of the loop into the setup code
-GL_LoadTexture_setup:
- glt->crc = crc; // LordHavoc: used to verify textures are identical
- glt->width = width;
- glt->height = height;
- glt->mipmap = mipmap;
- glt->bytesperpixel = bytesperpixel;
- glt->lerped = gl_lerpimages.value != 0;
-
- glBindTexture(GL_TEXTURE_2D, glt->texnum);
-
- if (bytesperpixel == 1) // 8bit
- GL_Upload8 (data, width, height, mipmap, alpha);
- else // 32bit
- GL_Upload32 (data, width, height, mipmap, true);
- glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
-
- return glt->texnum;
-}
-
-/*
-================
-GL_LoadPicTexture
-================
-*/
-int GL_LoadPicTexture (qpic_t *pic)
-{
- return GL_LoadTexture ("", pic->width, pic->height, pic->data, false, true, 1);
-}
-
-int GL_GetTextureSlots (int count)
-{
- gltexture_t *glt, *first;
-
- first = glt = &gltextures[numgltextures];
- while (count--)
- {
- glt->identifier[0] = 0;
- glt->texnum = texture_extension_number++;
- glt->crc = 0;
- glt->width = 0;
- glt->height = 0;
- glt->bytesperpixel = 0;
- glt++;
- numgltextures++;
- }
- return first->texnum;
-}
--- /dev/null
+
+#include "quakedef.h"
+
+// LordHavoc: vertex array
+float *aliasvert;
+float *aliasvertnorm;
+byte *aliasvertcolor;
+byte *aliasvertcolor2;
+
+int chrometexture;
+
+void makechrometexture()
+{
+ int i;
+ byte noise[64*64];
+ byte data[64*64][4];
+
+ fractalnoise(noise, 64);
+
+ // convert to RGBA data
+ for (i = 0;i < 64*64;i++)
+ {
+ data[i][0] = data[i][1] = data[i][2] = noise[i];
+ data[i][3] = 255;
+ }
+
+ chrometexture = GL_LoadTexture ("chrometexture", 64, 64, &data[0][0], true, false, 4);
+}
+
+void gl_models_start()
+{
+ // allocate vertex processing arrays
+ aliasvert = malloc(sizeof(float[MD2MAX_VERTS][3]));
+ aliasvertnorm = malloc(sizeof(float[MD2MAX_VERTS][3]));
+ aliasvertcolor = malloc(sizeof(byte[MD2MAX_VERTS][4]));
+ aliasvertcolor2 = malloc(sizeof(byte[MD2MAX_VERTS][4])); // used temporarily for tinted coloring
+ makechrometexture();
+}
+
+void gl_models_shutdown()
+{
+ free(aliasvert);
+ free(aliasvertnorm);
+ free(aliasvertcolor);
+ free(aliasvertcolor2);
+}
+
+void GL_Models_Init()
+{
+ R_RegisterModule("GL_Models", gl_models_start, gl_models_shutdown);
+}
+
+extern vec3_t softwaretransform_x;
+extern vec3_t softwaretransform_y;
+extern vec3_t softwaretransform_z;
+extern vec_t softwaretransform_scale;
+extern vec3_t softwaretransform_offset;
+void R_AliasLerpVerts(int vertcount, float lerp, trivert2 *verts1, vec3_t scale1, vec3_t translate1, trivert2 *verts2, vec3_t scale2, vec3_t translate2)
+{
+ int i;
+ vec3_t point, matrix_x, matrix_y, matrix_z;
+ float *av, *avn;
+ av = aliasvert;
+ avn = aliasvertnorm;
+ VectorScale(softwaretransform_x, softwaretransform_scale, matrix_x);
+ VectorScale(softwaretransform_y, softwaretransform_scale, matrix_y);
+ VectorScale(softwaretransform_z, softwaretransform_scale, matrix_z);
+ if (lerp < 0) lerp = 0;
+ if (lerp > 1) lerp = 1;
+ if (lerp != 0)
+ {
+ float ilerp, ilerp127, lerp127, scalex1, scalex2, translatex, scaley1, scaley2, translatey, scalez1, scalez2, translatez;
+ if (lerp < 0) lerp = 0;
+ if (lerp > 1) lerp = 1;
+ ilerp = 1 - lerp;
+ ilerp127 = ilerp * (1.0 / 127.0);
+ lerp127 = lerp * (1.0 / 127.0);
+ // calculate combined interpolation variables
+ scalex1 = scale1[0] * ilerp;scalex2 = scale2[0] * lerp;translatex = translate1[0] * ilerp + translate2[0] * lerp;
+ scaley1 = scale1[1] * ilerp;scaley2 = scale2[1] * lerp;translatey = translate1[1] * ilerp + translate2[1] * lerp;
+ scalez1 = scale1[2] * ilerp;scalez2 = scale2[2] * lerp;translatez = translate1[2] * ilerp + translate2[2] * lerp;
+ // generate vertices
+ for (i = 0;i < vertcount;i++)
+ {
+ // rotate, scale, and translate the vertex locations
+ point[0] = verts1->v[0] * scalex1 + verts2->v[0] * scalex2 + translatex;
+ point[1] = verts1->v[1] * scaley1 + verts2->v[1] * scaley2 + translatey;
+ point[2] = verts1->v[2] * scalez1 + verts2->v[2] * scalez2 + translatez;
+ *av++ = point[0] * matrix_x[0] + point[1] * matrix_y[0] + point[2] * matrix_z[0] + softwaretransform_offset[0];
+ *av++ = point[0] * matrix_x[1] + point[1] * matrix_y[1] + point[2] * matrix_z[1] + softwaretransform_offset[1];
+ *av++ = point[0] * matrix_x[2] + point[1] * matrix_y[2] + point[2] * matrix_z[2] + softwaretransform_offset[2];
+ // rotate the normals
+ point[0] = verts1->n[0] * ilerp127 + verts2->n[0] * lerp127;
+ point[1] = verts1->n[1] * ilerp127 + verts2->n[1] * lerp127;
+ point[2] = verts1->n[2] * ilerp127 + verts2->n[2] * lerp127;
+ *avn++ = point[0] * softwaretransform_x[0] + point[1] * softwaretransform_y[0] + point[2] * softwaretransform_z[0];
+ *avn++ = point[0] * softwaretransform_x[1] + point[1] * softwaretransform_y[1] + point[2] * softwaretransform_z[1];
+ *avn++ = point[0] * softwaretransform_x[2] + point[1] * softwaretransform_y[2] + point[2] * softwaretransform_z[2];
+ verts1++;verts2++;
+ }
+ }
+ else
+ {
+ // generate vertices
+ for (i = 0;i < vertcount;i++)
+ {
+ // rotate, scale, and translate the vertex locations
+ point[0] = verts1->v[0] * scale1[0] + translate1[0];
+ point[1] = verts1->v[1] * scale1[1] + translate1[1];
+ point[2] = verts1->v[2] * scale1[2] + translate1[2];
+ *av++ = point[0] * matrix_x[0] + point[1] * matrix_y[0] + point[2] * matrix_z[0] + softwaretransform_offset[0];
+ *av++ = point[0] * matrix_x[1] + point[1] * matrix_y[1] + point[2] * matrix_z[1] + softwaretransform_offset[1];
+ *av++ = point[0] * matrix_x[2] + point[1] * matrix_y[2] + point[2] * matrix_z[2] + softwaretransform_offset[2];
+ // rotate the normals
+ point[0] = verts1->n[0] * (1.0f / 127.0f);
+ point[1] = verts1->n[1] * (1.0f / 127.0f);
+ point[2] = verts1->n[2] * (1.0f / 127.0f);
+ *avn++ = point[0] * softwaretransform_x[0] + point[1] * softwaretransform_y[0] + point[2] * softwaretransform_z[0];
+ *avn++ = point[0] * softwaretransform_x[1] + point[1] * softwaretransform_y[1] + point[2] * softwaretransform_z[1];
+ *avn++ = point[0] * softwaretransform_x[2] + point[1] * softwaretransform_y[2] + point[2] * softwaretransform_z[2];
+ verts1++;
+ }
+ }
+}
+
+float R_CalcAnimLerp(entity_t *ent, int pose, float lerpscale)
+{
+ if (ent->draw_lastmodel == ent->model && ent->draw_lerpstart <= cl.time)
+ {
+ if (pose != ent->draw_pose)
+ {
+ ent->draw_lastpose = ent->draw_pose;
+ ent->draw_pose = pose;
+ ent->draw_lerpstart = cl.time;
+ return 0;
+ }
+ else
+ return ((cl.time - ent->draw_lerpstart) * lerpscale);
+ }
+ else // uninitialized
+ {
+ ent->draw_lastmodel = ent->model;
+ ent->draw_lastpose = ent->draw_pose = pose;
+ ent->draw_lerpstart = cl.time;
+ return 0;
+ }
+}
+
+extern cvar_t gl_vertexarrays;
+extern qboolean lighthalf;
+void GL_DrawModelMesh(int skin, byte *colors, maliashdr_t *maliashdr)
+{
+ int i;
+ glBindTexture(GL_TEXTURE_2D, skin);
+ if (!colors)
+ {
+ if (lighthalf)
+ glColor3f(0.5f, 0.5f, 0.5f);
+ else
+ glColor3f(1.0f, 1.0f, 1.0f);
+ }
+ if (gl_vertexarrays.value)
+ {
+// qglVertexPointer(3, GL_FLOAT, 0, aliasvert);
+// glEnableClientState(GL_VERTEX_ARRAY);
+ if (colors)
+ {
+ qglColorPointer(4, GL_UNSIGNED_BYTE, 0, colors);
+ glEnableClientState(GL_COLOR_ARRAY);
+ }
+
+ qglTexCoordPointer(2, GL_FLOAT, 0, (void *)((int) maliashdr->texdata + (int) maliashdr));
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+
+ qglDrawElements(GL_TRIANGLES, maliashdr->numtris * 3, GL_UNSIGNED_SHORT, (void *)((int) maliashdr + maliashdr->tridata));
+
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ /*
+ // draw the front faces
+ qglTexCoordPointer(2, GL_FLOAT, 0, (void *)((int) paliashdr->texcoords + (int) paliashdr));
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ qglDrawElements(GL_TRIANGLES, paliashdr->frontfaces * 3, GL_UNSIGNED_SHORT, (void *)((int) paliashdr->vertindices + (int) paliashdr));
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+
+ // draw the back faces
+ qglTexCoordPointer(2, GL_FLOAT, 0, (void *)((int) paliashdr->texcoords + sizeof(float[2]) * paliashdr->numverts + (int) paliashdr));
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ qglDrawElements(GL_TRIANGLES, paliashdr->backfaces * 3, GL_UNSIGNED_SHORT, (void *)((int) paliashdr->vertindices + sizeof(unsigned short[3]) * paliashdr->frontfaces + (int) paliashdr));
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ */
+
+ if (colors)
+ glDisableClientState(GL_COLOR_ARRAY);
+// glDisableClientState(GL_VERTEX_ARRAY);
+ }
+ else
+ {
+ unsigned short *in, index;
+ float *tex;
+ in = (void *)((int) maliashdr + maliashdr->tridata);
+ glBegin(GL_TRIANGLES);
+ tex = (void *)((int) maliashdr + maliashdr->texdata);
+ for (i = 0;i < maliashdr->numtris * 3;i++)
+ {
+ index = *in++;
+ glTexCoord2f(tex[index*2], tex[index*2+1]);
+ if (colors)
+ glColor4f(colors[index*4] * (1.0f / 255.0f), colors[index*4+1] * (1.0f / 255.0f), colors[index*4+2] * (1.0f / 255.0f), colors[index*4+3] * (1.0f / 255.0f));
+ glVertex3fv(&aliasvert[index*3]);
+ }
+ glEnd();
+ /*
+ in = (void *)((int) paliashdr->vertindices + (int) paliashdr);
+ glBegin(GL_TRIANGLES);
+ // draw the front faces
+ tex = (void *)((int) paliashdr->texcoords + (int) paliashdr);
+ //if (isG200)
+ //{
+ for (i = 0;i < paliashdr->frontfaces * 3;i++)
+ {
+ index = *in++;
+ glTexCoord2f(tex[index*2], tex[index*2+1]);
+ if (colors)
+ glColor4f(colors[index*4] * (1.0f / 255.0f), colors[index*4+1] * (1.0f / 255.0f), colors[index*4+2] * (1.0f / 255.0f), colors[index*4+3] * (1.0f / 255.0f));
+ glVertex3fv(&aliasvert[index*3]);
+ }
+ */
+ /*
+ }
+ else
+ {
+ for (i = 0;i < paliashdr->frontfaces * 3;i++)
+ {
+ index = *in++;
+ glTexCoord2f(tex[index*2], tex[index*2+1]);
+ glColor4ub(colors[index*4], colors[index*4+1], colors[index*4+2], colors[index*4+3]);
+ glVertex3fv(&aliasvert[index*3]);
+ }
+ }
+ */
+ /*
+ // draw the back faces
+ tex += 2 * paliashdr->numverts;
+ //if (isG200)
+ //{
+ for (i = 0;i < paliashdr->backfaces * 3;i++)
+ {
+ index = *in++;
+ glTexCoord2f(tex[index*2], tex[index*2+1]);
+ if (colors)
+ glColor4f(colors[index*4] * (1.0f / 255.0f), colors[index*4+1] * (1.0f / 255.0f), colors[index*4+2] * (1.0f / 255.0f), colors[index*4+3] * (1.0f / 255.0f));
+ glVertex3fv(&aliasvert[index*3]);
+ }
+ */
+ /*
+ }
+ else
+ {
+ for (i = 0;i < paliashdr->backfaces * 3;i++)
+ {
+ index = *in++;
+ glTexCoord2f(tex[index*2], tex[index*2+1]);
+ glColor4ub(colors[index*4], colors[index*4+1], colors[index*4+2], colors[index*4+3]);
+ glVertex3fv(&aliasvert[index*3]);
+ }
+ }
+ */
+ /*
+ glEnd();
+ */
+ }
+ // leave it in a state for additional passes
+ glDepthMask(0);
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE); // additive
+}
+
+void R_TintModel(byte *in, byte *out, int verts, byte *color)
+{
+ int i;
+ byte r = color[0];
+ byte g = color[1];
+ byte b = color[2];
+ for (i = 0;i < verts;i++)
+ {
+ out[0] = (byte) ((in[0] * r) >> 8);
+ out[1] = (byte) ((in[1] * g) >> 8);
+ out[2] = (byte) ((in[2] * b) >> 8);
+ out[3] = in[3];
+ in += 4;
+ out += 4;
+ }
+}
+
+/*
+=================
+R_DrawAliasFrame
+
+=================
+*/
+extern vec3_t lightspot;
+void R_LightModel(int numverts, vec3_t center, vec3_t basecolor);
+void R_DrawAliasFrame (maliashdr_t *maliashdr, float alpha, vec3_t color, entity_t *ent, int shadow, vec3_t org, int frame, int *skin, int colormap, int effects, int flags)
+{
+ int i, pose;
+ float lerpscale, lerp;
+ maliasframe_t *frameinfo;
+
+ softwaretransformforentity(ent);
+
+ if ((frame >= maliashdr->numframes) || (frame < 0))
+ {
+ Con_DPrintf ("R_AliasSetupFrame: no such frame %d\n", frame);
+ frame = 0;
+ }
+
+ frameinfo = ((maliasframe_t *)((int) maliashdr + maliashdr->framedata)) + frame;
+ pose = frameinfo->start;
+
+ if (frameinfo->length > 1)
+ {
+ lerpscale = frameinfo->rate;
+ pose += (int)(cl.time * frameinfo->rate) % frameinfo->length;
+ }
+ else
+ lerpscale = 10.0f;
+
+ lerp = R_CalcAnimLerp(ent, pose, lerpscale);
+
+ R_AliasLerpVerts(maliashdr->numverts, lerp, (trivert2 *)((int) maliashdr + maliashdr->posedata) + ent->draw_lastpose * maliashdr->numverts, maliashdr->scale, maliashdr->scale_origin, (trivert2 *)((int) maliashdr + maliashdr->posedata) + ent->draw_pose * maliashdr->numverts, maliashdr->scale, maliashdr->scale_origin);
+
+ // prep the vertex array as early as possible
+ if (gl_vertexarrays.value)
+ {
+ qglVertexPointer(3, GL_FLOAT, 0, aliasvert);
+ glEnableClientState(GL_VERTEX_ARRAY);
+ }
+
+ R_LightModel(maliashdr->numverts, org, color);
+
+ glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+ glShadeModel(GL_SMOOTH);
+ if (effects & EF_ADDITIVE)
+ {
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE); // additive rendering
+ glEnable(GL_BLEND);
+ glDepthMask(0);
+ }
+ else if (alpha != 1.0)
+ {
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glEnable(GL_BLEND);
+ glDepthMask(0);
+ }
+ else
+ {
+ glDisable(GL_BLEND);
+ glDepthMask(1);
+ }
+
+ if (colormap >= 0)
+ {
+ if (!skin[0] && !skin[1] && !skin[2] && !skin[3])
+ GL_DrawModelMesh(0, NULL, maliashdr);
+ else
+ {
+ int c;
+ if (skin[0])
+ GL_DrawModelMesh(skin[0], aliasvertcolor, maliashdr);
+ if (skin[1])
+ {
+ c = (colormap & 0xF) << 4;c += (c >= 128 && c < 224) ? 4 : 12; // 128-224 are backwards ranges
+ R_TintModel(aliasvertcolor, aliasvertcolor2, maliashdr->numverts, (byte *) (&d_8to24table[c]));
+ GL_DrawModelMesh(skin[1], aliasvertcolor2, maliashdr);
+ }
+ if (skin[2])
+ {
+ c = colormap & 0xF0 ;c += (c >= 128 && c < 224) ? 4 : 12; // 128-224 are backwards ranges
+ R_TintModel(aliasvertcolor, aliasvertcolor2, maliashdr->numverts, (byte *) (&d_8to24table[c]));
+ GL_DrawModelMesh(skin[2], aliasvertcolor2, maliashdr);
+ }
+ if (skin[3]) GL_DrawModelMesh(skin[3], NULL, maliashdr);
+ }
+ }
+ else
+ {
+ if (!skin[3] && !skin[4])
+ GL_DrawModelMesh(0, NULL, maliashdr);
+ else
+ {
+ if (skin[4]) GL_DrawModelMesh(skin[4], aliasvertcolor, maliashdr);
+ if (skin[3]) GL_DrawModelMesh(skin[3], NULL, maliashdr);
+ }
+ }
+
+ if (fogenabled)
+ {
+ vec3_t diff;
+ glDisable (GL_TEXTURE_2D);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glEnable (GL_BLEND);
+ glDepthMask(0); // disable zbuffer updates
+
+ VectorSubtract(org, r_refdef.vieworg, diff);
+ glColor4f(fogcolor[0], fogcolor[1], fogcolor[2], exp(fogdensity/DotProduct(diff,diff)));
+
+ if (gl_vertexarrays.value)
+ {
+// qglVertexPointer(3, GL_FLOAT, 0, aliasvert);
+// glEnableClientState(GL_VERTEX_ARRAY);
+ qglDrawElements(GL_TRIANGLES, maliashdr->numtris * 3, GL_UNSIGNED_SHORT, (void *)((int) maliashdr + maliashdr->tridata));
+// glDisableClientState(GL_VERTEX_ARRAY);
+ }
+ else
+ {
+ unsigned short *in;
+ in = (void *)((int) maliashdr + maliashdr->tridata);
+ glBegin(GL_TRIANGLES);
+ for (i = 0;i < maliashdr->numtris * 3;i++)
+ glVertex3fv(&aliasvert[*in++ * 3]);
+ glEnd();
+ }
+
+ glEnable (GL_TEXTURE_2D);
+ glColor3f (1,1,1);
+ }
+ if (gl_vertexarrays.value)
+ glDisableClientState(GL_VERTEX_ARRAY);
+
+ if (!fogenabled && r_shadows.value && !(effects & EF_ADDITIVE) && shadow)
+ {
+ // flatten it to make a shadow
+ float *av = aliasvert + 2, l = lightspot[2] + 0.125;
+ av = aliasvert + 2;
+ for (i = 0;i < maliashdr->numverts;i++, av+=3)
+ if (*av > l)
+ *av = l;
+ glDisable (GL_TEXTURE_2D);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glEnable (GL_BLEND);
+ glDepthMask(0); // disable zbuffer updates
+ glColor4f (0,0,0,0.5 * alpha);
+
+ if (gl_vertexarrays.value)
+ {
+ qglVertexPointer(3, GL_FLOAT, 0, aliasvert);
+ glEnableClientState(GL_VERTEX_ARRAY);
+ qglDrawElements(GL_TRIANGLES, maliashdr->numtris * 3, GL_UNSIGNED_SHORT, (void *)((int) maliashdr + maliashdr->tridata));
+ glDisableClientState(GL_VERTEX_ARRAY);
+ }
+ else
+ {
+ unsigned short *in;
+ in = (void *)((int) maliashdr + maliashdr->tridata);
+ glBegin(GL_TRIANGLES);
+ for (i = 0;i < maliashdr->numtris * 3;i++)
+ glVertex3fv(&aliasvert[*in++ * 3]);
+ glEnd();
+ }
+
+ glEnable (GL_TEXTURE_2D);
+ glColor3f (1,1,1);
+ }
+
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glEnable (GL_BLEND);
+ glDepthMask(1);
+}
+
+/*
+=================
+R_DrawQ2AliasFrame
+
+=================
+*/
+void R_DrawQ2AliasFrame (md2mem_t *pheader, float alpha, vec3_t color, entity_t *ent, int shadow, vec3_t org, int frame, int skin, int effects, int flags)
+{
+ int *order, count;
+ float lerp;
+ md2memframe_t *frame1, *frame2;
+
+ glBindTexture(GL_TEXTURE_2D, skin);
+
+ softwaretransformforentity(ent);
+
+ if ((frame >= pheader->num_frames) || (frame < 0))
+ {
+ Con_DPrintf ("R_SetupQ2AliasFrame: no such frame %d\n", frame);
+ frame = 0;
+ }
+
+ lerp = R_CalcAnimLerp(ent, frame, 10);
+
+ frame1 = (void *)((int) pheader + pheader->ofs_frames + (pheader->framesize * ent->draw_lastpose));
+ frame2 = (void *)((int) pheader + pheader->ofs_frames + (pheader->framesize * ent->draw_pose));
+ R_AliasLerpVerts(pheader->num_xyz, lerp, frame1->verts, frame1->scale, frame1->translate, frame2->verts, frame2->scale, frame2->translate);
+
+ R_LightModel(pheader->num_xyz, org, color);
+
+ if (gl_vertexarrays.value)
+ {
+ // LordHavoc: big mess...
+ // using arrays only slightly, although it is enough to prevent duplicates
+ // (saving half the transforms)
+ qglVertexPointer(3, GL_FLOAT, 0, aliasvert);
+ qglColorPointer(4, GL_UNSIGNED_BYTE, 0, aliasvertcolor);
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glEnableClientState(GL_COLOR_ARRAY);
+
+ order = (int *)((int)pheader + pheader->ofs_glcmds);
+ while(1)
+ {
+ if (!(count = *order++))
+ break;
+ if (count > 0)
+ glBegin(GL_TRIANGLE_STRIP);
+ else
+ {
+ glBegin(GL_TRIANGLE_FAN);
+ count = -count;
+ }
+ do
+ {
+ glTexCoord2f(((float *)order)[0], ((float *)order)[1]);
+ qglArrayElement(order[2]);
+ order += 3;
+ }
+ while (count--);
+ }
+
+ glDisableClientState(GL_COLOR_ARRAY);
+ glDisableClientState(GL_VERTEX_ARRAY);
+ }
+ else
+ {
+ order = (int *)((int)pheader + pheader->ofs_glcmds);
+ while(1)
+ {
+ if (!(count = *order++))
+ break;
+ if (count > 0)
+ glBegin(GL_TRIANGLE_STRIP);
+ else
+ {
+ glBegin(GL_TRIANGLE_FAN);
+ count = -count;
+ }
+ //if (isG200)
+ //{
+ do
+ {
+ glTexCoord2f(((float *)order)[0], ((float *)order)[1]);
+ glColor4f(aliasvertcolor[order[2] * 4] * (1.0f / 255.0f), aliasvertcolor[order[2] * 4 + 1] * (1.0f / 255.0f), aliasvertcolor[order[2] * 4 + 2] * (1.0f / 255.0f), aliasvertcolor[order[2] * 4 + 3] * (1.0f / 255.0f));
+ glVertex3fv(&aliasvert[order[2] * 3]);
+ order += 3;
+ }
+ while (count--);
+ /*
+ }
+ else
+ {
+ do
+ {
+ glTexCoord2f(((float *)order)[0], ((float *)order)[1]);
+ glColor4ub(aliasvertcolor[order[2] * 4], aliasvertcolor[order[2] * 4 + 1], aliasvertcolor[order[2] * 4 + 2], aliasvertcolor[order[2] * 4 + 3]);
+ glVertex3fv(&aliasvert[order[2] * 3]);
+ order += 3;
+ }
+ while (count--);
+ }
+ */
+ }
+ }
+
+ if (fogenabled)
+ {
+ glDisable (GL_TEXTURE_2D);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glEnable (GL_BLEND);
+ glDepthMask(0); // disable zbuffer updates
+ {
+ vec3_t diff;
+ VectorSubtract(org, r_refdef.vieworg, diff);
+ glColor4f(fogcolor[0], fogcolor[1], fogcolor[2], exp(fogdensity/DotProduct(diff,diff)));
+ }
+
+ if (gl_vertexarrays.value)
+ {
+ // LordHavoc: big mess...
+ // using arrays only slightly, although it is enough to prevent duplicates
+ // (saving half the transforms)
+ qglVertexPointer(3, GL_FLOAT, 0, aliasvert);
+ glEnableClientState(GL_VERTEX_ARRAY);
+
+ order = (int *)((int)pheader + pheader->ofs_glcmds);
+ while(1)
+ {
+ if (!(count = *order++))
+ break;
+ if (count > 0)
+ glBegin(GL_TRIANGLE_STRIP);
+ else
+ {
+ glBegin(GL_TRIANGLE_FAN);
+ count = -count;
+ }
+ do
+ {
+ qglArrayElement(order[2]);
+ order += 3;
+ }
+ while (count--);
+ }
+
+ glDisableClientState(GL_VERTEX_ARRAY);
+ }
+ else
+ {
+ order = (int *)((int)pheader + pheader->ofs_glcmds);
+ while(1)
+ {
+ if (!(count = *order++))
+ break;
+ if (count > 0)
+ glBegin(GL_TRIANGLE_STRIP);
+ else
+ {
+ glBegin(GL_TRIANGLE_FAN);
+ count = -count;
+ }
+ do
+ {
+ glVertex3fv(&aliasvert[order[2] * 3]);
+ order += 3;
+ }
+ while (count--);
+ }
+ }
+
+ glEnable (GL_TEXTURE_2D);
+ glColor3f (1,1,1);
+ }
+
+ if (!fogenabled && r_shadows.value && !(effects & EF_ADDITIVE) && shadow)
+ {
+ int i;
+ float *av = aliasvert + 2, l = lightspot[2] + 0.125;
+ av = aliasvert + 2;
+ for (i = 0;i < pheader->num_xyz;i++, av+=3)
+ if (*av > l)
+ *av = l;
+ glDisable (GL_TEXTURE_2D);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glEnable (GL_BLEND);
+ glDepthMask(0); // disable zbuffer updates
+ glColor4f (0,0,0,0.5 * alpha);
+
+ if (gl_vertexarrays.value)
+ {
+ qglVertexPointer(3, GL_FLOAT, 0, aliasvert);
+ glEnableClientState(GL_VERTEX_ARRAY);
+
+ while(1)
+ {
+ if (!(count = *order++))
+ break;
+ if (count > 0)
+ glBegin(GL_TRIANGLE_STRIP);
+ else
+ {
+ glBegin(GL_TRIANGLE_FAN);
+ count = -count;
+ }
+ do
+ {
+ qglArrayElement(order[2]);
+ order += 3;
+ }
+ while (count--);
+ }
+
+ glDisableClientState(GL_VERTEX_ARRAY);
+ }
+ else
+ {
+ while(1)
+ {
+ if (!(count = *order++))
+ break;
+ if (count > 0)
+ glBegin(GL_TRIANGLE_STRIP);
+ else
+ {
+ glBegin(GL_TRIANGLE_FAN);
+ count = -count;
+ }
+ do
+ {
+ glVertex3fv(&aliasvert[order[2] * 3]);
+ order += 3;
+ }
+ while (count--);
+ }
+ }
+
+ glEnable (GL_TEXTURE_2D);
+ glColor3f (1,1,1);
+ }
+
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glEnable (GL_BLEND);
+ glDepthMask(1);
+}
+
+int modeldlightbits[8];
+extern int r_dlightframecount;
+extern void R_LightPoint (vec3_t color, vec3_t p);
+
+/*
+=================
+R_DrawAliasModel
+
+=================
+*/
+void R_DrawAliasModel (entity_t *ent, int cull, float alpha, model_t *clmodel, int frame, int skin, vec3_t org, int effects, int flags, int colormap)
+{
+ int i;
+ vec3_t mins, maxs, color;
+// aliashdr_t *paliashdr = NULL;
+// md2mem_t *pheader = NULL;
+ mleaf_t *leaf;
+ void *modelheader;
+ int *skinset;
+
+ if (alpha < (1.0 / 64.0))
+ return; // basically completely transparent
+
+ VectorAdd (org, clmodel->mins, mins);
+ VectorAdd (org, clmodel->maxs, maxs);
+
+ if (cull && R_CullBox (mins, maxs))
+ return;
+
+ leaf = Mod_PointInLeaf (org, cl.worldmodel);
+ if (leaf->dlightframe == r_dlightframecount)
+ for (i = 0;i < 8;i++)
+ modeldlightbits[i] = leaf->dlightbits[i];
+ else
+ for (i = 0;i < 8;i++)
+ modeldlightbits[i] = 0;
+
+ // get lighting information
+
+ if ((flags & EF_FULLBRIGHT) || (effects & EF_FULLBRIGHT))
+ color[0] = color[1] = color[2] = 256;
+ else
+ {
+ // HACK HACK HACK -- no fullbright colors, so make torches full light
+ if (!strcmp (clmodel->name, "progs/flame2.mdl") || !strcmp (clmodel->name, "progs/flame.mdl") )
+ color[0] = color[1] = color[2] = 128;
+ else
+ R_LightPoint (color, org);
+ }
+
+ glDisable(GL_ALPHA_TEST);
+
+ if (frame < 0 || frame >= clmodel->numframes)
+ {
+ frame = 0;
+ Con_DPrintf("invalid skin number %d for model %s\n", frame, clmodel->name);
+ }
+
+ if (skin < 0 || skin >= clmodel->numskins)
+ {
+ skin = 0;
+ Con_DPrintf("invalid skin number %d for model %s\n", skin, clmodel->name);
+ }
+
+ modelheader = Mod_Extradata (clmodel);
+
+ {
+// int *skinanimrange = (int *) (clmodel->skinanimrange + (int) modelheader) + skin * 2;
+// int *skinanim = (int *) (clmodel->skinanim + (int) modelheader);
+ int *skinanimrange = clmodel->skinanimrange + skin * 2;
+ int *skinanim = clmodel->skinanim;
+ i = skinanimrange[0];
+ if (skinanimrange[1] > 1) // animated
+ i += ((int) (cl.time * 10) % skinanimrange[1]);
+ skinset = skinanim + i*5;
+ }
+
+// glBindTexture(GL_TEXTURE_2D, paliashdr->gl_texturenum[skin][(int)(cl.time*10) & 3]);
+// glBindTexture(GL_TEXTURE_2D, pheader->gl_texturenum[skin]);
+
+ glEnable (GL_TEXTURE_2D);
+
+ c_alias_polys += clmodel->numtris;
+ if (clmodel->aliastype == ALIASTYPE_MD2)
+ R_DrawQ2AliasFrame (modelheader, alpha, color, ent, ent != &cl.viewent, org, frame, skinset[0], effects, flags);
+ else
+ R_DrawAliasFrame (modelheader, alpha, color, ent, ent != &cl.viewent, org, frame, skinset, colormap, effects, flags);
+}
float transreciptable[256];
-void glpoly_init()
+void gl_poly_start()
{
int i;
- Cvar_RegisterVariable (&gl_multitexture);
- Cvar_RegisterVariable (&gl_vertexarrays);
transvert = malloc(MAX_TRANSVERTS * sizeof(transvert_t));
transpoly = malloc(MAX_TRANSPOLYS * sizeof(transpoly_t));
transpolyindex = malloc(MAX_TRANSPOLYS * sizeof(unsigned short));
for (i = 1;i < 256;i++)
transreciptable[i] = 1.0f / i;
}
+void gl_poly_shutdown()
+{
+ free(transvert);
+ free(transpoly);
+ free(transpolyindex);
+ free(wallvert);
+ free(wallpoly);
+ free(skyvert);
+ free(skypoly);
+}
+
+void GL_Poly_Init()
+{
+ Cvar_RegisterVariable (&gl_multitexture);
+ Cvar_RegisterVariable (&gl_vertexarrays);
+ R_RegisterModule("GL_Poly", gl_poly_start, gl_poly_shutdown);
+}
void transpolyclear()
{
// LordHavoc: moved all code related to particles into r_part.c
//int particletexture; // little dot for particles
-int playertextures; // up to 16 color translated skins
+//int playertextures; // up to 16 color translated skins
extern qboolean isG200, isRagePro; // LordHavoc: special card hacks
cvar_t r_waterripple = {"r_waterripple","0"};
cvar_t r_fullbrights = {"r_fullbrights", "1"};
-//cvar_t gl_cull = {"gl_cull","1"};
-//cvar_t gl_affinemodels = {"gl_affinemodels","0"};
-//cvar_t gl_polyblend = {"gl_polyblend","1"};
-cvar_t gl_playermip = {"gl_playermip","0"};
-//cvar_t gl_nocolors = {"gl_nocolors","0"};
-//cvar_t gl_keeptjunctions = {"gl_keeptjunctions","1"};
-//cvar_t gl_reporttjunctions = {"gl_reporttjunctions","0"};
cvar_t contrast = {"contrast", "1.0", TRUE}; // LordHavoc: a method of operating system independent color correction
cvar_t brightness = {"brightness", "1.0", TRUE}; // LordHavoc: a method of operating system independent color correction
cvar_t gl_lightmode = {"gl_lightmode", "1", TRUE}; // LordHavoc: overbright lighting
-//cvar_t r_dynamicwater = {"r_dynamicwater", "1"};
//cvar_t r_dynamicbothsides = {"r_dynamicbothsides", "1"}; // LordHavoc: can disable dynamic lighting of backfaces, but quake maps are weird so it doesn't always work right...
cvar_t r_farclip = {"r_farclip", "6144"};
cvar_t gl_fogend = {"gl_fogend","0"};
cvar_t glfog = {"glfog", "0"};
-int chrometexture;
-
-void makechrometextures()
-{
- int x, y, g, g2, amplitude, noise[64][64], min, max;
- byte data[64][64][4];
- //
- // particle texture
- //
- chrometexture = texture_extension_number++;
- glBindTexture(GL_TEXTURE_2D, chrometexture);
-
-#define n(x,y) noise[(y)&63][(x)&63]
-
- amplitude = 16777215;
- g2 = 64;
- noise[0][0] = 0;
- for (;(g = g2 >> 1) >= 1;g2 >>= 1)
- {
- // subdivide, diamond-square algorythm (really this has little to do with squares)
- // diamond
- for (y = 0;y < 64;y += g2)
- for (x = 0;x < 64;x += g2)
- n(x+g,y+g) = (n(x,y) + n(x+g2,y) + n(x,y+g2) + n(x+g2,y+g2)) >> 2;
- // square
- for (y = 0;y < 64;y += g2)
- for (x = 0;x < 64;x += g2)
- {
- n(x+g,y) = (n(x,y) + n(x+g2,y) + n(x+g,y-g) + n(x+g,y+g)) >> 2;
- n(x,y+g) = (n(x,y) + n(x,y+g2) + n(x-g,y+g) + n(x+g,y+g)) >> 2;
- }
- // brownian motion theory
- amplitude >>= 1;
- for (y = 0;y < 64;y += g)
- for (x = 0;x < 64;x += g)
- noise[y][x] += rand()&litude;
- }
- // normalize the noise range
- min = max = 0;
- for (y = 0;y < 64;y++)
- for (x = 0;x < 64;x++)
- {
- if (n(x,y) < min) min = n(x,y);
- if (n(x,y) > max) max = n(x,y);
- }
- max -= min;
- for (y = 0;y < 64;y++)
- for (x = 0;x < 64;x++)
- n(x,y) = (n(x,y) - min) * 255 / max;
-
-#undef n
-
- // convert to RGBA data
- for (y = 0;y < 64;y++)
- for (x = 0;x < 64;x++)
- {
- data[y][x][0] = data[y][x][1] = data[y][x][2] = (byte) noise[y][x];
- data[y][x][3] = 255;
- }
-
- glTexImage2D (GL_TEXTURE_2D, 0, 4, 64, 64, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
-
- glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
-
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-}
-
extern qboolean isRagePro;
qboolean lighthalf;
}
}
-void glpoly_init();
-void glrsurf_init();
-void rlight_init();
-
-// LordHavoc: vertex array
-float *aliasvert;
-float *aliasvertnorm;
-byte *aliasvertcolor;
+void glmain_start()
+{
+}
-void rmain_registercvars()
+void glmain_shutdown()
{
- // allocate vertex processing arrays
- aliasvert = malloc(sizeof(float[MD2MAX_VERTS][3]));
- aliasvertnorm = malloc(sizeof(float[MD2MAX_VERTS][3]));
- aliasvertcolor = malloc(sizeof(byte[MD2MAX_VERTS][4]));
+}
+void GL_Main_Init()
+{
FOG_registercvars();
Cvar_RegisterVariable (&r_speeds2);
Cvar_RegisterVariable (&contrast);
// if (gl_vendor && strstr(gl_vendor, "3Dfx"))
// gl_lightmode.value = 0;
Cvar_RegisterVariable (&r_fullbright);
- makechrometextures();
- glpoly_init();
- glrsurf_init();
- rlight_init();
+ R_RegisterModule("GL_Main", glmain_start, glmain_shutdown);
+}
+
+extern void GL_Draw_Init();
+extern void GL_Main_Init();
+extern void GL_Models_Init();
+extern void GL_Poly_Init();
+extern void GL_Surf_Init();
+extern void GL_Screen_Init();
+extern void GL_Misc_Init();
+extern void R_Crosshairs_Init();
+extern void R_Light_Init();
+extern void R_Particles_Init();
+
+void Render_Init()
+{
+ R_ShutdownModules();
+ GL_Draw_Init();
+ GL_Main_Init();
+ GL_Models_Init();
+ GL_Poly_Init();
+ GL_Surf_Init();
+ GL_Screen_Init();
+ GL_Misc_Init();
+ R_Crosshairs_Init();
+ R_Light_Init();
+ R_Particles_Init();
+ R_StartModules();
}
/*
float modelalpha;
-void R_LightPoint (vec3_t color, vec3_t p);
-void R_DynamicLightPoint(vec3_t color, vec3_t org, int *dlightbits);
-void R_DynamicLightPointNoMask(vec3_t color, vec3_t org);
-
-float R_CalcAnimLerp(int pose, float lerpscale)
-{
- if (currententity->draw_lastmodel == currententity->model && currententity->draw_lerpstart <= cl.time)
- {
- if (pose != currententity->draw_pose)
- {
- currententity->draw_lastpose = currententity->draw_pose;
- currententity->draw_pose = pose;
- currententity->draw_lerpstart = cl.time;
- return 0;
- }
- else
- return ((cl.time - currententity->draw_lerpstart) * lerpscale);
- }
- else // uninitialized
- {
- currententity->draw_lastmodel = currententity->model;
- currententity->draw_lastpose = currententity->draw_pose = pose;
- currententity->draw_lerpstart = cl.time;
- return 0;
- }
-}
+extern void R_LightPoint (vec3_t color, vec3_t p);
+extern void R_DynamicLightPoint(vec3_t color, vec3_t org, int *dlightbits);
+extern void R_DynamicLightPointNoMask(vec3_t color, vec3_t org);
/*
=============================================================
GL_DrawSpriteImage(newframe, org, up, right, shadecolor[0],shadecolor[1],shadecolor[2],e->alpha*255*lerp);
}
-/*
-=============================================================
-
- ALIAS MODELS
-
-=============================================================
-*/
-
-extern vec3_t softwaretransform_x;
-extern vec3_t softwaretransform_y;
-extern vec3_t softwaretransform_z;
-extern vec_t softwaretransform_scale;
-extern vec3_t softwaretransform_offset;
-void R_AliasLerpVerts(int vertcount, float lerp, trivert2 *verts1, vec3_t scale1, vec3_t translate1, trivert2 *verts2, vec3_t scale2, vec3_t translate2)
-{
- int i;
- vec3_t point, matrix_x, matrix_y, matrix_z;
- float *av, *avn;
- av = aliasvert;
- avn = aliasvertnorm;
- if (lerp < 0) lerp = 0;
- if (lerp > 1) lerp = 1;
- if (lerp != 0)
- {
- float ilerp, ilerp127, lerp127, scalex1, scalex2, translatex, scaley1, scaley2, translatey, scalez1, scalez2, translatez;
- if (lerp < 0) lerp = 0;
- if (lerp > 1) lerp = 1;
- ilerp = 1 - lerp;
- ilerp127 = ilerp * (1.0 / 127.0);
- lerp127 = lerp * (1.0 / 127.0);
- VectorScale(softwaretransform_x, softwaretransform_scale, matrix_x);
- VectorScale(softwaretransform_y, softwaretransform_scale, matrix_y);
- VectorScale(softwaretransform_z, softwaretransform_scale, matrix_z);
- // calculate combined interpolation variables
- scalex1 = scale1[0] * ilerp;scalex2 = scale2[0] * lerp;translatex = translate1[0] * ilerp + translate2[0] * lerp;
- scaley1 = scale1[1] * ilerp;scaley2 = scale2[1] * lerp;translatey = translate1[1] * ilerp + translate2[1] * lerp;
- scalez1 = scale1[2] * ilerp;scalez2 = scale2[2] * lerp;translatez = translate1[2] * ilerp + translate2[2] * lerp;
- // generate vertices
- for (i = 0;i < vertcount;i++)
- {
- // rotate, scale, and translate the vertex locations
- point[0] = verts1->v[0] * scalex1 + verts2->v[0] * scalex2 + translatex;
- point[1] = verts1->v[1] * scaley1 + verts2->v[1] * scaley2 + translatey;
- point[2] = verts1->v[2] * scalez1 + verts2->v[2] * scalez2 + translatez;
- *av++ = point[0] * matrix_x[0] + point[1] * matrix_y[0] + point[2] * matrix_z[0] + softwaretransform_offset[0];
- *av++ = point[0] * matrix_x[1] + point[1] * matrix_y[1] + point[2] * matrix_z[1] + softwaretransform_offset[1];
- *av++ = point[0] * matrix_x[2] + point[1] * matrix_y[2] + point[2] * matrix_z[2] + softwaretransform_offset[2];
- // rotate the normals
- point[0] = verts1->n[0] * ilerp127 + verts2->n[0] * lerp127;
- point[1] = verts1->n[1] * ilerp127 + verts2->n[1] * lerp127;
- point[2] = verts1->n[2] * ilerp127 + verts2->n[2] * lerp127;
- *avn++ = point[0] * softwaretransform_x[0] + point[1] * softwaretransform_y[0] + point[2] * softwaretransform_z[0];
- *avn++ = point[0] * softwaretransform_x[1] + point[1] * softwaretransform_y[1] + point[2] * softwaretransform_z[1];
- *avn++ = point[0] * softwaretransform_x[2] + point[1] * softwaretransform_y[2] + point[2] * softwaretransform_z[2];
- verts1++;verts2++;
- }
- }
- else
- {
- float i127;
- i127 = 1.0f / 127.0f;
- VectorScale(softwaretransform_x, softwaretransform_scale, matrix_x);
- VectorScale(softwaretransform_y, softwaretransform_scale, matrix_y);
- VectorScale(softwaretransform_z, softwaretransform_scale, matrix_z);
- // generate vertices
- for (i = 0;i < vertcount;i++)
- {
- // rotate, scale, and translate the vertex locations
- point[0] = verts1->v[0] * scale1[0] + translate1[0];
- point[1] = verts1->v[1] * scale1[1] + translate1[1];
- point[2] = verts1->v[2] * scale1[2] + translate1[2];
- *av++ = point[0] * matrix_x[0] + point[1] * matrix_y[0] + point[2] * matrix_z[0] + softwaretransform_offset[0];
- *av++ = point[0] * matrix_x[1] + point[1] * matrix_y[1] + point[2] * matrix_z[1] + softwaretransform_offset[1];
- *av++ = point[0] * matrix_x[2] + point[1] * matrix_y[2] + point[2] * matrix_z[2] + softwaretransform_offset[2];
- // rotate the normals
- point[0] = verts1->n[0] * i127;
- point[1] = verts1->n[1] * i127;
- point[2] = verts1->n[2] * i127;
- *avn++ = point[0] * softwaretransform_x[0] + point[1] * softwaretransform_y[0] + point[2] * softwaretransform_z[0];
- *avn++ = point[0] * softwaretransform_x[1] + point[1] * softwaretransform_y[1] + point[2] * softwaretransform_z[1];
- *avn++ = point[0] * softwaretransform_x[2] + point[1] * softwaretransform_y[2] + point[2] * softwaretransform_z[2];
- verts1++;
- }
- }
-}
-
-/*
-=================
-R_DrawAliasFrame
-
-=================
-*/
-extern vec3_t lightspot;
-void R_LightModel(int numverts, vec3_t center);
-extern cvar_t gl_vertexarrays;
-void R_DrawAliasFrame (aliashdr_t *paliashdr)
-{
- int i, pose, frame = currententity->frame;
- float lerpscale, lerp;
-
- softwaretransformforentity(currententity);
-
- if ((frame >= paliashdr->numframes) || (frame < 0))
- {
- Con_DPrintf ("R_AliasSetupFrame: no such frame %d\n", frame);
- frame = 0;
- }
-
- pose = paliashdr->frames[frame].firstpose;
-
- if (paliashdr->frames[frame].numposes > 1)
- {
- lerpscale = 1.0 / paliashdr->frames[frame].interval;
- pose += (int)(cl.time * lerpscale) % paliashdr->frames[frame].numposes;
- }
- else
- lerpscale = 10.0;
-
- lerp = R_CalcAnimLerp(pose, lerpscale);
-
- R_AliasLerpVerts(paliashdr->numverts, lerp, (trivert2 *)((byte *)paliashdr + paliashdr->posedata) + currententity->draw_lastpose * paliashdr->numverts, paliashdr->scale, paliashdr->scale_origin, (trivert2 *)((byte *)paliashdr + paliashdr->posedata) + currententity->draw_pose * paliashdr->numverts, paliashdr->scale, paliashdr->scale_origin);
-
- R_LightModel(paliashdr->numverts, currententity->origin);
-
- glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
- glShadeModel(GL_SMOOTH);
- if (currententity->effects & EF_ADDITIVE)
- {
- glBlendFunc(GL_SRC_ALPHA, GL_ONE); // additive rendering
- glEnable(GL_BLEND);
- glDepthMask(0);
- }
- else if (modelalpha != 1.0)
- {
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glEnable(GL_BLEND);
- glDepthMask(0);
- }
- else
- {
- glDisable(GL_BLEND);
- glDepthMask(1);
- }
-
- if (gl_vertexarrays.value)
- {
- // LordHavoc: I would use InterleavedArrays here,
- // but the texture coordinates are a seperate array,
- // and it would be wasteful to copy them into the main array...
- // glColor4f(shadecolor[0], shadecolor[1], shadecolor[2], modelalpha);
- qglVertexPointer(3, GL_FLOAT, 0, aliasvert);
- qglColorPointer(4, GL_UNSIGNED_BYTE, 0, aliasvertcolor);
- glEnableClientState(GL_VERTEX_ARRAY);
- glEnableClientState(GL_COLOR_ARRAY);
-
- // draw the front faces
- qglTexCoordPointer(2, GL_FLOAT, 0, (void *)((int) paliashdr->texcoords + (int) paliashdr));
- glEnableClientState(GL_TEXTURE_COORD_ARRAY);
- qglDrawElements(GL_TRIANGLES, paliashdr->frontfaces * 3, GL_UNSIGNED_SHORT, (void *)((int) paliashdr->vertindices + (int) paliashdr));
- glDisableClientState(GL_TEXTURE_COORD_ARRAY);
-
- // draw the back faces
- qglTexCoordPointer(2, GL_FLOAT, 0, (void *)((int) paliashdr->texcoords + sizeof(float[2]) * paliashdr->numverts + (int) paliashdr));
- glEnableClientState(GL_TEXTURE_COORD_ARRAY);
- qglDrawElements(GL_TRIANGLES, paliashdr->backfaces * 3, GL_UNSIGNED_SHORT, (void *)((int) paliashdr->vertindices + sizeof(unsigned short[3]) * paliashdr->frontfaces + (int) paliashdr));
- glDisableClientState(GL_TEXTURE_COORD_ARRAY);
-
- glDisableClientState(GL_COLOR_ARRAY);
- glDisableClientState(GL_VERTEX_ARRAY);
- }
- else
- {
- unsigned short *in, index;
- float *tex;
- in = (void *)((int) paliashdr->vertindices + (int) paliashdr);
- glBegin(GL_TRIANGLES);
- // draw the front faces
- tex = (void *)((int) paliashdr->texcoords + (int) paliashdr);
- //if (isG200)
- //{
- for (i = 0;i < paliashdr->frontfaces * 3;i++)
- {
- index = *in++;
- glTexCoord2f(tex[index*2], tex[index*2+1]);
- glColor4f(aliasvertcolor[index*4] * (1.0f / 255.0f), aliasvertcolor[index*4+1] * (1.0f / 255.0f), aliasvertcolor[index*4+2] * (1.0f / 255.0f), aliasvertcolor[index*4+3] * (1.0f / 255.0f));
- glVertex3fv(&aliasvert[index*3]);
- }
- /*
- }
- else
- {
- for (i = 0;i < paliashdr->frontfaces * 3;i++)
- {
- index = *in++;
- glTexCoord2f(tex[index*2], tex[index*2+1]);
- glColor4ub(aliasvertcolor[index*4], aliasvertcolor[index*4+1], aliasvertcolor[index*4+2], aliasvertcolor[index*4+3]);
- glVertex3fv(&aliasvert[index*3]);
- }
- }
- */
- // draw the back faces
- tex += 2 * paliashdr->numverts;
- //if (isG200)
- //{
- for (i = 0;i < paliashdr->backfaces * 3;i++)
- {
- index = *in++;
- glTexCoord2f(tex[index*2], tex[index*2+1]);
- glColor4f(aliasvertcolor[index*4] * (1.0f / 255.0f), aliasvertcolor[index*4+1] * (1.0f / 255.0f), aliasvertcolor[index*4+2] * (1.0f / 255.0f), aliasvertcolor[index*4+3] * (1.0f / 255.0f));
- glVertex3fv(&aliasvert[index*3]);
- }
- /*
- }
- else
- {
- for (i = 0;i < paliashdr->backfaces * 3;i++)
- {
- index = *in++;
- glTexCoord2f(tex[index*2], tex[index*2+1]);
- glColor4ub(aliasvertcolor[index*4], aliasvertcolor[index*4+1], aliasvertcolor[index*4+2], aliasvertcolor[index*4+3]);
- glVertex3fv(&aliasvert[index*3]);
- }
- }
- */
- glEnd();
- }
-
- if (fogenabled)
- {
- vec3_t diff;
- glDisable (GL_TEXTURE_2D);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glEnable (GL_BLEND);
- glDepthMask(0); // disable zbuffer updates
-
- VectorSubtract(currententity->origin, r_refdef.vieworg, diff);
- glColor4f(fogcolor[0], fogcolor[1], fogcolor[2], exp(fogdensity/DotProduct(diff,diff)));
-
- if (gl_vertexarrays.value)
- {
- qglVertexPointer(3, GL_FLOAT, 0, aliasvert);
- glEnableClientState(GL_VERTEX_ARRAY);
- qglDrawElements(GL_TRIANGLES, paliashdr->numtris * 3, GL_UNSIGNED_SHORT, (void *)((int) paliashdr->vertindices + (int) paliashdr));
- glDisableClientState(GL_VERTEX_ARRAY);
- }
- else
- {
- unsigned short *in;
- in = (void *)((int) paliashdr->vertindices + (int) paliashdr);
- glBegin(GL_TRIANGLES);
- for (i = 0;i < paliashdr->numtris * 3;i++)
- glVertex3fv(&aliasvert[*in++ * 3]);
- glEnd();
- }
-
- glEnable (GL_TEXTURE_2D);
- glColor3f (1,1,1);
- }
-
- if (!fogenabled && r_shadows.value && !(currententity->effects & EF_ADDITIVE) && currententity != &cl.viewent)
- {
- // flatten it to make a shadow
- float *av = aliasvert + 2, l = lightspot[2] + 0.125;
- av = aliasvert + 2;
- for (i = 0;i < paliashdr->numverts;i++, av+=3)
- if (*av > l)
- *av = l;
- glDisable (GL_TEXTURE_2D);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glEnable (GL_BLEND);
- glDepthMask(0); // disable zbuffer updates
- glColor4f (0,0,0,0.5 * modelalpha);
-
- if (gl_vertexarrays.value)
- {
- qglVertexPointer(3, GL_FLOAT, 0, aliasvert);
- glEnableClientState(GL_VERTEX_ARRAY);
- qglDrawElements(GL_TRIANGLES, paliashdr->numtris * 3, GL_UNSIGNED_SHORT, (void *)((int) paliashdr->vertindices + (int) paliashdr));
- glDisableClientState(GL_VERTEX_ARRAY);
- }
- else
- {
- unsigned short *in;
- in = (void *)((int) paliashdr->vertindices + (int) paliashdr);
- glBegin(GL_TRIANGLES);
- for (i = 0;i < paliashdr->numtris * 3;i++)
- glVertex3fv(&aliasvert[*in++ * 3]);
- glEnd();
- }
-
- glEnable (GL_TEXTURE_2D);
- glColor3f (1,1,1);
- }
-
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glEnable (GL_BLEND);
- glDepthMask(1);
-}
-
-/*
-=================
-R_DrawQ2AliasFrame
-
-=================
-*/
-void R_DrawQ2AliasFrame (md2mem_t *pheader)
-{
- int *order, count, frame = currententity->frame;
- float lerp;
- md2memframe_t *frame1, *frame2;
-
- softwaretransformforentity(currententity);
-
- if ((frame >= pheader->num_frames) || (frame < 0))
- {
- Con_DPrintf ("R_SetupQ2AliasFrame: no such frame %d\n", frame);
- frame = 0;
- }
-
- lerp = R_CalcAnimLerp(frame, 10);
-
- frame1 = (void *)((int) pheader + pheader->ofs_frames + (pheader->framesize * currententity->draw_lastpose));
- frame2 = (void *)((int) pheader + pheader->ofs_frames + (pheader->framesize * currententity->draw_pose));
- R_AliasLerpVerts(pheader->num_xyz, lerp, frame1->verts, frame1->scale, frame1->translate, frame2->verts, frame2->scale, frame2->translate);
-
- R_LightModel(pheader->num_xyz, currententity->origin);
-
- if (gl_vertexarrays.value)
- {
- // LordHavoc: big mess...
- // using arrays only slightly, although it is enough to prevent duplicates
- // (saving half the transforms)
- //glColor4f(shadecolor[0], shadecolor[1], shadecolor[2], modelalpha);
- qglVertexPointer(3, GL_FLOAT, 0, aliasvert);
- qglColorPointer(4, GL_UNSIGNED_BYTE, 0, aliasvertcolor);
- glEnableClientState(GL_VERTEX_ARRAY);
- glEnableClientState(GL_COLOR_ARRAY);
-
- order = (int *)((int)pheader + pheader->ofs_glcmds);
- while(1)
- {
- if (!(count = *order++))
- break;
- if (count > 0)
- glBegin(GL_TRIANGLE_STRIP);
- else
- {
- glBegin(GL_TRIANGLE_FAN);
- count = -count;
- }
- do
- {
- glTexCoord2f(((float *)order)[0], ((float *)order)[1]);
- qglArrayElement(order[2]);
- order += 3;
- }
- while (count--);
- }
-
- glDisableClientState(GL_COLOR_ARRAY);
- glDisableClientState(GL_VERTEX_ARRAY);
- }
- else
- {
- order = (int *)((int)pheader + pheader->ofs_glcmds);
- while(1)
- {
- if (!(count = *order++))
- break;
- if (count > 0)
- glBegin(GL_TRIANGLE_STRIP);
- else
- {
- glBegin(GL_TRIANGLE_FAN);
- count = -count;
- }
- //if (isG200)
- //{
- do
- {
- glTexCoord2f(((float *)order)[0], ((float *)order)[1]);
- glColor4f(aliasvertcolor[order[2] * 4] * (1.0f / 255.0f), aliasvertcolor[order[2] * 4 + 1] * (1.0f / 255.0f), aliasvertcolor[order[2] * 4 + 2] * (1.0f / 255.0f), aliasvertcolor[order[2] * 4 + 3] * (1.0f / 255.0f));
- glVertex3fv(&aliasvert[order[2] * 3]);
- order += 3;
- }
- while (count--);
- /*
- }
- else
- {
- do
- {
- glTexCoord2f(((float *)order)[0], ((float *)order)[1]);
- glColor4ub(aliasvertcolor[order[2] * 4], aliasvertcolor[order[2] * 4 + 1], aliasvertcolor[order[2] * 4 + 2], aliasvertcolor[order[2] * 4 + 3]);
- glVertex3fv(&aliasvert[order[2] * 3]);
- order += 3;
- }
- while (count--);
- }
- */
- }
- }
-
- if (fogenabled)
- {
- glDisable (GL_TEXTURE_2D);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glEnable (GL_BLEND);
- glDepthMask(0); // disable zbuffer updates
- {
- vec3_t diff;
- VectorSubtract(currententity->origin, r_refdef.vieworg, diff);
- glColor4f(fogcolor[0], fogcolor[1], fogcolor[2], exp(fogdensity/DotProduct(diff,diff)));
- }
-
- if (gl_vertexarrays.value)
- {
- // LordHavoc: big mess...
- // using arrays only slightly, although it is enough to prevent duplicates
- // (saving half the transforms)
- //glColor4f(shadecolor[0], shadecolor[1], shadecolor[2], modelalpha);
- qglVertexPointer(3, GL_FLOAT, 0, aliasvert);
- glEnableClientState(GL_VERTEX_ARRAY);
-
- order = (int *)((int)pheader + pheader->ofs_glcmds);
- while(1)
- {
- if (!(count = *order++))
- break;
- if (count > 0)
- glBegin(GL_TRIANGLE_STRIP);
- else
- {
- glBegin(GL_TRIANGLE_FAN);
- count = -count;
- }
- do
- {
- qglArrayElement(order[2]);
- order += 3;
- }
- while (count--);
- }
-
- glDisableClientState(GL_VERTEX_ARRAY);
- }
- else
- {
- order = (int *)((int)pheader + pheader->ofs_glcmds);
- while(1)
- {
- if (!(count = *order++))
- break;
- if (count > 0)
- glBegin(GL_TRIANGLE_STRIP);
- else
- {
- glBegin(GL_TRIANGLE_FAN);
- count = -count;
- }
- do
- {
- glVertex3fv(&aliasvert[order[2] * 3]);
- order += 3;
- }
- while (count--);
- }
- }
-
- glEnable (GL_TEXTURE_2D);
- glColor3f (1,1,1);
- }
-
- if (!fogenabled && r_shadows.value && !(currententity->effects & EF_ADDITIVE) && currententity != &cl.viewent)
- {
- int i;
- float *av = aliasvert + 2, l = lightspot[2] + 0.125;
- av = aliasvert + 2;
- for (i = 0;i < pheader->num_xyz;i++, av+=3)
- if (*av > l)
- *av = l;
- glDisable (GL_TEXTURE_2D);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glEnable (GL_BLEND);
- glDepthMask(0); // disable zbuffer updates
- glColor4f (0,0,0,0.5 * modelalpha);
-
- if (gl_vertexarrays.value)
- {
- qglVertexPointer(3, GL_FLOAT, 0, aliasvert);
- glEnableClientState(GL_VERTEX_ARRAY);
-
- while(1)
- {
- if (!(count = *order++))
- break;
- if (count > 0)
- glBegin(GL_TRIANGLE_STRIP);
- else
- {
- glBegin(GL_TRIANGLE_FAN);
- count = -count;
- }
- do
- {
- qglArrayElement(order[2]);
- order += 3;
- }
- while (count--);
- }
-
- glDisableClientState(GL_VERTEX_ARRAY);
- }
- else
- {
- while(1)
- {
- if (!(count = *order++))
- break;
- if (count > 0)
- glBegin(GL_TRIANGLE_STRIP);
- else
- {
- glBegin(GL_TRIANGLE_FAN);
- count = -count;
- }
- do
- {
- glVertex3fv(&aliasvert[order[2] * 3]);
- order += 3;
- }
- while (count--);
- }
- }
-
- glEnable (GL_TEXTURE_2D);
- glColor3f (1,1,1);
- }
-
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glEnable (GL_BLEND);
- glDepthMask(1);
-}
-
-int modeldlightbits[8];
-extern int r_dlightframecount;
-
-/*
-=================
-R_DrawAliasModel
-
-=================
-*/
-void R_DrawAliasModel (entity_t *e, int cull)
-{
- int i;
- model_t *clmodel;
- vec3_t mins, maxs;
- aliashdr_t *paliashdr = NULL;
- md2mem_t *pheader = NULL;
- int anim;
-
- if (modelalpha < (1.0 / 64.0))
- return; // basically completely transparent
-
- clmodel = currententity->model;
-
- VectorAdd (currententity->origin, clmodel->mins, mins);
- VectorAdd (currententity->origin, clmodel->maxs, maxs);
-
- if (cull && R_CullBox (mins, maxs))
- return;
-
- VectorCopy (currententity->origin, r_entorigin);
- VectorSubtract (r_origin, r_entorigin, modelorg);
-
- {
- mleaf_t *leaf = Mod_PointInLeaf (currententity->origin, cl.worldmodel);
- if (leaf->dlightframe == r_dlightframecount)
- for (i = 0;i < 8;i++)
- modeldlightbits[i] = leaf->dlightbits[i];
- else
- for (i = 0;i < 8;i++)
- modeldlightbits[i] = 0;
- }
-
- // get lighting information
-
- if (currententity->model->flags & EF_FULLBRIGHT || currententity->effects & EF_FULLBRIGHT)
- {
- shadecolor[0] = currententity->colormod[0] * 256;
- shadecolor[1] = currententity->colormod[1] * 256;
- shadecolor[2] = currententity->colormod[2] * 256;
- }
- else
- {
- R_LightPoint (shadecolor, currententity->origin);
-
- // HACK HACK HACK -- no fullbright colors, so make torches full light
- if (!strcmp (currententity->model->name, "progs/flame2.mdl") || !strcmp (currententity->model->name, "progs/flame.mdl") )
- shadecolor[0] = shadecolor[1] = shadecolor[2] = 128;
-
- shadecolor[0] *= currententity->colormod[0];
- shadecolor[1] *= currententity->colormod[1];
- shadecolor[2] *= currententity->colormod[2];
- }
-
- // locate the proper data
- if (clmodel->aliastype == ALIASTYPE_MD2)
- {
- pheader = (void *)Mod_Extradata (currententity->model);
- c_alias_polys += pheader->num_tris;
- }
- else
- {
- paliashdr = (void *)Mod_Extradata (currententity->model);
- c_alias_polys += paliashdr->numtris;
- }
-
- // draw all the triangles
-
- if (clmodel->aliastype == ALIASTYPE_MD2)
- {
- if (currententity->skinnum < 0 || currententity->skinnum >= pheader->num_skins)
- {
- currententity->skinnum = 0;
- Con_DPrintf("invalid skin number %d for model %s\n", currententity->skinnum, clmodel->name);
- }
- glBindTexture(GL_TEXTURE_2D, pheader->gl_texturenum[currententity->skinnum]);
- }
- else
- {
- if (currententity->skinnum < 0 || currententity->skinnum >= paliashdr->numskins)
- {
- currententity->skinnum = 0;
- Con_DPrintf("invalid skin number %d for model %s\n", currententity->skinnum, clmodel->name);
- }
- anim = (int)(cl.time*10) & 3;
- glBindTexture(GL_TEXTURE_2D, paliashdr->gl_texturenum[currententity->skinnum][anim]);
- }
- glDisable(GL_ALPHA_TEST);
- glEnable (GL_TEXTURE_2D);
-
- // we can't dynamically colormap textures, so they are cached
- // seperately for the players. Heads are just uncolored.
- if (currententity->colormap != 0 /*vid.colormap*/ /* && !gl_nocolors.value*/)
- {
- i = currententity - cl_entities;
- if (i >= 1 && i<=cl.maxclients /* && !strcmp (currententity->model->name, "progs/player.mdl") */)
- glBindTexture(GL_TEXTURE_2D, playertextures - 1 + i);
- }
-
-// if (gl_affinemodels.value)
-// glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
- if (clmodel->aliastype == ALIASTYPE_MD2)
- R_DrawQ2AliasFrame (pheader);
- else
- R_DrawAliasFrame (paliashdr);
-
- glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
-}
-
//==================================================================================
void R_DrawBrushModel (entity_t *e);
switch (currententity->model->type)
{
case mod_alias:
- R_DrawAliasModel (currententity, true);
+ R_DrawAliasModel (currententity, true, modelalpha, currententity->model, currententity->frame, currententity->skinnum, currententity->origin, currententity->effects, currententity->model->flags, currententity->colormap);
break;
case mod_sprite:
// hack the depth range to prevent view model from poking into walls
glDepthRange (gldepthmin, gldepthmin + 0.3*(gldepthmax-gldepthmin));
- R_DrawAliasModel (currententity, FALSE);
+ R_DrawAliasModel (currententity, FALSE, modelalpha, currententity->model, currententity->frame, currententity->skinnum, currententity->origin, currententity->effects, currententity->model->flags, currententity->colormap);
glDepthRange (gldepthmin, gldepthmax);
}
void R_InitParticles (void);
+void gl_misc_start()
+{
+}
+
+void gl_misc_shutdown()
+{
+}
+
/*
===============
R_Init
===============
*/
-void R_Init (void)
+void GL_Misc_Init (void)
{
-// extern cvar_t gl_finish;
-
Cmd_AddCommand ("timerefresh", R_TimeRefresh_f);
Cmd_AddCommand ("envmap", R_Envmap_f);
Cmd_AddCommand ("pointfile", R_ReadPointFile_f);
-// Cvar_RegisterVariable (&r_norefresh);
-// Cvar_RegisterVariable (&r_lightmap);
Cvar_RegisterVariable (&r_drawentities);
Cvar_RegisterVariable (&r_drawviewmodel);
Cvar_RegisterVariable (&r_shadows);
Cvar_RegisterVariable (&r_speeds);
Cvar_RegisterVariable (&r_waterripple); // LordHavoc: added waterripple
-// Cvar_RegisterVariable (&gl_cull);
-// Cvar_RegisterVariable (&gl_affinemodels);
-// Cvar_RegisterVariable (&gl_polyblend);
- Cvar_RegisterVariable (&gl_playermip);
-// Cvar_RegisterVariable (&gl_nocolors);
-
-// Cvar_RegisterVariable (&gl_keeptjunctions);
-// Cvar_RegisterVariable (&gl_reporttjunctions);
-
- R_InitParticles ();
-
- playertextures = texture_extension_number;
- texture_extension_number += 64; // LordHavoc: increased number of players from 16 to 64
+ R_RegisterModule("GL_Misc", gl_misc_start, gl_misc_shutdown);
}
-qboolean VID_Is8bit(void);
-void GL_Upload8_EXT (byte *data, int width, int height, qboolean mipmap, qboolean alpha);
-
-/*
-===============
-R_TranslatePlayerSkin
-
-Translates a skin texture by the per-player color lookup
-===============
-*/
-void R_TranslatePlayerSkin (int playernum)
-{
- int top, bottom;
- byte translate[256];
- unsigned translate32[256];
- int i, j, s;
- model_t *model;
- aliashdr_t *paliashdr;
- byte *original;
- unsigned pixels[512*256], *out;
- unsigned scaled_width, scaled_height;
- int inwidth, inheight;
- byte *inrow;
- unsigned frac, fracstep;
-
- top = cl.scores[playernum].colors & 0xf0;
- bottom = (cl.scores[playernum].colors &15)<<4;
-
- for (i=0 ; i<256 ; i++)
- translate[i] = i;
-
- for (i=0 ; i<16 ; i++)
- {
- // LordHavoc: corrected color ranges
- if (top < 128 || (top >= 224 && top < 240)) // the artists made some backwards ranges. sigh.
- translate[TOP_RANGE+i] = top+i;
- else
- translate[TOP_RANGE+i] = top+15-i;
-
- // LordHavoc: corrected color ranges
- if (bottom < 128 || (bottom >= 224 && bottom < 240))
- translate[BOTTOM_RANGE+i] = bottom+i;
- else
- translate[BOTTOM_RANGE+i] = bottom+15-i;
- }
-
- //
- // locate the original skin pixels
- //
- currententity = &cl_entities[1+playernum];
- model = currententity->model;
- if (!model)
- return; // player doesn't have a model yet
- if (model->type != mod_alias)
- return; // only translate skins on alias models
-
- paliashdr = (aliashdr_t *)Mod_Extradata (model);
- s = paliashdr->skinwidth * paliashdr->skinheight;
- if (currententity->skinnum < 0 || currententity->skinnum >= paliashdr->numskins)
- {
- Con_Printf("(%d): Invalid player skin #%d\n", playernum, currententity->skinnum);
- original = (byte *)paliashdr + paliashdr->texels[0];
- }
- else
- original = (byte *)paliashdr + paliashdr->texels[currententity->skinnum];
- if (s & 3)
- Sys_Error ("R_TranslateSkin: s&3");
-
- inwidth = paliashdr->skinwidth;
- inheight = paliashdr->skinheight;
-
- // because this happens during gameplay, do it fast
- // instead of sending it through gl_upload 8
- glBindTexture(GL_TEXTURE_2D, playertextures + playernum);
-
-#if 0
- byte translated[320*200];
-
- for (i=0 ; i<s ; i+=4)
- {
- translated[i] = translate[original[i]];
- translated[i+1] = translate[original[i+1]];
- translated[i+2] = translate[original[i+2]];
- translated[i+3] = translate[original[i+3]];
- }
-
-
- // don't mipmap these, because it takes too long
- GL_Upload8 (translated, paliashdr->skinwidth, paliashdr->skinheight, false, false, true);
-#else
- scaled_width = gl_max_size.value < 512 ? gl_max_size.value : 512;
- scaled_height = gl_max_size.value < 256 ? gl_max_size.value : 256;
-
- // allow users to crunch sizes down even more if they want
- scaled_width >>= (int)gl_playermip.value;
- scaled_height >>= (int)gl_playermip.value;
-
- if (VID_Is8bit())
- { // 8bit texture upload
- byte *out2;
-
- out2 = (byte *)pixels;
- memset(pixels, 0, sizeof(pixels));
- fracstep = inwidth*0x10000/scaled_width;
- for (i=0 ; i<scaled_height ; i++, out2 += scaled_width)
- {
- inrow = original + inwidth*(i*inheight/scaled_height);
- frac = fracstep >> 1;
- for (j=0 ; j<scaled_width ; j+=4)
- {
- out2[j] = translate[inrow[frac>>16]];
- frac += fracstep;
- out2[j+1] = translate[inrow[frac>>16]];
- frac += fracstep;
- out2[j+2] = translate[inrow[frac>>16]];
- frac += fracstep;
- out2[j+3] = translate[inrow[frac>>16]];
- frac += fracstep;
- }
- }
-
- GL_Upload8_EXT ((byte *)pixels, scaled_width, scaled_height, false, false);
- return;
- }
-
- for (i=0 ; i<256 ; i++)
- translate32[i] = d_8to24table[translate[i]];
-
- out = pixels;
- fracstep = inwidth*0x10000/scaled_width;
- for (i=0 ; i<scaled_height ; i++, out += scaled_width)
- {
- inrow = original + inwidth*(i*inheight/scaled_height);
- frac = fracstep >> 1;
- for (j=0 ; j<scaled_width ; j+=4)
- {
- out[j] = translate32[inrow[frac>>16]];
- frac += fracstep;
- out[j+1] = translate32[inrow[frac>>16]];
- frac += fracstep;
- out[j+2] = translate32[inrow[frac>>16]];
- frac += fracstep;
- out[j+3] = translate32[inrow[frac>>16]];
- frac += fracstep;
- }
- }
- glTexImage2D (GL_TEXTURE_2D, 0, gl_solid_format, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
-
- glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-#endif
-
-}
+//qboolean VID_Is8bit(void);
+//void GL_Upload8_EXT (byte *data, int width, int height, qboolean mipmap, qboolean alpha);
void R_ClearParticles (void);
void GL_BuildLightmaps (void);
cvar_t gl_texsort = {"gl_texsort", "1"};
//cvar_t gl_funnywalls = {"gl_funnywalls", "0"}; // LordHavoc: see BuildSurfaceDisplayList
-qboolean lightmaprgba, nosubimagefragments, nosubimage;
+qboolean lightmaprgba, nosubimagefragments, nosubimage, skyisvisible;
int lightmapbytes;
-qboolean skyisvisible;
extern qboolean gl_arrays;
extern int r_dlightframecount;
-void glrsurf_init()
+void gl_surf_start()
+{
+}
+
+void gl_surf_shutdown()
+{
+}
+
+void GL_Surf_Init()
{
int i;
for (i = 0;i < MAX_LIGHTMAPS;i++)
// Cvar_SetValue("gl_nosubimage", 1);
Cvar_SetValue("gl_lightmode", 0);
}
+
+ R_RegisterModule("GL_Surf", gl_surf_start, gl_surf_shutdown);
}
extern qboolean lighthalf;
extern int alphaskytexture;
extern float speedscale; // for top sky and bottom sky
-qboolean mtexenabled = false;
-
extern char skyname[];
void R_DynamicLightPoint(vec3_t color, vec3_t org, int *dlightbits);
-//extern cvar_t r_dynamicwater;
float turbsin[256] =
{
#include "gl_warp_sin.h"
}
}
-void R_SkySurf(msurface_t *s, qboolean transform)
+float wvert[1024*6]; // used by the following functions
+
+void RSurf_DrawSky(msurface_t *s, int transform)
{
glpoly_t *p;
int i;
}
}
-void R_LightSurface(int *dlightbits, glpoly_t *polys, float *wvert)
+int RSurf_Light(int *dlightbits, glpoly_t *polys)
{
float cr, cg, cb, radius, radius2, f, *v, *wv;
- int i, a, b;
- unsigned int c;
+ int i, a, b, lit = false;
+ unsigned int c, d;
dlight_t *light;
vec_t *lightorigin;
glpoly_t *p;
{
if ((c = dlightbits[a]))
{
- for (b = 0;c && b < 32;b++)
+ for (b = 0, d = 1;c;b++, d <<= 1)
{
- if (c & (1 << b))
+ if (c & d)
{
- c -= (1 << b);
+ c -= d;
light = &cl_dlights[a * 32 + b];
lightorigin = light->origin;
cr = light->color[0];
cg = light->color[1];
cb = light->color[2];
- radius = light->radius*light->radius*16.0f;
- radius2 = radius * 16.0f;
+ radius = light->radius*light->radius*LIGHTSCALE;
+ radius2 = radius * (256.0f / LIGHTSCALE);
wv = wvert;
for (p = polys;p;p = p->next)
{
f = VectorDistance2(wv, lightorigin);
if (f < radius)
{
- f = radius2 / (f + 65536.0f);
+ f = radius2 / (f + LIGHTOFFSET);
wv[3] += cr * f;
wv[4] += cg * f;
wv[5] += cb * f;
+ lit = true;
}
wv += 6;
}
}
}
- c >>= 1;
- b++;
}
}
}
+ return lit;
}
-void R_WaterSurf(msurface_t *s, texture_t *t, qboolean transform, int alpha)
+void RSurf_DrawWater(msurface_t *s, texture_t *t, int transform, int alpha)
{
int i;
float os = turbsin[(int)(realtime * TURBSCALE) & 255], ot = turbsin[(int)(realtime * TURBSCALE + 96.0) & 255];
glpoly_t *p;
- float wvert[1024*6], *wv, *v;
+ float *wv, *v;
wv = wvert;
for (p = s->polys;p;p = p->next)
{
}
}
if (s->dlightframe == r_dlightframecount && r_dynamic.value)
- R_LightSurface(s->dlightbits, s->polys, wvert);
+ RSurf_Light(s->dlightbits, s->polys);
wv = wvert;
// FIXME: make fog texture if water texture is transparent?
for (p=s->polys ; p ; p=p->next)
}
}
-void R_WallSurf(msurface_t *s, texture_t *t, qboolean transform)
+void RSurf_CheckLightmap(msurface_t *s)
{
- int i;
- glpoly_t *p;
- float wvert[64*6], *wv, *v;
- // check for lightmap modification
if (r_dynamic.value)
{
if (r_ambient.value != s->cached_ambient || lighthalf != s->cached_lighthalf
|| (s->styles[3] != 255 && d_lightstylevalue[s->styles[3]] != s->cached_light[3]))
R_UpdateLightmap(s, s->lightmaptexturenum);
}
- wv = wvert;
- for (p = s->polys;p;p = p->next)
+}
+
+void RSurf_Transform(glpoly_t *p, int transform)
+{
+ int i;
+ float *v, *wv = wvert;
+ for (;p;p = p->next)
{
for (i = 0, v = p->verts[0];i < p->numverts;i++, v += VERTEXSIZE)
{
wv += 6;
}
}
- if (s->dlightframe == r_dlightframecount && r_dynamic.value)
- R_LightSurface(s->dlightbits, s->polys, wvert);
- wv = wvert;
- for (p = s->polys;p;p = p->next)
+}
+
+void RSurf_EmitWallpolys(int lightmap, glpoly_t *p, texture_t *t, int lit)
+{
+ int i;
+ float *v, *wv = wvert;
+ wallpoly_t *wp = &wallpoly[currentwallpoly];
+ wallvert_t *out = &wallvert[currentwallvert];
+ for (;p;p = p->next)
{
if (currentwallpoly >= MAX_WALLPOLYS)
break;
+ if (currentwallvert+p->numverts > MAX_WALLVERTS)
+ break;
v = p->verts[0];
- wallpoly[currentwallpoly].texnum = (unsigned short) t->gl_texturenum;
- wallpoly[currentwallpoly].lighttexnum = (unsigned short) lightmap_textures + s->lightmaptexturenum;
- wallpoly[currentwallpoly].glowtexnum = (unsigned short) t->gl_glowtexturenum;
- wallpoly[currentwallpoly].firstvert = currentwallvert;
- wallpoly[currentwallpoly].numverts = p->numverts;
- wallpoly[currentwallpoly++].lit = true;
- for (i = 0;i<p->numverts;i++, v += VERTEXSIZE)
+ wp->texnum = (unsigned short) t->gl_texturenum;
+ wp->lighttexnum = (unsigned short) lightmap;
+ wp->glowtexnum = (unsigned short) t->gl_glowtexturenum;
+ wp->firstvert = currentwallvert;
+ wp->numverts = p->numverts;
+ wp->lit = lit;
+ wp++;
+ currentwallpoly++;
+ currentwallvert += p->numverts;
+ for (i = 0;i < p->numverts;i++, v += VERTEXSIZE, wv += 6, out++)
{
- if (lighthalf)
- {
- wallvert[currentwallvert].r = (byte) (bound(0, (int) wv[3] >> 1, 255));
- wallvert[currentwallvert].g = (byte) (bound(0, (int) wv[4] >> 1, 255));
- wallvert[currentwallvert].b = (byte) (bound(0, (int) wv[5] >> 1, 255));
- wallvert[currentwallvert].a = 255;
- }
- else
+ if (lit)
{
- wallvert[currentwallvert].r = (byte) (bound(0, (int) wv[3], 255));
- wallvert[currentwallvert].g = (byte) (bound(0, (int) wv[4], 255));
- wallvert[currentwallvert].b = (byte) (bound(0, (int) wv[5], 255));
- wallvert[currentwallvert].a = 255;
+ if (lighthalf)
+ {
+ out->r = (byte) (bound(0, (int) wv[3] >> 1, 255));
+ out->g = (byte) (bound(0, (int) wv[4] >> 1, 255));
+ out->b = (byte) (bound(0, (int) wv[5] >> 1, 255));
+ out->a = 255;
+ }
+ else
+ {
+ out->r = (byte) (bound(0, (int) wv[3], 255));
+ out->g = (byte) (bound(0, (int) wv[4], 255));
+ out->b = (byte) (bound(0, (int) wv[5], 255));
+ out->a = 255;
+ }
}
- wallvert[currentwallvert].vert[0] = wv[0];
- wallvert[currentwallvert].vert[1] = wv[1];
- wallvert[currentwallvert].vert[2] = wv[2];
- wallvert[currentwallvert].s = v[3];
- wallvert[currentwallvert].t = v[4];
- wallvert[currentwallvert].u = v[5];
- wallvert[currentwallvert++].v = v[6];
- wv += 6;
+ out->vert[0] = wv[0];
+ out->vert[1] = wv[1];
+ out->vert[2] = wv[2];
+ out->s = v[3];
+ out->t = v[4];
+ out->u = v[5];
+ out->v = v[6];
}
}
}
+void RSurf_DrawWall(msurface_t *s, texture_t *t, int transform)
+{
+ int lit = false;
+ // check for lightmap modification
+ RSurf_CheckLightmap(s);
+ RSurf_Transform(s->polys, transform);
+ if (s->dlightframe == r_dlightframecount && r_dynamic.value)
+ lit = RSurf_Light(s->dlightbits, s->polys);
+ RSurf_EmitWallpolys(lightmap_textures + s->lightmaptexturenum, s->polys, t, lit);
+}
+
// LordHavoc: transparent brush models
extern int r_dlightframecount;
extern float modelalpha;
-//extern vec3_t shadecolor;
-//qboolean R_CullBox (vec3_t mins, vec3_t maxs);
-//void R_DynamicLightPoint(vec3_t color, vec3_t org, int *dlightbits);
-//void R_DynamicLightPointNoMask(vec3_t color, vec3_t org);
-//void EmitWaterPolys (msurface_t *fa);
-void R_WallSurfVertex(msurface_t *s, texture_t *t, qboolean transform, qboolean isbmodel)
+void RSurf_EmitWallVertex(glpoly_t *p, texture_t *t, int modulate, int alpha)
{
- int i, alpha;
+ int i;
+ float *v, *wv = wvert;
+ if (modulate)
+ {
+ for (;p;p = p->next)
+ {
+ v = p->verts[0];
+ transpolybegin(t->gl_texturenum, t->gl_glowtexturenum, 0, currententity->effects & EF_ADDITIVE ? TPOLYTYPE_ADD : TPOLYTYPE_ALPHA);
+ for (i = 0,v = p->verts[0];i < p->numverts;i++, v += VERTEXSIZE, wv += 6)
+ transpolyvert(wv[0], wv[1], wv[2], v[3], v[4], wv[3] * currententity->colormod[0], wv[4] * currententity->colormod[1], wv[5] * currententity->colormod[2], alpha);
+ transpolyend();
+ }
+ }
+ else
+ {
+ for (;p;p = p->next)
+ {
+ v = p->verts[0];
+ transpolybegin(t->gl_texturenum, t->gl_glowtexturenum, 0, currententity->effects & EF_ADDITIVE ? TPOLYTYPE_ADD : TPOLYTYPE_ALPHA);
+ for (i = 0,v = p->verts[0];i < p->numverts;i++, v += VERTEXSIZE, wv += 6)
+ transpolyvert(wv[0], wv[1], wv[2], v[3], v[4], wv[3], wv[4], wv[5], alpha);
+ transpolyend();
+ }
+ }
+}
+
+void RSurf_WallVertexTransform(msurface_t *s, texture_t *t, int transform)
+{
+ int i;
glpoly_t *p;
- float wvert[64*6], *wv, *v;
+ float *wv, *v;
int size3;
float scale;
byte *lm;
size3 = ((s->extents[0]>>4)+1)*((s->extents[1]>>4)+1)*3; // *3 for colored lighting
- alpha = (int) (modelalpha * 255.0f);
- // check for lightmap modification
- if (r_dynamic.value)
- {
- if (r_ambient.value != s->cached_ambient || lighthalf != s->cached_lighthalf
- || (s->styles[0] != 255 && d_lightstylevalue[s->styles[0]] != s->cached_light[0])
- || (s->styles[1] != 255 && d_lightstylevalue[s->styles[1]] != s->cached_light[1])
- || (s->styles[2] != 255 && d_lightstylevalue[s->styles[2]] != s->cached_light[2])
- || (s->styles[3] != 255 && d_lightstylevalue[s->styles[3]] != s->cached_light[3]))
- R_UpdateLightmap(s, s->lightmaptexturenum);
- }
wv = wvert;
for (p = s->polys;p;p = p->next)
{
wv += 6;
}
}
+}
+
+void RSurf_DrawWallVertex(msurface_t *s, texture_t *t, int transform, int isbmodel)
+{
+ RSurf_WallVertexTransform(s, t, transform);
if (s->dlightframe == r_dlightframecount && r_dynamic.value)
- R_LightSurface(s->dlightbits, s->polys, wvert);
- wv = wvert;
- if (isbmodel && (currententity->colormod[0] != 1 || currententity->colormod[1] != 1 || currententity->colormod[2] != 1))
- {
- for (p = s->polys;p;p = p->next)
- {
- v = p->verts[0];
- transpolybegin(t->gl_texturenum, t->gl_glowtexturenum, 0, currententity->effects & EF_ADDITIVE ? TPOLYTYPE_ADD : TPOLYTYPE_ALPHA);
- for (i = 0,v = p->verts[0];i < p->numverts;i++, v += VERTEXSIZE, wv += 6)
- transpolyvert(wv[0], wv[1], wv[2], v[3], v[4], wv[3] * currententity->colormod[0], wv[4] * currententity->colormod[1], wv[5] * currententity->colormod[2], alpha);
- transpolyend();
- }
- }
- else
- {
- for (p = s->polys;p;p = p->next)
- {
- v = p->verts[0];
- transpolybegin(t->gl_texturenum, t->gl_glowtexturenum, 0, currententity->effects & EF_ADDITIVE ? TPOLYTYPE_ADD : TPOLYTYPE_ALPHA);
- for (i = 0,v = p->verts[0];i < p->numverts;i++, v += VERTEXSIZE, wv += 6)
- transpolyvert(wv[0], wv[1], wv[2], v[3], v[4], wv[3], wv[4], wv[5], alpha);
- transpolyend();
- }
- }
+ RSurf_Light(s->dlightbits, s->polys);
+ RSurf_EmitWallVertex(s->polys, t, isbmodel && (currententity->colormod[0] != 1 || currententity->colormod[1] != 1 || currententity->colormod[2] != 1), (int) (modelalpha * 255.0f));
}
/*
*/
extern qboolean hlbsp;
extern char skyname[];
-//extern qboolean SV_TestLine (hull_t *hull, int num, vec3_t p1, vec3_t p2);
-void R_DrawSurf(msurface_t *s, qboolean isbmodel, qboolean vertexlit)
+void R_DrawSurf(msurface_t *s, int isbmodel, int vertexlit)
{
texture_t *t;
if (s->flags & SURF_DRAWSKY)
{
skyisvisible = true;
if (!hlbsp) // LordHavoc: HalfLife maps have freaky skypolys...
- R_SkySurf(s, false);
+ RSurf_DrawSky(s, false);
return;
}
t = R_TextureAnimation (s->texinfo->texture);
if (s->flags & SURF_DRAWTURB)
{
- R_WaterSurf(s, t, false, s->flags & SURF_DRAWNOALPHA ? 255 : r_wateralpha.value*255.0f);
+ RSurf_DrawWater(s, t, false, s->flags & SURF_DRAWNOALPHA ? 255 : r_wateralpha.value*255.0f);
return;
}
if (vertexlit)
- R_WallSurfVertex(s, t, false, false);
+ RSurf_DrawWallVertex(s, t, false, false);
else
- R_WallSurf(s, t, false);
+ RSurf_DrawWall(s, t, false);
}
void DrawTextureChains (void)
skyisvisible = true;
if (!hlbsp) // LordHavoc: HalfLife maps have freaky skypolys...
for (;s;s = s->texturechain)
- R_SkySurf(s, false);
+ RSurf_DrawSky(s, false);
continue;
}
t = R_TextureAnimation (cl.worldmodel->textures[n]);
{
int alpha = s->flags & SURF_DRAWNOALPHA ? 255 : r_wateralpha.value*255.0f;
for (;s;s = s->texturechain)
- R_WaterSurf(s, t, false, alpha);
+ RSurf_DrawWater(s, t, false, alpha);
continue;
}
if (gl_vertex.value)
for (;s;s = s->texturechain)
- R_WallSurfVertex(s, t, false, false);
+ RSurf_DrawWallVertex(s, t, false, false);
else
for (;s;s = s->texturechain)
- R_WallSurf(s, t, false);
+ RSurf_DrawWall(s, t, false);
}
}
vec3_t mins, maxs;
msurface_t *s;
model_t *clmodel;
- qboolean rotated, vertexlit = false;
+ int rotated, vertexlit = false;
texture_t *t;
vec3_t org;
// R_DrawSurf(s, true, vertexlit || s->texinfo->texture->transparent);
if (s->flags & SURF_DRAWSKY)
{
- R_SkySurf(s, true);
+ RSurf_DrawSky(s, true);
continue;
}
t = R_TextureAnimation (s->texinfo->texture);
if (s->flags & SURF_DRAWTURB)
{
- R_WaterSurf(s, t, true, s->flags & SURF_DRAWNOALPHA ? 255 : r_wateralpha.value*255.0f);
+ RSurf_DrawWater(s, t, true, s->flags & SURF_DRAWNOALPHA ? 255 : r_wateralpha.value*255.0f);
continue;
}
if (vertexlit || s->texinfo->texture->transparent)
- R_WallSurfVertex(s, t, true, true);
+ RSurf_DrawWallVertex(s, t, true, true);
else
- R_WallSurf(s, t, true);
+ RSurf_DrawWall(s, t, true);
}
}
UploadLightmaps();
//============================================================================
+void gl_screen_start()
+{
+ scr_ram = Draw_PicFromWad ("ram");
+ scr_net = Draw_PicFromWad ("net");
+ scr_turtle = Draw_PicFromWad ("turtle");
+}
+
+void gl_screen_shutdown()
+{
+}
+
/*
==================
SCR_Init
==================
*/
-void SCR_Init (void)
+void GL_Screen_Init (void)
{
Cvar_RegisterVariable (&scr_fov);
Cmd_AddCommand ("sizeup",SCR_SizeUp_f);
Cmd_AddCommand ("sizedown",SCR_SizeDown_f);
- scr_ram = Draw_PicFromWad ("ram");
- scr_net = Draw_PicFromWad ("net");
- scr_turtle = Draw_PicFromWad ("turtle");
-
scr_initialized = true;
+
+ R_RegisterModule("GL_Screen", gl_screen_start, gl_screen_shutdown);
}
SCR_UpdateScreen ();
cl.cshifts[0].percent = 0; // no area contents palette on next frame
- VID_SetPalette (host_basepal);
}
+void DrawCrosshair(int num);
void GL_Set2D (void);
extern void SHOWLMP_drawall();
if (vid.recalc_refdef)
SCR_CalcRefdef ();
- glClearColor(1,0,0,0);
+ glClearColor(0,0,0,0);
glClear (GL_COLOR_BUFFER_BIT); // LordHavoc: clear the screen (around the view as well)
//
else
{
if (crosshair.value)
- Draw_Character (r_refdef.vrect.x + r_refdef.vrect.width/2, r_refdef.vrect.y + r_refdef.vrect.height/2, '+');
+ DrawCrosshair(crosshair.value);
SCR_DrawRam ();
SCR_DrawNet ();
--- /dev/null
+#include "quakedef.h"
+
+cvar_t gl_max_size = {"gl_max_size", "1024"};
+cvar_t gl_picmip = {"gl_picmip", "0"};
+cvar_t gl_lerpimages = {"gl_lerpimages", "1"};
+
+int gl_filter_min = GL_LINEAR_MIPMAP_LINEAR; //NEAREST;
+int gl_filter_max = GL_LINEAR;
+
+
+int texels;
+
+// 4096x4096
+#define MAXMIPS 12
+
+typedef struct
+{
+ int texnum;
+ byte *texels[MAXMIPS];
+ unsigned short texelsize[MAXMIPS][2];
+ char identifier[64];
+ short width, height;
+// LordHavoc: CRC to identify cache mismatchs
+ unsigned short crc;
+ char mipmap;
+ char alpha;
+ char bytesperpixel;
+ char lerped; // whether this texture was uploaded with or without interpolation
+} gltexture_t;
+
+#define MAX_GLTEXTURES 4096
+gltexture_t gltextures[MAX_GLTEXTURES];
+int numgltextures;
+
+typedef struct
+{
+ char *name;
+ int minimize, maximize;
+} glmode_t;
+
+glmode_t modes[] = {
+ {"GL_NEAREST", GL_NEAREST, GL_NEAREST},
+ {"GL_LINEAR", GL_LINEAR, GL_LINEAR},
+ {"GL_NEAREST_MIPMAP_NEAREST", GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST},
+ {"GL_LINEAR_MIPMAP_NEAREST", GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR},
+ {"GL_NEAREST_MIPMAP_LINEAR", GL_NEAREST_MIPMAP_LINEAR, GL_NEAREST},
+ {"GL_LINEAR_MIPMAP_LINEAR", GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR}
+};
+
+/*
+===============
+Draw_TextureMode_f
+===============
+*/
+void Draw_TextureMode_f (void)
+{
+ int i;
+ gltexture_t *glt;
+
+ if (Cmd_Argc() == 1)
+ {
+ for (i=0 ; i< 6 ; i++)
+ if (gl_filter_min == modes[i].minimize)
+ {
+ Con_Printf ("%s\n", modes[i].name);
+ return;
+ }
+ Con_Printf ("current filter is unknown???\n");
+ return;
+ }
+
+ for (i=0 ; i< 6 ; i++)
+ {
+ if (!Q_strcasecmp (modes[i].name, Cmd_Argv(1) ) )
+ break;
+ }
+ if (i == 6)
+ {
+ Con_Printf ("bad filter name\n");
+ return;
+ }
+
+ gl_filter_min = modes[i].minimize;
+ gl_filter_max = modes[i].maximize;
+
+ // change all the existing mipmap texture objects
+ for (i=0, glt=gltextures ; i<numgltextures ; i++, glt++)
+ {
+ if (glt->mipmap)
+ {
+ glBindTexture(GL_TEXTURE_2D, glt->texnum);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
+ }
+ }
+}
+
+extern int buildnumber;
+
+char engineversion[40];
+
+void GL_UploadTexture (gltexture_t *glt);
+void gl_textures_start()
+{
+ int i;
+ gltexture_t *glt;
+ for (i=0, glt=gltextures ; i<numgltextures ; i++, glt++)
+ GL_UploadTexture(glt);
+}
+
+void gl_textures_shutdown()
+{
+}
+
+void GL_Textures_Init (void)
+{
+ Cvar_RegisterVariable (&gl_max_size);
+ Cvar_RegisterVariable (&gl_picmip);
+ Cvar_RegisterVariable (&gl_lerpimages);
+
+ // 3dfx can only handle 256 wide textures
+ if (!Q_strncasecmp ((char *)gl_renderer, "3dfx",4) || strstr((char *)gl_renderer, "Glide"))
+ Cvar_Set ("gl_max_size", "256");
+
+ Cmd_AddCommand ("gl_texturemode", &Draw_TextureMode_f);
+
+ R_RegisterModule("GL_Textures", gl_textures_start, gl_textures_shutdown);
+}
+
+/*
+================
+GL_FindTexture
+================
+*/
+int GL_FindTexture (char *identifier)
+{
+ int i;
+ gltexture_t *glt;
+
+ for (i=0, glt=gltextures ; i<numgltextures ; i++, glt++)
+ {
+ if (!strcmp (identifier, glt->identifier))
+ return gltextures[i].texnum;
+ }
+
+ return -1;
+}
+
+extern byte qgamma[];
+
+// LordHavoc: gamma correction and improved resampling
+void GL_ResampleTextureLerpLine (byte *in, byte *out, int inwidth, int outwidth)
+{
+ int j, xi, oldx = 0, f, fstep, l1, l2, endx;
+ fstep = (int) (inwidth*65536.0f/outwidth);
+ endx = (inwidth-1);
+ for (j = 0,f = 0;j < outwidth;j++, f += fstep)
+ {
+ xi = (int) f >> 16;
+ if (xi != oldx)
+ {
+ in += (xi - oldx) * 4;
+ oldx = xi;
+ }
+ if (xi < endx)
+ {
+ l2 = f & 0xFFFF;
+ l1 = 0x10000 - l2;
+ *out++ = qgamma[(byte) ((in[0] * l1 + in[4] * l2) >> 16)];
+ *out++ = qgamma[(byte) ((in[1] * l1 + in[5] * l2) >> 16)];
+ *out++ = qgamma[(byte) ((in[2] * l1 + in[6] * l2) >> 16)];
+ *out++ = (byte) ((in[3] * l1 + in[7] * l2) >> 16) ;
+ }
+ else // last pixel of the line has no pixel to lerp to
+ {
+ *out++ = qgamma[in[0]];
+ *out++ = qgamma[in[1]];
+ *out++ = qgamma[in[2]];
+ *out++ = in[3] ;
+ }
+ }
+}
+
+/*
+================
+GL_ResampleTexture
+================
+*/
+void GL_ResampleTexture (void *indata, int inwidth, int inheight, void *outdata, int outwidth, int outheight)
+{
+ // LordHavoc: gamma correction and greatly improved resampling
+ if (gl_lerpimages.value)
+ {
+ int i, j, yi, oldy, f, fstep, l1, l2, endy = (inheight-1);
+ byte *inrow, *out, *row1, *row2;
+ out = outdata;
+ fstep = (int) (inheight*65536.0f/outheight);
+
+ row1 = malloc(outwidth*4);
+ row2 = malloc(outwidth*4);
+ inrow = indata;
+ oldy = 0;
+ GL_ResampleTextureLerpLine (inrow, row1, inwidth, outwidth);
+ GL_ResampleTextureLerpLine (inrow + inwidth*4, row2, inwidth, outwidth);
+ for (i = 0, f = 0;i < outheight;i++,f += fstep)
+ {
+ yi = f >> 16;
+ if (yi != oldy)
+ {
+ inrow = (byte *)indata + inwidth*4*yi;
+ if (yi == oldy+1)
+ memcpy(row1, row2, outwidth*4);
+ else
+ GL_ResampleTextureLerpLine (inrow, row1, inwidth, outwidth);
+ if (yi < endy)
+ GL_ResampleTextureLerpLine (inrow + inwidth*4, row2, inwidth, outwidth);
+ else
+ memcpy(row2, row1, outwidth*4);
+ oldy = yi;
+ }
+ if (yi < endy)
+ {
+ l2 = f & 0xFFFF;
+ l1 = 0x10000 - l2;
+ for (j = 0;j < outwidth;j++)
+ {
+ *out++ = (byte) ((*row1++ * l1 + *row2++ * l2) >> 16);
+ *out++ = (byte) ((*row1++ * l1 + *row2++ * l2) >> 16);
+ *out++ = (byte) ((*row1++ * l1 + *row2++ * l2) >> 16);
+ *out++ = (byte) ((*row1++ * l1 + *row2++ * l2) >> 16);
+ }
+ row1 -= outwidth*4;
+ row2 -= outwidth*4;
+ }
+ else // last line has no pixels to lerp to
+ {
+ for (j = 0;j < outwidth;j++)
+ {
+ *out++ = *row1++;
+ *out++ = *row1++;
+ *out++ = *row1++;
+ *out++ = *row1++;
+ }
+ row1 -= outwidth*4;
+ }
+ }
+ free(row1);
+ free(row2);
+ }
+ else
+ {
+ int i, j;
+ unsigned frac, fracstep;
+ byte *inrow, *out, *inpix;
+ out = outdata;
+
+ fracstep = inwidth*0x10000/outwidth;
+ for (i=0 ; i<outheight ; i++)
+ {
+ inrow = (byte *)indata + inwidth*(i*inheight/outheight)*4;
+ frac = fracstep >> 1;
+ for (j=0 ; j<outwidth ; j+=4)
+ {
+ inpix = inrow + ((frac >> 14) & ~3);*out++ = qgamma[*inpix++];*out++ = qgamma[*inpix++];*out++ = qgamma[*inpix++];*out++ = *inpix++ ;frac += fracstep;
+ inpix = inrow + ((frac >> 14) & ~3);*out++ = qgamma[*inpix++];*out++ = qgamma[*inpix++];*out++ = qgamma[*inpix++];*out++ = *inpix++ ;frac += fracstep;
+ inpix = inrow + ((frac >> 14) & ~3);*out++ = qgamma[*inpix++];*out++ = qgamma[*inpix++];*out++ = qgamma[*inpix++];*out++ = *inpix++ ;frac += fracstep;
+ inpix = inrow + ((frac >> 14) & ~3);*out++ = qgamma[*inpix++];*out++ = qgamma[*inpix++];*out++ = qgamma[*inpix++];*out++ = *inpix++ ;frac += fracstep;
+ }
+ }
+ }
+}
+
+/*
+================
+GL_Resample8BitTexture -- JACK
+================
+*/
+/*
+void GL_Resample8BitTexture (unsigned char *in, int inwidth, int inheight, unsigned char *out, int outwidth, int outheight)
+{
+ int i, j;
+ unsigned char *inrow;
+ unsigned frac, fracstep;
+
+ fracstep = inwidth*0x10000/outwidth;
+ for (i=0 ; i<outheight ; i++, out += outwidth)
+ {
+ inrow = in + inwidth*(i*inheight/outheight);
+ frac = fracstep >> 1;
+ for (j=0 ; j<outwidth ; j+=4)
+ {
+ out[j ] = inrow[frac>>16];frac += fracstep;
+ out[j+1] = inrow[frac>>16];frac += fracstep;
+ out[j+2] = inrow[frac>>16];frac += fracstep;
+ out[j+3] = inrow[frac>>16];frac += fracstep;
+ }
+ }
+}
+*/
+
+
+/*
+================
+GL_MipMap
+
+Operates in place, quartering the size of the texture
+================
+*/
+/*
+void GL_MipMap (byte *in, int width, int height)
+{
+ int i, j;
+ byte *out;
+
+ width <<=2;
+ height >>= 1;
+ out = in;
+ for (i=0 ; i<height ; i++, in+=width)
+ {
+ for (j=0 ; j<width ; j+=8, out+=4, in+=8)
+ {
+ out[0] = (in[0] + in[4] + in[width+0] + in[width+4])>>2;
+ out[1] = (in[1] + in[5] + in[width+1] + in[width+5])>>2;
+ out[2] = (in[2] + in[6] + in[width+2] + in[width+6])>>2;
+ out[3] = (in[3] + in[7] + in[width+3] + in[width+7])>>2;
+ }
+ }
+}
+*/
+
+/*
+================
+GL_MipMap8Bit
+
+Mipping for 8 bit textures
+================
+*/
+/*
+void GL_MipMap8Bit (byte *in, int width, int height)
+{
+ int i, j;
+ unsigned short r,g,b;
+ byte *out, *at1, *at2, *at3, *at4;
+
+ height >>= 1;
+ out = in;
+ for (i=0 ; i<height ; i++, in+=width)
+ {
+ for (j=0 ; j<width ; j+=2, out+=1, in+=2)
+ {
+ at1 = (byte *) (d_8to24table + in[0]);
+ at2 = (byte *) (d_8to24table + in[1]);
+ at3 = (byte *) (d_8to24table + in[width+0]);
+ at4 = (byte *) (d_8to24table + in[width+1]);
+
+ r = (at1[0]+at2[0]+at3[0]+at4[0]); r>>=5;
+ g = (at1[1]+at2[1]+at3[1]+at4[1]); g>>=5;
+ b = (at1[2]+at2[2]+at3[2]+at4[2]); b>>=5;
+
+ out[0] = d_15to8table[(r<<0) + (g<<5) + (b<<10)];
+ }
+ }
+}
+*/
+
+/*
+===============
+GL_Upload32
+===============
+*/
+/*
+void GL_Upload32 (void *data, int width, int height, qboolean mipmap, qboolean alpha)
+{
+ int samples, scaled_width, scaled_height, i;
+ byte *in, *out, *scaled;
+
+ for (scaled_width = 1 ; scaled_width < width ; scaled_width<<=1)
+ ;
+ for (scaled_height = 1 ; scaled_height < height ; scaled_height<<=1)
+ ;
+
+ scaled_width >>= (int)gl_picmip.value;
+ scaled_height >>= (int)gl_picmip.value;
+
+ if (scaled_width > gl_max_size.value)
+ scaled_width = gl_max_size.value;
+ if (scaled_height > gl_max_size.value)
+ scaled_height = gl_max_size.value;
+
+ if (alpha)
+ {
+ alpha = false;
+ in = data;
+ for (i = 3;i < width*height*4;i += 4)
+ if (in[i] != 255)
+ {
+ alpha = true;
+ break;
+ }
+ }
+
+ samples = alpha ? gl_alpha_format : gl_solid_format;
+
+ texels += scaled_width * scaled_height;
+
+ scaled = malloc(scaled_width*scaled_height*4);
+ if (scaled_width == width && scaled_height == height)
+ {
+ // LordHavoc: gamma correct while copying
+ in = (byte *)data;
+ out = (byte *)scaled;
+ for (i = 0;i < width*height;i++)
+ {
+ *out++ = qgamma[*in++];
+ *out++ = qgamma[*in++];
+ *out++ = qgamma[*in++];
+ *out++ = *in++;
+ }
+ }
+ else
+ GL_ResampleTexture (data, width, height, scaled, scaled_width, scaled_height);
+
+ glTexImage2D (GL_TEXTURE_2D, 0, samples, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaled);
+ if (mipmap)
+ {
+ int miplevel;
+
+ miplevel = 0;
+ while (scaled_width > 1 || scaled_height > 1)
+ {
+ GL_MipMap ((byte *)scaled, scaled_width, scaled_height);
+ scaled_width >>= 1;
+ scaled_height >>= 1;
+ if (scaled_width < 1)
+ scaled_width = 1;
+ if (scaled_height < 1)
+ scaled_height = 1;
+ miplevel++;
+ glTexImage2D (GL_TEXTURE_2D, miplevel, samples, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaled);
+ }
+ }
+
+ if (mipmap)
+ {
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
+ }
+ else
+ {
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_max);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
+ }
+ free(scaled);
+}
+
+void GL_Upload8_EXT (byte *data, int width, int height, qboolean mipmap)
+{
+ int scaled_width, scaled_height;
+ byte *scaled = NULL;
+
+ for (scaled_width = 1 ; scaled_width < width ; scaled_width<<=1)
+ ;
+ for (scaled_height = 1 ; scaled_height < height ; scaled_height<<=1)
+ ;
+
+ scaled_width >>= (int)gl_picmip.value;
+ scaled_height >>= (int)gl_picmip.value;
+
+ if (scaled_width > gl_max_size.value)
+ scaled_width = gl_max_size.value;
+ if (scaled_height > gl_max_size.value)
+ scaled_height = gl_max_size.value;
+
+ texels += scaled_width * scaled_height;
+
+ if (scaled_width == width && scaled_height == height)
+ {
+ if (!mipmap)
+ {
+ glTexImage2D (GL_TEXTURE_2D, 0, GL_COLOR_INDEX8_EXT, scaled_width, scaled_height, 0, GL_COLOR_INDEX , GL_UNSIGNED_BYTE, data);
+ goto done;
+ }
+ scaled = malloc(scaled_width*scaled_height*4);
+ memcpy (scaled, data, width*height);
+ }
+ else
+ {
+ scaled = malloc(scaled_width*scaled_height*4);
+ GL_Resample8BitTexture (data, width, height, (void*) scaled, scaled_width, scaled_height);
+ }
+
+ glTexImage2D (GL_TEXTURE_2D, 0, GL_COLOR_INDEX8_EXT, scaled_width, scaled_height, 0, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, scaled);
+ if (mipmap)
+ {
+ int miplevel;
+
+ miplevel = 0;
+ while (scaled_width > 1 || scaled_height > 1)
+ {
+ GL_MipMap8Bit ((byte *)scaled, scaled_width, scaled_height);
+ scaled_width >>= 1;
+ scaled_height >>= 1;
+ if (scaled_width < 1)
+ scaled_width = 1;
+ if (scaled_height < 1)
+ scaled_height = 1;
+ miplevel++;
+ glTexImage2D (GL_TEXTURE_2D, miplevel, GL_COLOR_INDEX8_EXT, scaled_width, scaled_height, 0, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, scaled);
+ }
+ }
+done: ;
+
+
+ if (mipmap)
+ {
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
+ }
+ else
+ {
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_max);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
+ }
+ free(scaled);
+}
+*/
+
+extern qboolean VID_Is8bit();
+
+/*
+===============
+GL_Upload8
+===============
+*/
+/*
+void GL_Upload8 (byte *data, int width, int height, qboolean mipmap, qboolean alpha)
+{
+ static unsigned *trans;
+ int i, s;
+ qboolean noalpha;
+ int p;
+ byte *indata;
+ int *outdata;
+
+ s = width*height;
+ trans = malloc(s*4);
+ // if there are no transparent pixels, make it a 3 component
+ // texture even if it was specified as otherwise
+ if (alpha)
+ {
+ noalpha = true;
+ for (i=0 ; i<s ; i++)
+ {
+ p = data[i];
+ if (p != 255)
+ trans[i] = d_8to24table[p];
+ else
+ {
+ trans[i] = 0; // force to black
+ noalpha = false;
+ }
+ }
+
+ if (noalpha)
+ {
+ if (VID_Is8bit() && (data!=scrap_texels[0]))
+ {
+ GL_Upload8_EXT (data, width, height, mipmap);
+ free(trans);
+ return;
+ }
+ alpha = false;
+ }
+ }
+ else
+ {
+ // LordHavoc: dodge the copy if it will be uploaded as 8bit
+ if (VID_Is8bit() && (data!=scrap_texels[0]))
+ {
+ GL_Upload8_EXT (data, width, height, mipmap);
+ free(trans);
+ return;
+ }
+ //if (s&3)
+ // Sys_Error ("GL_Upload8: s&3");
+ indata = data;
+ outdata = trans;
+ if (s&1)
+ *outdata++ = d_8to24table[*indata++];
+ if (s&2)
+ {
+ *outdata++ = d_8to24table[*indata++];
+ *outdata++ = d_8to24table[*indata++];
+ }
+ for (i = 0;i < s;i+=4)
+ {
+ *outdata++ = d_8to24table[*indata++];
+ *outdata++ = d_8to24table[*indata++];
+ *outdata++ = d_8to24table[*indata++];
+ *outdata++ = d_8to24table[*indata++];
+ }
+ }
+
+ GL_Upload32 (trans, width, height, mipmap, alpha);
+ free(trans);
+}
+*/
+
+void GL_AllocTexels(gltexture_t *glt, int width, int height, int mipmapped)
+{
+ int i, w, h, size, done;
+ if (glt->texels[0])
+ free(glt->texels[0]);
+ glt->texelsize[0][0] = width;
+ glt->texelsize[0][1] = height;
+ if (mipmapped)
+ {
+ size = 0;
+ w = width;h = height;
+ i = 0;
+ done = false;
+ for (i = 0;i < MAXMIPS;i++)
+ {
+ glt->texelsize[i][0] = w;
+ glt->texelsize[i][1] = h;
+ glt->texels[i] = (void *)size;
+ size += w*h*4;
+ if (w > 1)
+ {
+ w >>= 1;
+ if (h > 1)
+ h >>= 1;
+ }
+ else if (h > 1)
+ h >>= 1;
+ else
+ {
+ i++;
+ break;
+ }
+ }
+ while (i < MAXMIPS)
+ glt->texels[i++] = NULL;
+ glt->texels[0] = malloc(size);
+ for (i = 1;i < MAXMIPS && glt->texels[i];i++)
+ glt->texels[i] += (int) glt->texels[0];
+ }
+ else
+ {
+ glt->texels[0] = malloc(width*height*4);
+ for (i = 1;i < MAXMIPS;i++)
+ glt->texels[i] = NULL;
+ }
+ if (!glt->texels[0])
+ Sys_Error("GL_AllocTexels: out of memory\n");
+}
+
+// in can be the same as out
+void GL_MipReduce(byte *in, byte *out, int width, int height, int destwidth, int destheight)
+{
+ int x, y, width2, height2, nextrow;
+ if (width > destwidth)
+ {
+ if (height > destheight)
+ {
+ // reduce both
+ width2 = width >> 1;
+ height2 = height >> 1;
+ nextrow = width << 2;
+ for (y = 0;y < height2;y++)
+ {
+ for (x = 0;x < width2;x++)
+ {
+ out[0] = (byte) ((in[0] + in[4] + in[nextrow ] + in[nextrow+4]) >> 2);
+ out[1] = (byte) ((in[1] + in[5] + in[nextrow+1] + in[nextrow+5]) >> 2);
+ out[2] = (byte) ((in[2] + in[6] + in[nextrow+2] + in[nextrow+6]) >> 2);
+ out[3] = (byte) ((in[3] + in[7] + in[nextrow+3] + in[nextrow+7]) >> 2);
+ out += 4;
+ in += 8;
+ }
+ in += nextrow; // skip a line
+ }
+ }
+ else
+ {
+ // reduce width
+ width2 = width >> 1;
+ for (y = 0;y < height;y++)
+ {
+ for (x = 0;x < width2;x++)
+ {
+ out[0] = (byte) ((in[0] + in[4]) >> 1);
+ out[1] = (byte) ((in[1] + in[5]) >> 1);
+ out[2] = (byte) ((in[2] + in[6]) >> 1);
+ out[3] = (byte) ((in[3] + in[7]) >> 1);
+ out += 4;
+ in += 8;
+ }
+ }
+ }
+ }
+ else
+ {
+ if (height > destheight)
+ {
+ // reduce height
+ height2 = height >> 1;
+ nextrow = width << 2;
+ for (y = 0;y < height2;y++)
+ {
+ for (x = 0;x < width;x++)
+ {
+ out[0] = (byte) ((in[0] + in[nextrow ]) >> 1);
+ out[1] = (byte) ((in[1] + in[nextrow+1]) >> 1);
+ out[2] = (byte) ((in[2] + in[nextrow+2]) >> 1);
+ out[3] = (byte) ((in[3] + in[nextrow+3]) >> 1);
+ out += 4;
+ in += 4;
+ }
+ in += nextrow; // skip a line
+ }
+ }
+ else
+ Sys_Error("GL_MipReduce: desired size already achieved\n");
+ }
+}
+
+void GL_UploadTexture (gltexture_t *glt)
+{
+ int mip, width, height;
+ glBindTexture(GL_TEXTURE_2D, glt->texnum);
+ width = glt->width;
+ height = glt->height;
+ for (mip = 0;mip < MAXMIPS && glt->texels[mip];mip++)
+ glTexImage2D(GL_TEXTURE_2D, mip, glt->alpha ? 4 : 3, glt->texelsize[mip][0], glt->texelsize[mip][1], 0, GL_RGBA, GL_UNSIGNED_BYTE, glt->texels[mip]);
+ if (glt->mipmap)
+ {
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
+ }
+ else
+ {
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_max);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
+ }
+ glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+}
+
+/*
+================
+GL_LoadTexture
+================
+*/
+int GL_LoadTexture (char *identifier, int width, int height, byte *data, qboolean mipmap, qboolean alpha, int bytesperpixel)
+{
+ unsigned short crc;
+ int i, width2, height2, width3, height3, w, h, mip;
+ gltexture_t *glt;
+
+ if (isDedicated)
+ return 1;
+
+ // LordHavoc: do a CRC to confirm the data really is the same as previous occurances.
+ crc = CRC_Block(data, width*height*bytesperpixel);
+ // see if the texture is already present
+ if (identifier[0])
+ {
+ for (i=0, glt=gltextures ; i<numgltextures ; i++, glt++)
+ {
+ if (!strcmp (identifier, glt->identifier))
+ {
+ // LordHavoc: everyone hates cache mismatchs, so I fixed it
+ if (crc != glt->crc || width != glt->width || height != glt->height)
+ {
+ Con_DPrintf("GL_LoadTexture: cache mismatch, replacing old texture\n");
+ goto GL_LoadTexture_setup; // drop out with glt pointing to the texture to replace
+ //Sys_Error ("GL_LoadTexture: cache mismatch");
+ }
+ if ((gl_lerpimages.value != 0) != glt->lerped)
+ goto GL_LoadTexture_setup; // drop out with glt pointing to the texture to replace
+ return glt->texnum;
+ }
+ }
+ }
+ // LordHavoc: although this could be an else condition as it was in the original id code,
+ // it is more clear this way
+ // LordHavoc: check if there are still slots available
+ if (numgltextures >= MAX_GLTEXTURES)
+ Sys_Error ("GL_LoadTexture: ran out of texture slots (%d)\n", MAX_GLTEXTURES);
+ glt = &gltextures[numgltextures++];
+
+ strcpy (glt->identifier, identifier);
+ glt->texnum = texture_extension_number;
+ texture_extension_number++;
+// LordHavoc: label to drop out of the loop into the setup code
+GL_LoadTexture_setup:
+ // calculate power of 2 size
+ width2 = 1;while (width2 < width) width2 <<= 1;
+ height2 = 1;while (height2 < height) height2 <<= 1;
+ // calculate final size (mipmapped downward to this)
+ width3 = width2 >> (int) gl_picmip.value;
+ height3 = height2 >> (int) gl_picmip.value;
+ while (width3 > (int) gl_max_size.value) width3 >>= 1;
+ while (height3 > (int) gl_max_size.value) height3 >>= 1;
+ if (width3 < 1) width3 = 1;
+ if (height3 < 1) height3 = 1;
+
+ // final storage
+ GL_AllocTexels(glt, width3, height3, mipmap);
+ glt->crc = crc; // LordHavoc: used to verify textures are identical
+ glt->width = width;
+ glt->height = height;
+ glt->mipmap = mipmap;
+ glt->bytesperpixel = bytesperpixel;
+ glt->lerped = gl_lerpimages.value != 0;
+ glt->alpha = false; // updated later
+ if (width == width3 && height == height3) // perfect match
+ {
+ if (bytesperpixel == 1) // 8bit
+ Image_Copy8bitRGBA(data, glt->texels[0], width*height, d_8to24table);
+ else
+ Image_CopyRGBAGamma(data, glt->texels[0], width*height);
+ }
+ else if (width == width2 && height == height2) // perfect match for top level, but needs to be reduced
+ {
+ byte *temptexels2;
+ temptexels2 = malloc(width2*height2*4); // scaleup buffer
+ if (bytesperpixel == 1) // 8bit
+ Image_Copy8bitRGBA(data, temptexels2, width*height, d_8to24table);
+ else
+ Image_CopyRGBAGamma(data, temptexels2, width*height);
+ while (width2 > width3 || height2 > height3)
+ {
+ w = width2;h = height2;
+ if (width2 > width3) width2 >>= 1;
+ if (height2 > height3) height2 >>= 1;
+ if (width2 <= width3 && height2 <= height3) // size achieved
+ GL_MipReduce(temptexels2, glt->texels[0], w, h, width3, height3);
+ else
+ GL_MipReduce(temptexels2, temptexels2, w, h, width3, height3);
+ }
+ free(temptexels2);
+ }
+ else // scaling...
+ {
+ byte *temptexels;
+ // pre-scaleup buffer
+ temptexels = malloc(width*height*4);
+ if (bytesperpixel == 1) // 8bit
+ Image_Copy8bitRGBA(data, temptexels, width*height, d_8to24table);
+ else
+ Image_CopyRGBAGamma(data, temptexels, width*height);
+ if (width2 != width3 || height2 != height3) // reduced by gl_pic_mip or gl_max_size
+ {
+ byte *temptexels2;
+ temptexels2 = malloc(width2*height2*4); // scaleup buffer
+ GL_ResampleTexture(temptexels, width, height, temptexels2, width2, height2);
+ while (width2 > width3 || height2 > height3)
+ {
+ w = width2;h = height2;
+ if (width2 > width3) width2 >>= 1;
+ if (height2 > height3) height2 >>= 1;
+ if (width2 <= width3 && height2 <= height3) // size achieved
+ GL_MipReduce(temptexels2, glt->texels[0], w, h, width3, height3);
+ else
+ GL_MipReduce(temptexels2, temptexels2, w, h, width3, height3);
+ }
+ free(temptexels2);
+ }
+ else // copy directly
+ GL_ResampleTexture(temptexels, width, height, glt->texels[0], width2, height2);
+ free(temptexels);
+ }
+ if (alpha)
+ {
+ byte *in = glt->texels[0] + 3;
+ for (i = 0;i < width*height;i++, in += 4)
+ if (*in < 255)
+ {
+ glt->alpha = true;
+ break;
+ }
+ }
+ // this loop is skipped if there are no mipmaps to generate
+ for (mip = 1;mip < MAXMIPS && glt->texels[mip];mip++)
+ GL_MipReduce(glt->texels[mip-1], glt->texels[mip], glt->texelsize[mip-1][0], glt->texelsize[mip-1][1], 1, 1);
+ GL_UploadTexture(glt);
+
+// if (bytesperpixel == 1) // 8bit
+// GL_Upload8 (data, width, height, mipmap, alpha);
+// else // 32bit
+// GL_Upload32 (data, width, height, mipmap, true);
+
+ return glt->texnum;
+}
+
+/*
+================
+GL_LoadPicTexture
+================
+*/
+int GL_LoadPicTexture (qpic_t *pic)
+{
+ return GL_LoadTexture ("", pic->width, pic->height, pic->data, false, true, 1);
+}
+
+int GL_GetTextureSlots (int count)
+{
+ gltexture_t *glt, *first;
+
+ first = glt = &gltextures[numgltextures];
+ while (count--)
+ {
+ glt->identifier[0] = 0;
+ glt->texnum = texture_extension_number++;
+ glt->crc = 0;
+ glt->width = 0;
+ glt->height = 0;
+ glt->bytesperpixel = 0;
+ glt++;
+ numgltextures++;
+ }
+ return first->texnum;
+}
extern qboolean lighthalf;
-#define SKY_TEX 4000
+int skyboxside[6];
char skyname[256];
for (i=0 ; i<6 ; i++)
{
- glBindTexture(GL_TEXTURE_2D, SKY_TEX + i);
sprintf (name, "env/%s%s", skyname, suf[i]);
if (!(image_rgba = loadimagepixels(name, FALSE, 0, 0)))
{
continue;
}
}
- glTexImage2D (GL_TEXTURE_2D, 0, gl_solid_format, image_width, image_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, image_rgba);
+ skyboxside[i] = GL_LoadTexture(va("skyboxside%d", i), image_width, image_height, image_rgba, false, false, 4);
free (image_rgba);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
}
glColor3f(0.5,0.5,0.5);
else
glColor3f(1,1,1);
- glBindTexture(GL_TEXTURE_2D, SKY_TEX + 3); // front
+ glBindTexture(GL_TEXTURE_2D, skyboxside[3]); // front
glBegin(GL_QUADS);
R_SkyBoxPolyVec(1, 0, 1, -1, 1);
R_SkyBoxPolyVec(1, 1, 1, -1, -1);
R_SkyBoxPolyVec(0, 1, 1, 1, -1);
R_SkyBoxPolyVec(0, 0, 1, 1, 1);
glEnd();
- glBindTexture(GL_TEXTURE_2D, SKY_TEX + 1); // back
+ glBindTexture(GL_TEXTURE_2D, skyboxside[1]); // back
glBegin(GL_QUADS);
R_SkyBoxPolyVec(1, 0, -1, 1, 1);
R_SkyBoxPolyVec(1, 1, -1, 1, -1);
R_SkyBoxPolyVec(0, 1, -1, -1, -1);
R_SkyBoxPolyVec(0, 0, -1, -1, 1);
glEnd();
- glBindTexture(GL_TEXTURE_2D, SKY_TEX + 0); // right
+ glBindTexture(GL_TEXTURE_2D, skyboxside[0]); // right
glBegin(GL_QUADS);
R_SkyBoxPolyVec(1, 0, 1, 1, 1);
R_SkyBoxPolyVec(1, 1, 1, 1, -1);
R_SkyBoxPolyVec(0, 1, -1, 1, -1);
R_SkyBoxPolyVec(0, 0, -1, 1, 1);
glEnd();
- glBindTexture(GL_TEXTURE_2D, SKY_TEX + 2); // left
+ glBindTexture(GL_TEXTURE_2D, skyboxside[2]); // left
glBegin(GL_QUADS);
R_SkyBoxPolyVec(1, 0, -1, -1, 1);
R_SkyBoxPolyVec(1, 1, -1, -1, -1);
R_SkyBoxPolyVec(0, 1, 1, -1, -1);
R_SkyBoxPolyVec(0, 0, 1, -1, 1);
glEnd();
- glBindTexture(GL_TEXTURE_2D, SKY_TEX + 4); // up
+ glBindTexture(GL_TEXTURE_2D, skyboxside[4]); // up
glBegin(GL_QUADS);
R_SkyBoxPolyVec(1, 0, 1, -1, 1);
R_SkyBoxPolyVec(1, 1, 1, 1, 1);
R_SkyBoxPolyVec(0, 1, -1, 1, 1);
R_SkyBoxPolyVec(0, 0, -1, -1, 1);
glEnd();
- glBindTexture(GL_TEXTURE_2D, SKY_TEX + 5); // down
+ glBindTexture(GL_TEXTURE_2D, skyboxside[5]); // down
glBegin(GL_QUADS);
R_SkyBoxPolyVec(1, 0, 1, 1, -1);
R_SkyBoxPolyVec(1, 1, 1, -1, -1);
A sky texture is 256*128, with the right side being a masked overlay
==============
*/
-// LordHavoc: changed this for GLQuake
-void R_InitSky (byte *src, int bytesperpixel) //texture_t *mt)
+void R_InitSky (byte *src, int bytesperpixel)
{
int i, j, p;
-// byte *src;
unsigned trans[128*128];
unsigned transpix;
int r, g, b;
unsigned *rgba;
-// src = (byte *)mt + mt->offsets[0];
-
if (bytesperpixel == 4)
{
for (i = 0;i < 128;i++)
((byte *)&transpix)[3] = 0;
}
- if (!solidskytexture)
- solidskytexture = texture_extension_number++;
- if (!isDedicated)
- {
- glBindTexture(GL_TEXTURE_2D, solidskytexture );
- glTexImage2D (GL_TEXTURE_2D, 0, gl_solid_format, 128, 128, 0, GL_RGBA, GL_UNSIGNED_BYTE, trans);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- }
-
+ solidskytexture = GL_LoadTexture ("sky_solidtexture", 128, 128, (byte *) trans, false, false, 4);
if (bytesperpixel == 4)
{
}
}
- if (!alphaskytexture)
- alphaskytexture = texture_extension_number++;
- if (!isDedicated)
- {
- glBindTexture(GL_TEXTURE_2D, alphaskytexture);
- glTexImage2D (GL_TEXTURE_2D, 0, gl_alpha_format, 128, 128, 0, GL_RGBA, GL_UNSIGNED_BYTE, trans);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- }
+ alphaskytexture = GL_LoadTexture ("sky_alphatexture", 128, 128, (byte *) trans, false, true, 4);
}
#include <GL/gl.h>
//#include <GL/glu.h>
-void GL_BeginRendering (int *x, int *y, int *width, int *height);
-void GL_EndRendering (void);
+extern void GL_BeginRendering (int *x, int *y, int *width, int *height);
+extern void GL_EndRendering (void);
extern int texture_extension_number;
extern float gldepthmin, gldepthmax;
-void GL_Upload32 (void *data, int width, int height, qboolean mipmap, qboolean alpha);
-void GL_Upload8 (byte *data, int width, int height, qboolean mipmap, qboolean alpha);
-int GL_LoadTexture (char *identifier, int width, int height, byte *data, qboolean mipmap, qboolean alpha, int bytesperpixel);
-int GL_FindTexture (char *identifier);
+extern void GL_Upload32 (void *data, int width, int height, qboolean mipmap, qboolean alpha);
+extern void GL_Upload8 (byte *data, int width, int height, qboolean mipmap, qboolean alpha);
+extern int GL_LoadTexture (char *identifier, int width, int height, byte *data, qboolean mipmap, qboolean alpha, int bytesperpixel);
+extern int GL_FindTexture (char *identifier);
typedef struct
{
#define BACKFACE_EPSILON 0.01
-void R_TimeRefresh_f (void);
-void R_ReadPointFile_f (void);
+extern void R_TimeRefresh_f (void);
+extern void R_ReadPointFile_f (void);
//====================================================
extern int d_lightstylevalue[256]; // 8.8 fraction of base light value
extern qboolean envmap;
-extern int cnttextures[2];
-// LordHavoc: moved all code relating to particles into r_part.c
-//extern int particletexture;
-extern int playertextures;
extern int skytexturenum; // index in cl.loadmodel, not gl texture object
-//extern cvar_t r_norefresh;
extern cvar_t r_drawentities;
-//extern cvar_t r_drawworld;
extern cvar_t r_drawviewmodel;
extern cvar_t r_speeds;
-//extern cvar_t r_waterwarp;
extern cvar_t r_fullbright;
-//extern cvar_t r_lightmap;
extern cvar_t r_shadows;
extern cvar_t r_wateralpha;
extern cvar_t r_dynamic;
extern cvar_t r_novis;
extern cvar_t r_waterripple;
-//extern cvar_t gl_cull;
-//extern cvar_t gl_poly;
-//extern cvar_t gl_smoothmodels;
-//extern cvar_t gl_affinemodels;
-//extern cvar_t gl_polyblend;
-//extern cvar_t gl_keeptjunctions;
-//extern cvar_t gl_reporttjunctions;
-//extern cvar_t gl_nocolors;
-//extern cvar_t gl_doubleeyes;
-
extern cvar_t gl_max_size;
-extern cvar_t gl_playermip;
extern float r_world_matrix[16];
extern const char *gl_version;
extern const char *gl_extensions;
-void R_TranslatePlayerSkin (int playernum);
-
// Multitexture
#define TEXTURE0_SGIS 0x835E
#define TEXTURE1_SGIS 0x835F
//#define calcfog(v) (exp(-(fogdensity*fogdensity*(((v)[0] - r_refdef.vieworg[0]) * vpn[0] + ((v)[1] - r_refdef.vieworg[1]) * vpn[1] + ((v)[2] - r_refdef.vieworg[2]) * vpn[2])*(((v)[0] - r_refdef.vieworg[0]) * vpn[0] + ((v)[1] - r_refdef.vieworg[1]) * vpn[1] + ((v)[2] - r_refdef.vieworg[2]) * vpn[2]))))
#define calcfog(v) (exp(-(fogdensity*fogdensity*(((v)[0] - r_refdef.vieworg[0])*((v)[0] - r_refdef.vieworg[0])+((v)[1] - r_refdef.vieworg[1])*((v)[1] - r_refdef.vieworg[1])+((v)[2] - r_refdef.vieworg[2])*((v)[2] - r_refdef.vieworg[2])))))
#define calcfogbyte(v) ((byte) (bound(0, ((int) ((float) (calcfog((v)) * 255.0f))), 255)))
+
+#include "r_modules.h"
+
+extern void R_DrawAliasModel (entity_t *ent, int cull, float alpha, model_t *clmodel, int frame, int skin, vec3_t org, int effects, int flags, int colormap);
jmp_buf host_abortserver;
byte *host_basepal;
-//byte *host_colormap;
cvar_t host_framerate = {"host_framerate","0"}; // set for slow motion
cvar_t host_speeds = {"host_speeds","0"}; // set for running times
==================
*/
-#ifdef FPS_20
-
-void _Host_ServerFrame (void)
-{
-// run the world state
- pr_global_struct->frametime = host_frametime;
-
-// read client messages
- SV_RunClients ();
-
-// move things around and think
-// always pause in single player if in console or menus
- if (!sv.paused && (svs.maxclients > 1 || key_dest == key_game) )
- SV_Physics ();
-}
-
-void Host_ServerFrame (void)
-{
- float save_host_frametime;
- float temp_host_frametime;
- static float host_serverframe_timevalue;
-
-// run the world state
- pr_global_struct->frametime = host_frametime;
-
-// set the time and clear the general datagram
- SV_ClearDatagram ();
-
-// check for new clients
- SV_CheckForNewClients ();
-
- temp_host_frametime = save_host_frametime = host_frametime;
- // LordHavoc: the results of my attempts to mangle this code to process no more than sys_ticrate,
- // when I found that was too choppy, I changed it back to processing at least 20fps,
- // I consider it a bit of a failure... because I felt a little out of control in singleplayer
- // (sliding around)
- //if (host_serverframe_timevalue < -0.2) // don't let it get way out of range
- // host_serverframe_timevalue = -0.2;
- //host_serverframe_timevalue += host_frametime;
- // process frames (several if rendering is too slow to run well as a server)
- while(temp_host_frametime > 0.0)
- {
- host_frametime = temp_host_frametime;
- if (host_frametime > 0.05)
- host_frametime = 0.05;
- temp_host_frametime -= host_frametime;
- // host_serverframe_timevalue -= host_frametime;
- _Host_ServerFrame ();
- }
- host_frametime = save_host_frametime;
-
-// send all messages to the clients
- SV_SendClientMessages ();
-// LordHavoc: sadly, this didn't look good to the person running the server in listen mode
- /*
-// wait until enough time has built up when the framerate exceeds sys_ticrate
- if (host_serverframe_timevalue >= sys_ticrate.value)
- //{
- // while(host_serverframe_timevalue >= sys_ticrate.value)
- // host_serverframe_timevalue -= sys_ticrate.value;
-// send all messages to the clients
- SV_SendClientMessages ();
- }
- */
-}
-
-#else
-
double frametimetotal = 0, lastservertime = 0;
void Host_ServerFrame (void)
{
SV_SendClientMessages ();
}
-#endif
-
/*
==================
}
+void Render_Init();
+
/*
====================
Host_Init
if (!host_basepal)
Sys_Error ("Couldn't load gfx/palette.lmp");
host_basepal[765] = host_basepal[766] = host_basepal[767] = 0; // LordHavoc: force the transparent color to black
-// host_colormap = (byte *)COM_LoadHunkFile ("gfx/colormap.lmp", false);
-// if (!host_colormap)
-// Sys_Error ("Couldn't load gfx/colormap.lmp");
#ifndef _WIN32 // on non win32, mouse comes before video for security reasons
IN_Init ();
#endif
VID_Init (host_basepal);
- Draw_Init ();
- SCR_Init ();
- R_Init ();
+ Render_Init();
S_Init ();
CDAudio_Init ();
Sbar_Init ();
if (cls.state != ca_dedicated)
{
+ R_ShutdownModules();
VID_Shutdown();
}
}
void PrintFrameName (model_t *m, int frame)
{
- aliashdr_t *hdr;
- maliasframedesc_t *pframedesc;
+ maliashdr_t *mheader;
+ maliasframe_t *frameinfo;
- hdr = (aliashdr_t *)Mod_Extradata (m);
- if (!hdr)
+ mheader = (maliashdr_t *)Mod_Extradata (m);
+ if (!mheader)
return;
- pframedesc = &hdr->frames[frame];
+ frameinfo = &((maliasframe_t *)(mheader->framedata + (int) mheader))[frame];
- Con_Printf ("frame %i: %s\n", frame, pframedesc->name);
+ Con_Printf ("frame %i: %s\n", frame, frameinfo->name);
}
/*
int image_width;
int image_height;
+// note: pal must be 32bit color
+void Image_Copy8bitRGBA(byte *in, byte *out, int pixels, int *pal)
+{
+ int *iout = (void *)out;
+ while (pixels >= 8)
+ {
+ iout[0] = pal[in[0]];
+ iout[1] = pal[in[1]];
+ iout[2] = pal[in[2]];
+ iout[3] = pal[in[3]];
+ iout[4] = pal[in[4]];
+ iout[5] = pal[in[5]];
+ iout[6] = pal[in[6]];
+ iout[7] = pal[in[7]];
+ in += 8;
+ iout += 8;
+ pixels -= 8;
+ }
+ if (pixels & 4)
+ {
+ iout[0] = pal[in[0]];
+ iout[1] = pal[in[1]];
+ iout[2] = pal[in[2]];
+ iout[3] = pal[in[3]];
+ in += 4;
+ iout += 4;
+ }
+ if (pixels & 2)
+ {
+ iout[0] = pal[in[0]];
+ iout[1] = pal[in[1]];
+ in += 2;
+ iout += 2;
+ }
+ if (pixels & 1)
+ iout[0] = pal[in[0]];
+}
+
+extern byte qgamma[];
+void Image_CopyRGBAGamma(byte *in, byte *out, int pixels)
+{
+ while (pixels--)
+ {
+ out[0] = qgamma[in[0]];
+ out[1] = qgamma[in[1]];
+ out[2] = qgamma[in[2]];
+ out[3] = in[3] ;
+ in += 4;
+ out += 4;
+ }
+}
+
+
/*
=================================================================
}
}
}
+ fclose(f);
image_width = pcx->xmax+1;
image_height = pcx->ymax+1;
return image_rgba;
if (targa_header.colormap_type !=0
|| (targa_header.pixel_size!=32 && targa_header.pixel_size!=24))
- Host_Error ("Texture_LoadTGA: Only 32 or 24 bit images supported (no colormaps)\n");
+ Host_Error ("LoadTGA: Only 32 or 24 bit images supported (no colormaps)\n");
columns = targa_header.width;
rows = targa_header.height;
return image_rgba;
}
+/*
+============
+LoadLMP
+============
+*/
+byte* LoadLMP (FILE *f, int matchwidth, int matchheight)
+{
+ byte *image_rgba;
+ int width, height;
+
+ // parse the very complicated header *chuckle*
+ width = fgetLittleLong(f);
+ height = fgetLittleLong(f);
+ if ((unsigned) width > 4096 || (unsigned) height > 4096)
+ Host_Error("LoadLMP: invalid size\n");
+ if (matchwidth && width != matchwidth)
+ return NULL;
+ if (matchheight && height != matchheight)
+ return NULL;
+
+ image_rgba = malloc(width*height*4);
+ fread(image_rgba + width*height*3, 1, width*height, f);
+ fclose(f);
+
+ Image_Copy8bitRGBA(image_rgba + width*height*3, image_rgba, width*height, d_8to24table);
+ image_width = width;
+ image_height = height;
+ return image_rgba;
+}
+
byte* loadimagepixels (char* filename, qboolean complain, int matchwidth, int matchheight)
{
FILE *f;
char basename[128], name[128];
- byte *image_rgba;
+ byte *image_rgba, *c;
COM_StripExtension(filename, basename); // strip the extension to allow TGA skins on Q2 models despite the .pcx in the skin name
+ // replace *'s with +, so commandline utils don't get confused when dealing with the external files
+ c = basename;
+ while (*c)
+ {
+ if (*c == '*')
+ *c = '+';
+ c++;
+ }
sprintf (name, "textures/%s.tga", basename);
COM_FOpenFile (name, &f, true);
if (f)
COM_FOpenFile (name, &f, true);
if (f)
return LoadPCX (f, matchwidth, matchheight);
+ sprintf (name, "%s.lmp", basename);
+ COM_FOpenFile (name, &f, true);
+ if (f)
+ return LoadLMP (f, matchwidth, matchheight);
+ if ((image_rgba = W_GetTexture(basename, matchwidth, matchheight)))
+ return image_rgba;
+ COM_StripExtension(filename, basename); // do it again with a * this time
if ((image_rgba = W_GetTexture(basename, matchwidth, matchheight)))
return image_rgba;
if (complain)
return NULL;
}
-int loadtextureimage (int texnum, char* filename, qboolean complain, int matchwidth, int matchheight)
+int loadtextureimage (char* filename, int matchwidth, int matchheight, qboolean complain, qboolean mipmap)
{
+ int texnum;
byte *data;
if (!(data = loadimagepixels (filename, complain, matchwidth, matchheight)))
return 0;
+ texnum = GL_LoadTexture (filename, image_width, image_height, data, mipmap, true, 4);
+ free(data);
+ return texnum;
+ /*
if (texnum >= 0) // specific texnum, not cached
{
glBindTexture(GL_TEXTURE_2D, texnum);
- GL_Upload32 (data, image_width, image_height, true, true);
+ GL_Upload32 (data, image_width, image_height, mipmap, true);
free(data);
return texnum;
}
else // any texnum, cached
{
- texnum = GL_LoadTexture (filename, image_width, image_height, data, true, true, 4);
+ texnum = GL_LoadTexture (filename, image_width, image_height, data, mipmap, true, 4);
free(data);
return texnum;
}
+ */
}
--- /dev/null
+
+extern void Image_Copy8bitRGBA(byte *in, byte *out, int pixels, int *pal);
+extern void Image_CopyRGBAGamma(byte *in, byte *out, int pixels);
{
}
-aliashdr_t *pheader;
-
-typedef struct
-{
- int v[3];
- vec3_t normal;
-} temptris_t;
-temptris_t *temptris;
+//aliashdr_t *pheader;
+
+//typedef struct
+//{
+// int v[3];
+// vec3_t normal;
+//} temptris_t;
+//temptris_t *temptris;
//stvert_t stverts[MAXALIASVERTS];
//mtriangle_t triangles[MAXALIASTRIS];
float aliasbboxmin[3], aliasbboxmax[3]; // LordHavoc: proper bounding box considerations
-// LordHavoc: changed to use the normals from the model data itself
+#define MAXVERTS 8192
+float vertst[MAXVERTS][2];
+int vertusage[MAXVERTS];
+int vertonseam[MAXVERTS];
+int vertremap[MAXVERTS];
+unsigned short temptris[MAXVERTS][3];
+
#define NUMVERTEXNORMALS 162
extern float r_avertexnormals[NUMVERTEXNORMALS][3];
-void Mod_ConvertAliasVerts (int numverts, int numtris, vec3_t scale, vec3_t translate, trivertx_t *v, trivert2 *out)
+void Mod_ConvertAliasVerts (int inverts, vec3_t scale, vec3_t translate, trivertx_t *v, trivert2 *out)
{
- int i;
+ int i, j;
vec3_t temp;
- for (i = 0;i < numverts;i++)
+ for (i = 0;i < inverts;i++)
{
- VectorCopy(v[i].v, out[i].v);
+ if (vertremap[i] < 0 && vertremap[i+inverts] < 0) // only used vertices need apply...
+ continue;
temp[0] = v[i].v[0] * scale[0] + translate[0];
temp[1] = v[i].v[1] * scale[1] + translate[1];
temp[2] = v[i].v[2] * scale[2] + translate[2];
if (temp[0] > aliasbboxmax[0]) aliasbboxmax[0] = temp[0];
if (temp[1] > aliasbboxmax[1]) aliasbboxmax[1] = temp[1];
if (temp[2] > aliasbboxmax[2]) aliasbboxmax[2] = temp[2];
- out[i].n[0] = (signed char) (r_avertexnormals[v[i].lightnormalindex][0] * 127.0);
- out[i].n[1] = (signed char) (r_avertexnormals[v[i].lightnormalindex][1] * 127.0);
- out[i].n[2] = (signed char) (r_avertexnormals[v[i].lightnormalindex][2] * 127.0);
- }
- /*
- int i, j;
- vec3_t t1, t2;
- struct
- {
- vec3_t v;
- vec3_t normal;
- int count;
- } tempvert[MD2MAX_VERTS];
- temptris_t *tris;
- // decompress vertices
- for (i = 0;i < numverts;i++)
- {
- VectorCopy(v[i].v, out[i].v);
- tempvert[i].v[0] = v[i].v[0] * scale[0] + translate[0];
- tempvert[i].v[1] = v[i].v[1] * scale[1] + translate[1];
- tempvert[i].v[2] = v[i].v[2] * scale[2] + translate[2];
- tempvert[i].normal[0] = tempvert[i].normal[1] = tempvert[i].normal[2] = 0;
- tempvert[i].count = 0;
- // update bounding box
- if (tempvert[i].v[0] < aliasbboxmin[0]) aliasbboxmin[0] = tempvert[i].v[0];
- if (tempvert[i].v[1] < aliasbboxmin[1]) aliasbboxmin[1] = tempvert[i].v[1];
- if (tempvert[i].v[2] < aliasbboxmin[2]) aliasbboxmin[2] = tempvert[i].v[2];
- if (tempvert[i].v[0] > aliasbboxmax[0]) aliasbboxmax[0] = tempvert[i].v[0];
- if (tempvert[i].v[1] > aliasbboxmax[1]) aliasbboxmax[1] = tempvert[i].v[1];
- if (tempvert[i].v[2] > aliasbboxmax[2]) aliasbboxmax[2] = tempvert[i].v[2];
- }
- // calculate surface normals
- tris = temptris;
- for (i = 0;i < numtris;i++)
- {
- VectorSubtract(tempvert[tris->v[0]].v, tempvert[tris->v[1]].v, t1);
- VectorSubtract(tempvert[tris->v[2]].v, tempvert[tris->v[1]].v, t2);
- CrossProduct(t1, t2, tris->normal);
- VectorNormalize(tris->normal);
- // add surface normal to vertices
- for (j = 0;j < 3;j++)
+ j = vertremap[i]; // not onseam
+ if (j >= 0)
{
- VectorAdd(tris->normal, tempvert[tris->v[j]].normal, tempvert[tris->v[j]].normal);
- tempvert[tris->v[j]].count++;
+ VectorCopy(v[i].v, out[j].v);
+ out[j].n[0] = (signed char) (r_avertexnormals[v[i].lightnormalindex][0] * 127.0);
+ out[j].n[1] = (signed char) (r_avertexnormals[v[i].lightnormalindex][1] * 127.0);
+ out[j].n[2] = (signed char) (r_avertexnormals[v[i].lightnormalindex][2] * 127.0);
+ }
+ j = vertremap[i+inverts]; // onseam
+ if (j >= 0)
+ {
+ VectorCopy(v[i].v, out[j].v);
+ out[j].n[0] = (signed char) (r_avertexnormals[v[i].lightnormalindex][0] * 127.0);
+ out[j].n[1] = (signed char) (r_avertexnormals[v[i].lightnormalindex][1] * 127.0);
+ out[j].n[2] = (signed char) (r_avertexnormals[v[i].lightnormalindex][2] * 127.0);
}
- tris++;
- }
- // average normals and write out 1.7bit format
- for (i = 0;i < pheader->numtris;i++)
- {
- VectorNormalize(tempvert[i].normal);
- out[i].n[0] = (signed char) (tempvert[i].normal[0] * 127.0);
- out[i].n[1] = (signed char) (tempvert[i].normal[1] * 127.0);
- out[i].n[2] = (signed char) (tempvert[i].normal[2] * 127.0);
}
- */
}
/*
Mod_LoadAliasFrame
=================
*/
-void * Mod_LoadAliasFrame (void * pin, maliasframedesc_t *frame)
+void * Mod_LoadAliasFrame (void *pin, maliasframe_t *frame, maliashdr_t *mheader, int inverts, int outverts, trivert2 **posevert)
{
trivertx_t *pinframe;
- int i;
daliasframe_t *pdaliasframe;
pdaliasframe = (daliasframe_t *)pin;
- strcpy (frame->name, pdaliasframe->name);
- frame->firstpose = posenum;
- frame->numposes = 1;
-
- for (i=0 ; i<3 ; i++)
- {
- // these are byte values, so we don't have to worry about
- // endianness
- frame->bboxmin.v[i] = pdaliasframe->bboxmin.v[i];
- frame->bboxmax.v[i] = pdaliasframe->bboxmax.v[i]; // LordHavoc: was setting bboxmin a second time (bug)
- }
+ strcpy(frame->name, pdaliasframe->name);
+ frame->start = posenum;
+ frame->length = 1;
+ frame->rate = 10.0f; // unnecessary but...
pinframe = (trivertx_t *)(pdaliasframe + 1);
-// poseverts[posenum] = pinframe;
- Mod_ConvertAliasVerts(pheader->numverts, pheader->numtris, pheader->scale, pheader->scale_origin, pinframe, (void *)((int) pheader + pheader->posedata + sizeof(trivert2) * pheader->numverts * posenum));
-// // LordHavoc: copy the frame data
-// memcpy((void *)((int) pheader + pheader->posedata + sizeof(trivertx_t) * pheader->numverts * posenum), pinframe, sizeof(trivertx_t) * pheader->numverts);
+ Mod_ConvertAliasVerts(inverts, mheader->scale, mheader->scale_origin, pinframe, *posevert);
+ *posevert += outverts;
posenum++;
- pinframe += pheader->numverts;
+ pinframe += inverts;
return (void *)pinframe;
}
Mod_LoadAliasGroup
=================
*/
-void *Mod_LoadAliasGroup (void * pin, maliasframedesc_t *frame)
+void *Mod_LoadAliasGroup (void *pin, maliasframe_t *frame, maliashdr_t *mheader, int inverts, int outverts, trivert2 **posevert)
{
- daliasgroup_t *pingroup;
- int i, numframes;
- daliasinterval_t *pin_intervals;
- void *ptemp;
+ int i, numframes;
+ void *ptemp;
+ float interval;
- pingroup = (daliasgroup_t *)pin;
-
- numframes = LittleLong (pingroup->numframes);
-
- frame->firstpose = posenum;
- frame->numposes = numframes;
-
- for (i=0 ; i<3 ; i++)
- {
- // these are byte values, so we don't have to worry about endianness
- frame->bboxmin.v[i] = pingroup->bboxmin.v[i];
- frame->bboxmax.v[i] = pingroup->bboxmax.v[i]; // LordHavoc: was setting bboxmin a second time (bug)
- }
-
- pin_intervals = (daliasinterval_t *)(pingroup + 1);
+ numframes = LittleLong (((daliasgroup_t *)pin)->numframes);
- frame->interval = LittleFloat (pin_intervals->interval);
+ strcpy(frame->name, "group");
+ frame->start = posenum;
+ frame->length = numframes;
+ interval = LittleFloat (((daliasinterval_t *)(((daliasgroup_t *)pin) + 1))->interval); // FIXME: support variable framerate groups?
+ if (interval < 0.01f)
+ Host_Error("Mod_LoadAliasGroup: invalid interval");
+ frame->rate = 1.0f / interval;
- pin_intervals += numframes;
-
- ptemp = (void *)pin_intervals;
+ ptemp = (void *)(((daliasinterval_t *)(((daliasgroup_t *)pin) + 1)) + numframes);
for (i=0 ; i<numframes ; i++)
{
-// poseverts[posenum] = (trivertx_t *)((daliasframe_t *)ptemp + 1);
- Mod_ConvertAliasVerts(pheader->numverts, pheader->numtris, pheader->scale, pheader->scale_origin, (void *)((daliasframe_t *)ptemp + 1), (void *)((int) pheader + pheader->posedata + sizeof(trivert2) * pheader->numverts * posenum));
-// // LordHavoc: copy the frame data
-// memcpy((void *)((int) pheader + pheader->posedata + sizeof(trivertx_t) * pheader->numverts * posenum), (void *)((daliasframe_t *)ptemp + 1), sizeof(trivertx_t) * pheader->numverts);
+ ((daliasframe_t *)ptemp)++;
+ Mod_ConvertAliasVerts(inverts, mheader->scale, mheader->scale_origin, ptemp, *posevert);
+ *posevert += outverts;
posenum++;
-
- ptemp = (trivertx_t *)((daliasframe_t *)ptemp + 1) + pheader->numverts;
+ ptemp = (trivertx_t *)ptemp + inverts;
}
return ptemp;
}
}
+int GL_SkinSplitShirt(byte *in, byte *out, int width, int height, unsigned short bits, char *name)
+{
+ int i, pixels, passed;
+ byte pixeltest[16];
+ for (i = 0;i < 16;i++)
+ pixeltest[i] = (bits & (1 << i)) != 0;
+ pixels = width*height;
+ passed = 0;
+ while(pixels--)
+ {
+ if (pixeltest[*in >> 4] && *in != 0 && *in != 255)
+ {
+ passed++;
+ // turn to white while copying
+ if (*in >= 128 && *in < 224) // backwards ranges
+ *out = (*in & 15) ^ 15;
+ else
+ *out = *in & 15;
+ }
+ else
+ *out = 0;
+ in++;
+ out++;
+ }
+ if (passed)
+ return GL_LoadTexture (name, width, height, out - width*height, true, false, 1);
+ else
+ return 0;
+}
+
+int GL_SkinSplit(byte *in, byte *out, int width, int height, unsigned short bits, char *name)
+{
+ int i, pixels, passed;
+ byte pixeltest[16];
+ for (i = 0;i < 16;i++)
+ pixeltest[i] = (bits & (1 << i)) != 0;
+ pixels = width*height;
+ passed = 0;
+ while(pixels--)
+ {
+ if (pixeltest[*in >> 4] && *in != 0 && *in != 255)
+ {
+ passed++;
+ *out = *in;
+ }
+ else
+ *out = 0;
+ in++;
+ out++;
+ }
+ if (passed)
+ return GL_LoadTexture (name, width, height, out - width*height, true, false, 1);
+ else
+ return 0;
+}
+
/*
===============
Mod_LoadAllSkins
===============
*/
-void *Mod_LoadAllSkins (int numskins, daliasskintype_t *pskintype, int bytesperpixel)
+void *Mod_LoadAllSkins (int numskins, daliasskintype_t *pskintype, int width, int height)
{
- int i, j, k;
+ int i, j;
char name[32];
int s;
byte *skin;
- byte *texels;
daliasskingroup_t *pinskingroup;
int groupskins;
daliasskininterval_t *pinskinintervals;
+ int skinranges, skincount, *skintexnum, *skinrange, skinnum;
+ void *temp;
+ byte *skintemp = NULL;
skin = (byte *)(pskintype + 1);
if (numskins < 1 || numskins > MAX_SKINS)
Host_Error ("Mod_LoadAliasModel: Invalid # of skins: %d\n", numskins);
- s = pheader->skinwidth * pheader->skinheight;
+ s = width * height;
+ skintemp = malloc(s);
+ // LordHavoc: skim the data, measure the number of skins and number of groups
+ skinranges = numskins;
+ skincount = 0;
+ temp = pskintype;
+ for (i = 0;i < numskins;i++)
+ {
+ pskintype++;
+ if (pskintype[-1].type == ALIAS_SKIN_SINGLE)
+ {
+ skincount++;
+ (byte *)pskintype += s;
+ }
+ else
+ {
+ groupskins = LittleLong (((daliasskingroup_t *)pskintype)->numskins);
+ skincount += groupskins;
+ (byte *)pskintype += (s + sizeof(daliasskininterval_t)) * groupskins + sizeof(daliasskingroup_t);
+ }
+ }
+ pskintype = temp;
+
+ skinrange = loadmodel->skinanimrange;
+ skintexnum = loadmodel->skinanim;
+// skinrange = Hunk_AllocName (sizeof(int) * (skinranges + skincount), loadname);
+// skintexnum = skinrange + skinranges * 2;
+// loadmodel->skinanimrange = (int) skinrange - (int) pheader;
+// loadmodel->skinanim = (int) skintexnum - (int) pheader;
+ skinnum = 0;
for (i = 0;i < numskins;i++)
{
- if (pskintype->type == ALIAS_SKIN_SINGLE)
+ *skinrange++ = skinnum; // start of the range
+ pskintype++;
+ if (pskintype[-1].type == ALIAS_SKIN_SINGLE)
{
- if (bytesperpixel == 1)
- Mod_FloodFillSkin( skin, pheader->skinwidth, pheader->skinheight );
-
- // save 8 bit texels for the player model to remap
- // if (!strcmp(loadmodel->name,"progs/player.mdl")) {
- texels = Hunk_AllocName(s, loadname);
- pheader->texels[i] = texels - (byte *)pheader;
- memcpy (texels, (byte *)(pskintype + 1), s);
- // }
+ *skinrange++ = 1; // single skin
+ skinnum++;
sprintf (name, "%s_%i", loadmodel->name, i);
- pheader->gl_texturenum[i][0] =
- pheader->gl_texturenum[i][1] =
- pheader->gl_texturenum[i][2] =
- pheader->gl_texturenum[i][3] =
- GL_LoadTexture (name, pheader->skinwidth, pheader->skinheight, (byte *)(pskintype + 1), true, false, bytesperpixel);
- pskintype = (daliasskintype_t *)((byte *)(pskintype+1) + s);
+
+ Mod_FloodFillSkin( skin, width, height );
+ *skintexnum++ = GL_SkinSplit((byte *)pskintype, skintemp, width, height, 0x3FBD, va("%s_normal", name)); // normal (no special colors)
+ *skintexnum++ = GL_SkinSplitShirt((byte *)pskintype, skintemp, width, height, 0x0040, va("%s_pants", name)); // pants
+ *skintexnum++ = GL_SkinSplitShirt((byte *)pskintype, skintemp, width, height, 0x0002, va("%s_shirt", name)); // shirt
+ *skintexnum++ = GL_SkinSplit((byte *)pskintype, skintemp, width, height, 0xC000, va("%s_glow", name)); // glow
+ *skintexnum++ = GL_SkinSplit((byte *)pskintype, skintemp, width, height, 0x3FFF, va("%s_body", name)); // body (normal + pants + shirt, but not glow)
+ pskintype = (daliasskintype_t *)((byte *)(pskintype) + s);
}
else
{
// animating skin group. yuck.
- pskintype++;
pinskingroup = (daliasskingroup_t *)pskintype;
groupskins = LittleLong (pinskingroup->numskins);
pinskinintervals = (daliasskininterval_t *)(pinskingroup + 1);
pskintype = (void *)(pinskinintervals + groupskins);
+ *skinrange++ = groupskins; // number of skins
+ skinnum += groupskins;
for (j = 0;j < groupskins;j++)
{
- if (bytesperpixel == 1)
- Mod_FloodFillSkin( skin, pheader->skinwidth, pheader->skinheight );
- if (j == 0)
- {
- texels = Hunk_AllocName(s, loadname);
- pheader->texels[i] = texels - (byte *)pheader;
- memcpy (texels, (byte *)(pskintype), s);
- }
- sprintf (name, "%s_%i_%i", loadmodel->name, i,j);
- pheader->gl_texturenum[i][j&3] =
- GL_LoadTexture (name, pheader->skinwidth, pheader->skinheight, (byte *)(pskintype), true, false, bytesperpixel);
- pskintype = (daliasskintype_t *)((byte *)(pskintype) + s);
+ sprintf (name, "%s_%i_%i", loadmodel->name, i,j);
+
+ Mod_FloodFillSkin( skin, width, height );
+ *skintexnum++ = GL_SkinSplit((byte *)pskintype, skintemp, width, height, 0x3FBD, va("%s_normal", name)); // normal (no special colors)
+ *skintexnum++ = GL_SkinSplitShirt((byte *)pskintype, skintemp, width, height, 0x0040, va("%s_pants", name)); // pants
+ *skintexnum++ = GL_SkinSplitShirt((byte *)pskintype, skintemp, width, height, 0x0002, va("%s_shirt", name)); // shirt
+ *skintexnum++ = GL_SkinSplit((byte *)pskintype, skintemp, width, height, 0xC000, va("%s_glow", name)); // glow
+ *skintexnum++ = GL_SkinSplit((byte *)pskintype, skintemp, width, height, 0x3FFF, va("%s_body", name)); // body (normal + pants + shirt, but not glow)
+ pskintype = (daliasskintype_t *)((byte *)(pskintype) + s);
}
- k = j;
- for (;j < 4;j++)
- pheader->gl_texturenum[i][j&3] = pheader->gl_texturenum[i][j - k];
}
}
+ loadmodel->numskins = numskins;
+ free(skintemp);
return (void *)pskintype;
}
+void *Mod_SkipAllSkins (int numskins, daliasskintype_t *pskintype, int skinsize)
+{
+ int i;
+ for (i = 0;i < numskins;i++)
+ {
+ pskintype++;
+ if (pskintype[-1].type == ALIAS_SKIN_SINGLE)
+ (byte *)pskintype += skinsize;
+ else
+ (byte *)pskintype += (skinsize + sizeof(daliasskininterval_t)) * LittleLong (((daliasskingroup_t *)pskintype)->numskins) + sizeof(daliasskingroup_t);
+ }
+ return pskintype;
+}
+
//=========================================================================
//void GL_MakeAliasModelDisplayLists (model_t *m, aliashdr_t *hdr);
#define BOUNDF(VALUE,MIN,MAX) if (VALUE < MIN || VALUE >= MAX) Host_Error("model %s has an invalid VALUE (%f exceeds %f - %f)\n", mod->name, VALUE, MIN, MAX);
void Mod_LoadAliasModel (model_t *mod, void *buffer)
{
- int i, j, version, numframes, size, start, end, total;
+ int i, j, version, numframes, start, end, total, numverts, numtris, numposes, numskins, skinwidth, skinheight, f, totalverts;
mdl_t *pinmodel;
stvert_t *pinstverts;
dtriangle_t *pintriangles;
daliasframetype_t *pframetype;
daliasskintype_t *pskintype;
- // LordHavoc: 32bit textures
- int bytesperpixel;
- unsigned short *poutvertindices;
float *pouttexcoords, scales, scalet;
- temptris_t *tris;
+ maliashdr_t *mheader;
+ unsigned short *pouttris;
+ maliasframe_t *frame;
+ trivert2 *posevert;
start = Hunk_LowMark ();
- if (!temptris)
- temptris = malloc(sizeof(temptris_t) * MD2MAX_TRIANGLES);
-
pinmodel = (mdl_t *)buffer;
version = LittleLong (pinmodel->version);
- if (version != ALIAS_VERSION && version != ALIAS32_VERSION)
- Host_Error ("%s has wrong version number (%i should be %i or %i)",
- mod->name, version, ALIAS_VERSION, ALIAS32_VERSION);
+ if (version != ALIAS_VERSION)
+ Host_Error ("%s has wrong version number (%i should be %i)",
+ mod->name, version, ALIAS_VERSION);
mod->type = ALIASTYPE_MDL;
-//
-// allocate space for a working header, plus all the data except the frames,
-// skin and group info
-//
-// size = sizeof (aliashdr_t) + (LittleLong (pinmodel->numframes) - 1) * sizeof (pinmodel->frames[0]));
- size = sizeof (aliashdr_t);
- size += LittleLong (pinmodel->numverts) * sizeof(float[2][2]);
- size += LittleLong (pinmodel->numtris) * sizeof(unsigned short[3]);
- size += LittleLong (pinmodel->numframes) * (sizeof(trivert2) * LittleLong (pinmodel->numverts) + sizeof(maliasframedesc_t));
- BOUNDI(size,256,4194304);
- pheader = Hunk_AllocName (size, loadname);
+ numframes = LittleLong(pinmodel->numframes);
+ BOUNDI(numframes,0,65536);
+ numverts = LittleLong(pinmodel->numverts);
+ BOUNDI(numverts,0,MAXALIASVERTS);
+ numtris = LittleLong(pinmodel->numtris);
+ BOUNDI(numtris,0,65536);
+ numskins = LittleLong(pinmodel->numskins);
+ BOUNDI(numskins,0,256);
+ skinwidth = LittleLong (pinmodel->skinwidth);
+ BOUNDI(skinwidth,0,4096);
+ skinheight = LittleLong (pinmodel->skinheight);
+ BOUNDI(skinheight,0,1024);
+ pskintype = (daliasskintype_t *)&pinmodel[1];
+ pinstverts = (stvert_t *)Mod_SkipAllSkins (numskins, pskintype, skinwidth * skinheight);
+ pintriangles = (dtriangle_t *)&pinstverts[numverts];
+ pframetype = (daliasframetype_t *)&pintriangles[numtris];
+
+ numposes = 0;
+ for (i=0 ; i<numframes ; i++)
+ {
+ if ((aliasframetype_t) LittleLong (pframetype->type) == ALIAS_SINGLE)
+ {
+ numposes++;
+ pframetype = (daliasframetype_t *)((int)pframetype + sizeof(daliasframetype_t) + (sizeof(daliasframe_t) + sizeof(trivertx_t) * numverts) );
+ }
+ else
+ {
+ f = LittleLong (((daliasgroup_t *)((int)pframetype + sizeof(daliasframetype_t)))->numframes);
+ numposes += f;
+ pframetype = (daliasframetype_t *)((int)pframetype + sizeof(daliasframetype_t) + sizeof(daliasgroup_t) + (sizeof(daliasframe_t) + sizeof(daliasinterval_t) + sizeof(trivertx_t) * numverts) * f);
+ }
+ }
+
+ // rebuild the model
+ mheader = Hunk_AllocName (sizeof(maliashdr_t), loadname);
mod->flags = LittleLong (pinmodel->flags);
mod->type = mod_alias;
-
// endian-adjust and copy the data, starting with the alias model header
- pheader->boundingradius = LittleFloat (pinmodel->boundingradius);
- BOUNDF(pheader->boundingradius,0,65536);
- pheader->numskins = LittleLong (pinmodel->numskins);
- BOUNDI(pheader->numskins,0,256);
- pheader->skinwidth = LittleLong (pinmodel->skinwidth);
- BOUNDI(pheader->skinwidth,0,4096);
- pheader->skinheight = LittleLong (pinmodel->skinheight);
- BOUNDI(pheader->skinheight,0,1024);
-//LordHavoc: 32bit textures
- bytesperpixel = version == ALIAS32_VERSION ? 4 : 1;
-
-// if (pheader->skinheight > MAX_LBM_HEIGHT)
-// Host_Error ("model %s has a skin taller than %d", mod->name, MAX_LBM_HEIGHT);
-
- pheader->numverts = LittleLong (pinmodel->numverts);
- BOUNDI(pheader->numverts,0,MAXALIASVERTS);
- /*
- if (pheader->numverts <= 0)
- Host_Error ("model %s has no vertices", mod->name);
- if (pheader->numverts > MAXALIASVERTS)
- Host_Error ("model %s has too many vertices", mod->name);
- */
-
- pheader->numtris = LittleLong (pinmodel->numtris);
- BOUNDI(pheader->numtris,0,65536);
-// if (pheader->numtris <= 0)
-// Host_Error ("model %s has no triangles", mod->name);
-
- pheader->numframes = LittleLong (pinmodel->numframes);
- BOUNDI(pheader->numframes,0,65536);
- numframes = pheader->numframes;
-// if (numframes < 1)
-// Host_Error ("Mod_LoadAliasModel: Invalid # of frames: %d\n", numframes);
-
- pheader->size = LittleFloat (pinmodel->size) * ALIAS_BASE_SIZE_RATIO;
- BOUNDF(pheader->size,0,65536);
+ mheader->numverts = numverts;
+ mod->numtris = mheader->numtris = numtris;
+ mod->numframes = mheader->numframes = numframes;
mod->synctype = LittleLong (pinmodel->synctype);
- BOUNDI(pheader->synctype,0,2);
- mod->numframes = pheader->numframes;
+ BOUNDI(mod->synctype,0,2);
for (i=0 ; i<3 ; i++)
{
- pheader->scale[i] = LittleFloat (pinmodel->scale[i]);
- BOUNDF(pheader->scale[i],0,65536);
- pheader->scale_origin[i] = LittleFloat (pinmodel->scale_origin[i]);
- BOUNDF(pheader->scale_origin[i],-65536,65536);
- pheader->eyeposition[i] = LittleFloat (pinmodel->eyeposition[i]);
- BOUNDF(pheader->eyeposition[i],-65536,65536);
+ mheader->scale[i] = LittleFloat (pinmodel->scale[i]);
+ BOUNDF(mheader->scale[i],0,65536);
+ mheader->scale_origin[i] = LittleFloat (pinmodel->scale_origin[i]);
+ BOUNDF(mheader->scale_origin[i],-65536,65536);
}
-// load the skins
+ // load the skins
pskintype = (daliasskintype_t *)&pinmodel[1];
- pskintype = Mod_LoadAllSkins (pheader->numskins, pskintype, bytesperpixel);
+ pskintype = Mod_LoadAllSkins(numskins, pskintype, skinwidth, skinheight);
-// load base s and t vertices
+ // store texture coordinates into temporary array, they will be stored after usage is determined (triangle data)
pinstverts = (stvert_t *)pskintype;
- pouttexcoords = (float *)&pheader->frames[numframes];
- pheader->texcoords = (int) pouttexcoords - (int) pheader;
// LordHavoc: byteswap and convert stvert data
- scales = 1.0 / pheader->skinwidth;
- scalet = 1.0 / pheader->skinheight;
- for (i = 0;i < pheader->numverts;i++)
+ scales = 1.0 / skinwidth;
+ scalet = 1.0 / skinheight;
+ for (i = 0;i < numverts;i++)
{
- pouttexcoords[i*2] = LittleLong (pinstverts[i].s) * scales;
- pouttexcoords[i*2+1] = LittleLong (pinstverts[i].t) * scalet;
- pouttexcoords[(i+pheader->numverts)*2] = LittleLong (pinstverts[i].s) * scales + 0.5;
- pouttexcoords[(i+pheader->numverts)*2+1] = LittleLong (pinstverts[i].t) * scalet;
- if (pouttexcoords[i*2] >= 0.5) // already a back side coordinate
- {
- pouttexcoords[i*2] -= 0.5;
- pouttexcoords[(i+pheader->numverts)*2] -= 0.5;
- }
- // LordHavoc: CTF's v_star.mdl failed these checks
-// BOUNDF(pouttexcoords[i*2],0.0,1.0);
-// BOUNDF(pouttexcoords[i*2+1],0.0,1.0);
-// BOUNDF(pouttexcoords[(i+pheader->numverts)*2],0.0,1.0);
-// BOUNDF(pouttexcoords[(i+pheader->numverts)*2+1],0.0,1.0);
+ vertonseam[i] = LittleLong(pinstverts[i].onseam);
+ vertst[i][0] = LittleLong(pinstverts[i].s) * scales;
+ vertst[i][1] = LittleLong(pinstverts[i].t) * scalet;
+ vertst[i+numverts][0] = vertst[i][0] + 0.5;
+ vertst[i+numverts][1] = vertst[i][1];
+ vertusage[i] = 0;
+ vertusage[i+numverts] = 0;
}
// load triangle data
- pintriangles = (dtriangle_t *)&pinstverts[pheader->numverts];
- poutvertindices = (unsigned short *)&pouttexcoords[pheader->numverts*4];
- pheader->vertindices = (int) poutvertindices - (int) pheader;
- // LordHavoc: sort triangles into front and back lists
- // so they can be drawn refering to different texture coordinate arrays,
- // but sharing vertex data
- pheader->frontfaces = 0;
- pheader->backfaces = 0;
- tris = temptris;
- for (i=0 ; i<pheader->numtris ; i++)
+ pouttris = Hunk_AllocName(sizeof(unsigned short[3]) * numtris, loadname);
+ mheader->tridata = (int) pouttris - (int) mheader;
+ pintriangles = (dtriangle_t *)&pinstverts[mheader->numverts];
+
+ // count the vertices used
+ for (i = 0;i < numverts*2;i++)
+ vertusage[i] = 0;
+ for (i = 0;i < numtris;i++)
{
- if (LittleLong(pintriangles[i].facesfront))
+ temptris[i][0] = LittleLong(pintriangles[i].vertindex[0]);
+ temptris[i][1] = LittleLong(pintriangles[i].vertindex[1]);
+ temptris[i][2] = LittleLong(pintriangles[i].vertindex[2]);
+ if (!LittleLong(pintriangles[i].facesfront)) // backface
{
- pheader->frontfaces++;
- for (j=0 ; j<3 ; j++)
- *poutvertindices++ = LittleLong (pintriangles[i].vertindex[j]);
+ if (vertonseam[temptris[i][0]]) temptris[i][0] += numverts;
+ if (vertonseam[temptris[i][1]]) temptris[i][1] += numverts;
+ if (vertonseam[temptris[i][2]]) temptris[i][2] += numverts;
}
- for (j=0 ; j<3 ; j++)
- tris->v[j] = LittleLong (pintriangles[i].vertindex[j]);
- tris++;
+ vertusage[temptris[i][0]]++;
+ vertusage[temptris[i][1]]++;
+ vertusage[temptris[i][2]]++;
}
- for (i=0 ; i<pheader->numtris ; i++)
+ // build remapping table and compact array
+ totalverts = 0;
+ for (i = 0;i < numverts*2;i++)
{
- if (!LittleLong(pintriangles[i].facesfront))
+ if (vertusage[i])
{
- pheader->backfaces++;
- for (j=0 ; j<3 ; j++)
- *poutvertindices++ = LittleLong (pintriangles[i].vertindex[j]);
+ vertremap[i] = totalverts;
+ vertst[totalverts][0] = vertst[i][0];
+ vertst[totalverts][1] = vertst[i][1];
+ totalverts++;
}
+ else
+ vertremap[i] = -1; // not used at all
+ }
+ mheader->numverts = totalverts;
+ // remap the triangle references
+ for (i = 0;i < numtris;i++)
+ {
+ *pouttris++ = vertremap[temptris[i][0]];
+ *pouttris++ = vertremap[temptris[i][1]];
+ *pouttris++ = vertremap[temptris[i][2]];
+ }
+ // store the texture coordinates
+ pouttexcoords = Hunk_AllocName(sizeof(float[2]) * totalverts, loadname);
+ mheader->texdata = (int) pouttexcoords - (int) mheader;
+ for (i = 0;i < totalverts;i++)
+ {
+ *pouttexcoords++ = vertst[i][0];
+ *pouttexcoords++ = vertst[i][1];
}
// load the frames
posenum = 0;
- pheader->posedata = (int) poutvertindices - (int) pheader;
- pframetype = (daliasframetype_t *)&pintriangles[pheader->numtris];
+ frame = Hunk_AllocName(sizeof(maliasframe_t) * numframes, loadname);
+ mheader->framedata = (int) frame - (int) mheader;
+ posevert = Hunk_AllocName(sizeof(trivert2) * numposes * totalverts, loadname);
+ mheader->posedata = (int) posevert - (int) mheader;
+ pframetype = (daliasframetype_t *)&pintriangles[numtris];
// LordHavoc: doing proper bbox for model
aliasbboxmin[0] = aliasbboxmin[1] = aliasbboxmin[2] = 1000000000;
for (i=0 ; i<numframes ; i++)
{
- aliasframetype_t frametype;
-
- frametype = LittleLong (pframetype->type);
-
- if (frametype == ALIAS_SINGLE)
- pframetype = (daliasframetype_t *) Mod_LoadAliasFrame (pframetype + 1, &pheader->frames[i]);
+ if ((aliasframetype_t) LittleLong (pframetype->type) == ALIAS_SINGLE)
+ pframetype = (daliasframetype_t *) Mod_LoadAliasFrame (pframetype + 1, frame++, mheader, numverts, totalverts, &posevert);
else
- pframetype = (daliasframetype_t *) Mod_LoadAliasGroup (pframetype + 1, &pheader->frames[i]);
+ pframetype = (daliasframetype_t *) Mod_LoadAliasGroup (pframetype + 1, frame++, mheader, numverts, totalverts, &posevert);
}
- pheader->numposes = posenum;
-
// LordHavoc: fixed model bbox - was //FIXME: do this right
//mod->mins[0] = mod->mins[1] = mod->mins[2] = -16;
//mod->maxs[0] = mod->maxs[1] = mod->maxs[2] = 16;
Cache_Alloc (&mod->cache, total, loadname);
if (!mod->cache.data)
return;
- memcpy (mod->cache.data, pheader, total);
+ memcpy (mod->cache.data, mheader, total);
Hunk_FreeToLowMark (start);
}
+void Mod_ConvertQ2AliasVerts (int numverts, vec3_t scale, vec3_t translate, trivertx_t *v, trivert2 *out)
+{
+ int i;
+ vec3_t temp;
+ for (i = 0;i < numverts;i++)
+ {
+ VectorCopy(v[i].v, out[i].v);
+ temp[0] = v[i].v[0] * scale[0] + translate[0];
+ temp[1] = v[i].v[1] * scale[1] + translate[1];
+ temp[2] = v[i].v[2] * scale[2] + translate[2];
+ // update bounding box
+ if (temp[0] < aliasbboxmin[0]) aliasbboxmin[0] = temp[0];
+ if (temp[1] < aliasbboxmin[1]) aliasbboxmin[1] = temp[1];
+ if (temp[2] < aliasbboxmin[2]) aliasbboxmin[2] = temp[2];
+ if (temp[0] > aliasbboxmax[0]) aliasbboxmax[0] = temp[0];
+ if (temp[1] > aliasbboxmax[1]) aliasbboxmax[1] = temp[1];
+ if (temp[2] > aliasbboxmax[2]) aliasbboxmax[2] = temp[2];
+ out[i].n[0] = (signed char) (r_avertexnormals[v[i].lightnormalindex][0] * 127.0);
+ out[i].n[1] = (signed char) (r_avertexnormals[v[i].lightnormalindex][1] * 127.0);
+ out[i].n[2] = (signed char) (r_avertexnormals[v[i].lightnormalindex][2] * 127.0);
+ }
+ /*
+ int i, j;
+ vec3_t t1, t2;
+ struct
+ {
+ vec3_t v;
+ vec3_t normal;
+ int count;
+ } tempvert[MD2MAX_VERTS];
+ temptris_t *tris;
+ // decompress vertices
+ for (i = 0;i < numverts;i++)
+ {
+ VectorCopy(v[i].v, out[i].v);
+ tempvert[i].v[0] = v[i].v[0] * scale[0] + translate[0];
+ tempvert[i].v[1] = v[i].v[1] * scale[1] + translate[1];
+ tempvert[i].v[2] = v[i].v[2] * scale[2] + translate[2];
+ tempvert[i].normal[0] = tempvert[i].normal[1] = tempvert[i].normal[2] = 0;
+ tempvert[i].count = 0;
+ // update bounding box
+ if (tempvert[i].v[0] < aliasbboxmin[0]) aliasbboxmin[0] = tempvert[i].v[0];
+ if (tempvert[i].v[1] < aliasbboxmin[1]) aliasbboxmin[1] = tempvert[i].v[1];
+ if (tempvert[i].v[2] < aliasbboxmin[2]) aliasbboxmin[2] = tempvert[i].v[2];
+ if (tempvert[i].v[0] > aliasbboxmax[0]) aliasbboxmax[0] = tempvert[i].v[0];
+ if (tempvert[i].v[1] > aliasbboxmax[1]) aliasbboxmax[1] = tempvert[i].v[1];
+ if (tempvert[i].v[2] > aliasbboxmax[2]) aliasbboxmax[2] = tempvert[i].v[2];
+ }
+ // calculate surface normals
+ tris = temptris;
+ for (i = 0;i < numtris;i++)
+ {
+ VectorSubtract(tempvert[tris->v[0]].v, tempvert[tris->v[1]].v, t1);
+ VectorSubtract(tempvert[tris->v[2]].v, tempvert[tris->v[1]].v, t2);
+ CrossProduct(t1, t2, tris->normal);
+ VectorNormalize(tris->normal);
+ // add surface normal to vertices
+ for (j = 0;j < 3;j++)
+ {
+ VectorAdd(tris->normal, tempvert[tris->v[j]].normal, tempvert[tris->v[j]].normal);
+ tempvert[tris->v[j]].count++;
+ }
+ tris++;
+ }
+ // average normals and write out 1.7bit format
+ for (i = 0;i < pheader->numtris;i++)
+ {
+ VectorNormalize(tempvert[i].normal);
+ out[i].n[0] = (signed char) (tempvert[i].normal[0] * 127.0);
+ out[i].n[1] = (signed char) (tempvert[i].normal[1] * 127.0);
+ out[i].n[2] = (signed char) (tempvert[i].normal[2] * 127.0);
+ }
+ */
+}
+
/*
=================
Mod_LoadQ2AliasModel
=================
*/
-int loadtextureimage (int texnum, char* filename, qboolean complain, int matchwidth, int matchheight);
void Mod_LoadQ2AliasModel (model_t *mod, void *buffer)
{
int i, j, version, size, *pinglcmd, *poutglcmd, start, end, total, framesize;
md2frame_t *pinframe;
md2memframe_t *poutframe;
char *pinskins;
- temptris_t *tris;
+// temptris_t *tris;
start = Hunk_LowMark ();
- if (!temptris)
- temptris = malloc(sizeof(temptris_t) * MD2MAX_TRIANGLES);
+// if (!temptris)
+// temptris = malloc(sizeof(temptris_t) * MD2MAX_TRIANGLES);
pinmodel = (md2_t *)buffer;
mod->flags = 0; // there are no MD2 flags
mod->numframes = LittleLong(pinmodel->num_frames);
mod->synctype = ST_RAND;
+ mod->numtris = LittleLong(pinmodel->num_tris); // LordHavoc: to simplify renderer decisions
if (LittleLong(pinmodel->num_skins) >= 1 && (LittleLong(pinmodel->ofs_skins <= 0) || LittleLong(pinmodel->ofs_skins) >= LittleLong(pinmodel->ofs_end)))
Host_Error ("%s is not a valid model", mod->name);
Host_Error ("%s has invalid number of triangles: %i", mod->name, LittleLong(pinmodel->num_tris));
if (LittleLong(pinmodel->num_xyz < 1) || LittleLong(pinmodel->num_xyz) > MD2MAX_VERTS)
Host_Error ("%s has invalid number of vertices: %i", mod->name, LittleLong(pinmodel->num_xyz));
- if (LittleLong(pinmodel->num_frames < 1) || LittleLong(pinmodel->num_frames) > 256) //MD2MAX_FRAMES)
+ if (LittleLong(pinmodel->num_frames < 1) || LittleLong(pinmodel->num_frames) > MD2MAX_FRAMES)
Host_Error ("%s has invalid number of frames: %i", mod->name, LittleLong(pinmodel->num_frames));
if (LittleLong(pinmodel->num_skins < 0) || LittleLong(pinmodel->num_skins) > MD2MAX_SKINS)
Host_Error ("%s has invalid number of skins: %i", mod->name, LittleLong(pinmodel->num_skins));
// load the skins
if (pheader->num_skins)
{
+ int *skin, *skinrange;
+ skinrange = loadmodel->skinanimrange;
+ skin = loadmodel->skinanim;
+// skinrange = Hunk_AllocName (sizeof(int) * (pheader->num_skins * 2), loadname);
+// skin = skinrange + pheader->num_skins * 2;
+// loadmodel->skinanimrange = (int) skinrange - (int) pheader;
+// loadmodel->skinanim = (int) skin - (int) pheader;
pinskins = (void*)((int) pinmodel + LittleLong(pinmodel->ofs_skins));
for (i = 0;i < pheader->num_skins;i++)
{
- pheader->gl_texturenum[i] = loadtextureimage (-1, pinskins, TRUE, 0, 0);
+ *skinrange++ = i;
+ *skinrange++ = 1;
+ *skin++ = loadtextureimage (pinskins, 0, 0, true, true);
+ *skin++ = 0; // the extra 4 layers are currently unused
+ *skin++ = 0;
+ *skin++ = 0;
+ *skin++ = 0;
pinskins += MD2MAX_SKINNAME;
}
}
+ loadmodel->numskins = pheader->num_skins;
// load triangles
pintriangles = (void*)((int) pinmodel + LittleLong(pinmodel->ofs_tris));
pouttriangles = (void*)&pheader[1];
pheader->ofs_tris = (int) pouttriangles - (int) pheader;
- tris = temptris;
+// tris = temptris;
// swap the triangle list
for (i=0 ; i<pheader->num_tris ; i++)
{
for (j=0 ; j<3 ; j++)
{
- tris->v[j] = pouttriangles->index_xyz[j] = LittleShort (pintriangles->index_xyz[j]);
+ temptris[i][j] = pouttriangles->index_xyz[j] = LittleShort (pintriangles->index_xyz[j]);
pouttriangles->index_st[j] = LittleShort (pintriangles->index_st[j]);
if (pouttriangles->index_xyz[j] >= pheader->num_xyz)
Host_Error ("%s has invalid vertex indices", mod->name);
}
pintriangles++;
pouttriangles++;
- tris++;
}
// LordHavoc: doing proper bbox for model
poutframe->scale[j] = LittleFloat(pinframe->scale[j]);
poutframe->translate[j] = LittleFloat(pinframe->translate[j]);
}
- Mod_ConvertAliasVerts (pheader->num_xyz, pheader->num_tris, poutframe->scale, poutframe->translate, &pinframe->verts[0], &poutframe->verts[0]);
+ Mod_ConvertQ2AliasVerts (pheader->num_xyz, poutframe->scale, poutframe->translate, &pinframe->verts[0], &poutframe->verts[0]);
pinframe = (void*) &pinframe->verts[j];
poutframe = (void*) &poutframe->verts[j];
}
#include "modelgen.h"
+/*
typedef struct
{
int firstpose;
maliasgroupframedesc_t frames[1];
} maliasgroup_t;
-// !!! if this is changed, it must be changed in asm_draw.h too !!!
typedef struct mtriangle_s {
int facesfront;
int vertindex[3];
} mtriangle_t;
+*/
// LordHavoc: new vertex format
typedef struct {
synctype_t synctype;
int flags;
float size;
+} daliashdr_t;
- int numposes;
- int posedata; // LordHavoc: numposes*numverts*trivert2
- int frontfaces; // LordHavoc: how many front faces
- int backfaces; // LordHavoc: how many back faces
-// int poseverts;
-// int posedata; // numposes*poseverts trivert_t
-// int commands; // gl command list with embedded s/t
- int texcoords; // LordHavoc: texture coordinates
- int vertindices; // LordHavoc: vertex numbers
- int gl_texturenum[MAX_SKINS][4];
- int texels[MAX_SKINS]; // only for player skins
- maliasframedesc_t frames[1]; // variable sized
-} aliashdr_t;
+typedef struct
+{
+ char name[16]; // LordHavoc: only kept this for reasons of viewthing support
+ unsigned short start;
+ unsigned short length;
+ float rate; // in poses per second
+} maliasframe_t;
+
+typedef struct
+{
+ vec3_t scale;
+ vec3_t scale_origin;
+ int numverts;
+ int numtris;
+ int numframes;
+ int numposes;
+ int framedata; // LordHavoc: unsigned short start
+ int texdata; // LordHavoc: texture coordinate array
+ int posedata; // LordHavoc: vertex data for all the poses
+ int tridata; // LordHavoc: vertex indices for the triangles
+} maliashdr_t;
#define MAXALIASVERTS 4096
#define MAXALIASFRAMES 1024
#define MAXALIASTRIS 4096
-extern aliashdr_t *pheader;
-//extern stvert_t stverts[MAXALIASVERTS];
-//extern mtriangle_t triangles[MAXALIASTRIS];
-//extern trivertx_t *poseverts[MAXALIASFRAMES];
-
/*
========================================================================
float scale[3]; // multiply byte verts by this
float translate[3]; // then add this
char name[16]; // frame name from grabbing
- trivertx_t verts[0]; // variable sized
+ trivertx_t verts[]; // variable sized
} md2frame_t;
// LordHavoc: memory representation is different than disk
{
float scale[3]; // multiply byte verts by this
float translate[3]; // then add this
- trivert2 verts[0]; // variable sized
+ trivert2 verts[]; // variable sized
} md2memframe_t;
int ofs_tris; // offset for dtriangles
int ofs_frames; // offset for first frame
int ofs_glcmds;
-
- int gl_texturenum[MAX_SKINS];
} md2mem_t;
#define ALIASTYPE_MDL 1
loadmodel->clipnodes = out;
loadmodel->numclipnodes = count;
- 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 = &loadmodel->hulls[2];
- hull->clipnodes = out;
- hull->firstclipnode = 0;
- hull->lastclipnode = count-1;
- hull->planes = loadmodel->planes;
- hull->clip_mins[0] = -32;
- hull->clip_mins[1] = -32;
- hull->clip_mins[2] = -24;
- hull->clip_maxs[0] = 32;
- hull->clip_maxs[1] = 32;
- hull->clip_maxs[2] = 64;
+ if (hlbsp)
+ {
+ 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] = -36;
+ hull->clip_maxs[0] = 16;
+ hull->clip_maxs[1] = 16;
+ hull->clip_maxs[2] = 36;
+
+ hull = &loadmodel->hulls[2];
+ hull->clipnodes = out;
+ hull->firstclipnode = 0;
+ hull->lastclipnode = count-1;
+ hull->planes = loadmodel->planes;
+ hull->clip_mins[0] = -32;
+ hull->clip_mins[1] = -32;
+ hull->clip_mins[2] = -32;
+ hull->clip_maxs[0] = 32;
+ hull->clip_maxs[1] = 32;
+ hull->clip_maxs[2] = 32;
+
+ 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] = -18;
+ hull->clip_maxs[0] = 16;
+ hull->clip_maxs[1] = 16;
+ hull->clip_maxs[2] = 18;
+ }
+ else
+ {
+ 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 = &loadmodel->hulls[2];
+ hull->clipnodes = out;
+ hull->firstclipnode = 0;
+ hull->lastclipnode = count-1;
+ hull->planes = loadmodel->planes;
+ hull->clip_mins[0] = -32;
+ hull->clip_mins[1] = -32;
+ hull->clip_mins[2] = -24;
+ hull->clip_maxs[0] = 32;
+ hull->clip_maxs[1] = 32;
+ hull->clip_maxs[2] = 64;
+ }
for (i=0 ; i<count ; i++, out++, in++)
{
{
void *d;
unsigned *buf;
- byte stackbuf[1024]; // avoid dirtying the cache heap
+// byte stackbuf[1024]; // avoid dirtying the cache heap
if (!mod->needload)
{
}
// load the file
- buf = (unsigned *)COM_LoadStackFile (mod->name, stackbuf, sizeof(stackbuf), false);
+ buf = (unsigned *)COM_LoadMallocFile (mod->name, false);
+// buf = (unsigned *)COM_LoadStackFile (mod->name, stackbuf, sizeof(stackbuf), false);
if (!buf)
{
if (crash)
Mod_LoadBrushModel (mod, buf);
break;
}
+ free(buf);
return mod;
}
byte *lightdata;
char *entities;
+ // LordHavoc: useful for sprites and models
+ int numtris;
+ int numskins;
+ int skinanimrange[1024]; // array of start and length pairs, note: offset from ->cache.data
+ int skinanim[1024*5]; // texture numbers for each frame (indexed by animrange), note: offset from ->cache.data, second note: normal pants shirt glow body (normal contains no shirt/pants/glow colors and body is normal + pants + shirt, but not glow)
+
// additional model data
cache_user_t cache; // only access through Mod_Extradata
// *********************************************************
#define ALIAS_VERSION 6
-#define ALIAS32_VERSION 7
#define ALIAS_ONSEAM 0x0020
if (hInst == NULL)
{
- Con_SafePrintf ("Failed to load winsock.dll\n");
+ Con_SafePrintf ("Failed to load wsock32.dll\n");
winsock_lib_initialized = false;
return -1;
}
!pgethostname || !pgethostbyname || !pgethostbyaddr ||
!pgetsockname)
{
- Con_SafePrintf ("Couldn't GetProcAddress from winsock.dll\n");
+ Con_SafePrintf ("Couldn't GetProcAddress from wsock32.dll\n");
return -1;
}
PR_ExecuteProgram
====================
*/
-/*
-void PR_ExecuteProgram (func_t fnum)
-{
- eval_t *a, *b, *c;
- int s;
- dstatement_t *st;
- dfunction_t *f, *newf;
- int runaway;
- int i;
- edict_t *ed;
- int exitdepth;
- eval_t *ptr;
-
- if (!fnum || fnum >= progs->numfunctions)
- {
- if (pr_global_struct->self)
- ED_Print (PROG_TO_EDICT(pr_global_struct->self));
- Host_Error ("PR_ExecuteProgram: NULL function");
- }
-
- f = &pr_functions[fnum];
-
- runaway = 100000;
- pr_trace = false;
-
-// make a stack frame
- exitdepth = pr_depth;
-
- s = PR_EnterFunction (f);
-
-while (1)
-{
- s++; // next statement
-
- st = &pr_statements[s];
- // LordHavoc: fix for 32768 QC def limit (just added unsigned short typecast)
- a = (eval_t *)&pr_globals[(unsigned short) st->a];
- b = (eval_t *)&pr_globals[(unsigned short) st->b];
- c = (eval_t *)&pr_globals[(unsigned short) st->c];
-
- if (!--runaway)
- PR_RunError ("runaway loop error");
-
- pr_xfunction->profile++;
- pr_xstatement = s;
-
- if (pr_trace)
- PR_PrintStatement (st);
-
- switch (st->op)
- {
- case OP_ADD_F:
- c->_float = a->_float + b->_float;
- break;
- case OP_ADD_V:
- c->vector[0] = a->vector[0] + b->vector[0];
- c->vector[1] = a->vector[1] + b->vector[1];
- c->vector[2] = a->vector[2] + b->vector[2];
- break;
-
- case OP_SUB_F:
- c->_float = a->_float - b->_float;
- break;
- case OP_SUB_V:
- c->vector[0] = a->vector[0] - b->vector[0];
- c->vector[1] = a->vector[1] - b->vector[1];
- c->vector[2] = a->vector[2] - b->vector[2];
- break;
-
- case OP_MUL_F:
- c->_float = a->_float * b->_float;
- break;
- case OP_MUL_V:
- c->_float = a->vector[0]*b->vector[0]
- + a->vector[1]*b->vector[1]
- + a->vector[2]*b->vector[2];
- break;
- case OP_MUL_FV:
- c->vector[0] = a->_float * b->vector[0];
- c->vector[1] = a->_float * b->vector[1];
- c->vector[2] = a->_float * b->vector[2];
- break;
- case OP_MUL_VF:
- c->vector[0] = b->_float * a->vector[0];
- c->vector[1] = b->_float * a->vector[1];
- c->vector[2] = b->_float * a->vector[2];
- break;
-
- case OP_DIV_F:
- c->_float = a->_float / b->_float;
- break;
-
- case OP_BITAND:
- c->_float = (int)a->_float & (int)b->_float;
- break;
-
- case OP_BITOR:
- c->_float = (int)a->_float | (int)b->_float;
- break;
-
-
- case OP_GE:
- c->_float = a->_float >= b->_float;
- break;
- case OP_LE:
- c->_float = a->_float <= b->_float;
- break;
- case OP_GT:
- c->_float = a->_float > b->_float;
- break;
- case OP_LT:
- c->_float = a->_float < b->_float;
- break;
- case OP_AND:
- c->_float = a->_float && b->_float;
- break;
- case OP_OR:
- c->_float = a->_float || b->_float;
- break;
-
- case OP_NOT_F:
- c->_float = !a->_float;
- break;
- case OP_NOT_V:
- c->_float = !a->vector[0] && !a->vector[1] && !a->vector[2];
- break;
- case OP_NOT_S:
- c->_float = !a->string || !pr_strings[a->string];
- break;
- case OP_NOT_FNC:
- c->_float = !a->function;
- break;
- case OP_NOT_ENT:
- c->_float = (PROG_TO_EDICT(a->edict) == sv.edicts);
- break;
-
- case OP_EQ_F:
- c->_float = a->_float == b->_float;
- break;
- case OP_EQ_V:
- c->_float = (a->vector[0] == b->vector[0]) &&
- (a->vector[1] == b->vector[1]) &&
- (a->vector[2] == b->vector[2]);
- break;
- case OP_EQ_S:
- c->_float = !strcmp(pr_strings+a->string,pr_strings+b->string);
- break;
- case OP_EQ_E:
- c->_float = a->_int == b->_int;
- break;
- case OP_EQ_FNC:
- c->_float = a->function == b->function;
- break;
-
-
- case OP_NE_F:
- c->_float = a->_float != b->_float;
- break;
- case OP_NE_V:
- c->_float = (a->vector[0] != b->vector[0]) ||
- (a->vector[1] != b->vector[1]) ||
- (a->vector[2] != b->vector[2]);
- break;
- case OP_NE_S:
- c->_float = strcmp(pr_strings+a->string,pr_strings+b->string);
- break;
- case OP_NE_E:
- c->_float = a->_int != b->_int;
- break;
- case OP_NE_FNC:
- c->_float = a->function != b->function;
- break;
-
-//==================
- case OP_STORE_F:
- case OP_STORE_ENT:
- case OP_STORE_FLD: // integers
- case OP_STORE_S:
- case OP_STORE_FNC: // pointers
- b->_int = a->_int;
- break;
- case OP_STORE_V:
- b->vector[0] = a->vector[0];
- b->vector[1] = a->vector[1];
- b->vector[2] = a->vector[2];
- break;
-
- case OP_STOREP_F:
- case OP_STOREP_ENT:
- case OP_STOREP_FLD: // integers
- case OP_STOREP_S:
- case OP_STOREP_FNC: // pointers
- ptr = (eval_t *)((byte *)sv.edicts + b->_int);
- ptr->_int = a->_int;
- break;
- case OP_STOREP_V:
- ptr = (eval_t *)((byte *)sv.edicts + b->_int);
- ptr->vector[0] = a->vector[0];
- ptr->vector[1] = a->vector[1];
- ptr->vector[2] = a->vector[2];
- break;
-
- case OP_ADDRESS:
- ed = PROG_TO_EDICT(a->edict);
-#ifdef PARANOID
- NUM_FOR_EDICT(ed); // make sure it's in range
-#endif
- if (ed == (edict_t *)sv.edicts && sv.state == ss_active)
- PR_RunError ("assignment to world entity");
- c->_int = (byte *)((int *)&ed->v + b->_int) - (byte *)sv.edicts;
- break;
-
- case OP_LOAD_F:
- case OP_LOAD_FLD:
- case OP_LOAD_ENT:
- case OP_LOAD_S:
- case OP_LOAD_FNC:
- ed = PROG_TO_EDICT(a->edict);
-#ifdef PARANOID
- NUM_FOR_EDICT(ed); // make sure it's in range
-#endif
- a = (eval_t *)((int *)&ed->v + b->_int);
- c->_int = a->_int;
- break;
-
- case OP_LOAD_V:
- ed = PROG_TO_EDICT(a->edict);
-#ifdef PARANOID
- NUM_FOR_EDICT(ed); // make sure it's in range
-#endif
- a = (eval_t *)((int *)&ed->v + b->_int);
- c->vector[0] = a->vector[0];
- c->vector[1] = a->vector[1];
- c->vector[2] = a->vector[2];
- break;
-
-//==================
-
- case OP_IFNOT:
- if (!a->_int)
- s += st->b - 1; // offset the s++
- break;
-
- case OP_IF:
- if (a->_int)
- s += st->b - 1; // offset the s++
- break;
-
- case OP_GOTO:
- s += st->a - 1; // offset the s++
- break;
-
- case OP_CALL0:
- case OP_CALL1:
- case OP_CALL2:
- case OP_CALL3:
- case OP_CALL4:
- case OP_CALL5:
- case OP_CALL6:
- case OP_CALL7:
- case OP_CALL8:
- pr_argc = st->op - OP_CALL0;
- if (!a->function)
- PR_RunError ("NULL function");
-
- newf = &pr_functions[a->function];
-
- if (newf->first_statement < 0)
- { // negative statements are built in functions
- i = -newf->first_statement;
- if (i >= pr_numbuiltins)
- PR_RunError ("Bad builtin call number");
- pr_builtins[i] ();
- break;
- }
-
- s = PR_EnterFunction (newf);
- break;
-
- case OP_DONE:
- case OP_RETURN:
- pr_globals[OFS_RETURN] = pr_globals[st->a];
- pr_globals[OFS_RETURN+1] = pr_globals[st->a+1];
- pr_globals[OFS_RETURN+2] = pr_globals[st->a+2];
-
- s = PR_LeaveFunction ();
- if (pr_depth == exitdepth)
- return; // all done
- break;
-
- case OP_STATE:
- ed = PROG_TO_EDICT(pr_global_struct->self);
-#ifdef FPS_20
- ed->v.nextthink = pr_global_struct->time + 0.05;
-#else
- ed->v.nextthink = pr_global_struct->time + 0.1;
-#endif
- //if (a->_float != ed->v.frame) // LordHavoc: this was silly
- //{
- ed->v.frame = a->_float;
- //}
- ed->v.think = b->function;
- break;
-
- default:
- PR_RunError ("Bad opcode %i", st->op);
- }
-}
-
-}
-*/
-
// LordHavoc: optimized
#define OPA ((eval_t *)&pr_globals[(unsigned short) st->a])
#define OPB ((eval_t *)&pr_globals[(unsigned short) st->b])
while (1)
{
st++;
- if (++profile > 1000000) // LordHavoc: increased runaway loop limited 10x
+ if (++profile > 1000000) // LordHavoc: increased runaway loop limit 10x
{
pr_xstatement = st - pr_statements;
PR_RunError ("runaway loop error");
case OP_STATE:
ed = PROG_TO_EDICT(pr_global_struct->self);
- #ifdef FPS_20
- ed->v.nextthink = pr_global_struct->time + 0.05;
- #else
ed->v.nextthink = pr_global_struct->time + 0.1;
- #endif
ed->v.frame = OPA->_float;
ed->v.think = OPB->function;
break;
while (1)
{
st++;
- if (++profile > 1000000) // LordHavoc: increased runaway loop limited 10x
+ if (++profile > 1000000) // LordHavoc: increased runaway loop limit 10x
{
pr_xstatement = st - pr_statements;
PR_RunError ("runaway loop error");
case OP_STATE:
ed = PROG_TO_EDICT(pr_global_struct->self);
- #ifdef FPS_20
- ed->v.nextthink = pr_global_struct->time + 0.05;
- #else
ed->v.nextthink = pr_global_struct->time + 0.1;
- #endif
ed->v.frame = OPA->_float;
ed->v.think = OPB->function;
break;
*/
// quakedef.h -- primary header for client
-//#define GLTEST // experimental stuff
-
#define QUAKE_GAME // as opposed to utilities
-#define VERSION 1.05
+#define VERSION 1.50
#ifndef FALSE
#define FALSE 0
#endif
//define PARANOID // speed sapping error checking
+#ifdef _DEBUG
+#define ASSERT(condition) if (!(condition)) Sys_Error("assertion (##condition) failed at " __FILE__ ":" __LINE__ "\n");
+#else
+#define ASSERT(condition)
+#endif
#define GAMENAME "id1"
extern qboolean host_initialized; // true if into command execution
extern double host_frametime;
extern byte *host_basepal;
-extern byte *host_colormap;
extern int host_framecount; // incremented every frame, never reset
extern double realtime; // not bounded in any way, changed at
// start of every frame, never reset
void Chase_Init (void);
void Chase_Reset (void);
void Chase_Update (void);
+
+void fractalnoise(unsigned char *noise, int size);
+
+#include "image.h"
--- /dev/null
+#include "quakedef.h"
+
+cvar_t crosshair_brightness = {"crosshair_brightness", "1.0", true};
+cvar_t crosshair_alpha = {"crosshair_alpha", "1.0", true};
+cvar_t crosshair_flashspeed = {"crosshair_flashspeed", "2", true};
+cvar_t crosshair_flashrange = {"crosshair_flashrange", "0.1", true};
+
+#define NUMCROSSHAIRS 1
+
+int crosshairtex[NUMCROSSHAIRS];
+
+char crosshairtex1[16*16] =
+ "0000000000000000"
+ "0000000000000000"
+ "0000000000000000"
+ "0003000000003000"
+ "0000500000050000"
+ "0000070000700000"
+ "0000007007000000"
+ "0000000000000000"
+ "0000000000000000"
+ "0000007007000000"
+ "0000070000700000"
+ "0000500000050000"
+ "0003000000003000"
+ "0000000000000000"
+ "0000000000000000"
+ "0000000000000000"
+;
+
+void r_crosshairs_start()
+{
+ int i;
+ byte data[64*64][4];
+ for (i = 0;i < 16*16;i++)
+ {
+ data[i][0] = data[i][1] = data[i][2] = 255;
+ data[i][3] = (crosshairtex1[i] - '0') * 255 / 7;
+ }
+ crosshairtex[0] = GL_LoadTexture("crosshair0", 16, 16, &data[0][0], false, true, 4);
+}
+
+void r_crosshairs_shutdown()
+{
+}
+
+void R_Crosshairs_Init()
+{
+ Cvar_RegisterVariable(&crosshair_brightness);
+ Cvar_RegisterVariable(&crosshair_alpha);
+ Cvar_RegisterVariable(&crosshair_flashspeed);
+ Cvar_RegisterVariable(&crosshair_flashrange);
+ R_RegisterModule("R_Crosshairs", r_crosshairs_start, r_crosshairs_shutdown);
+}
+
+void DrawCrosshair(int num)
+{
+ byte *color;
+ float scale, base;
+// Draw_Character (r_refdef.vrect.x + r_refdef.vrect.width/2, r_refdef.vrect.y + r_refdef.vrect.height/2, '+');
+ if (num < 0 || num >= NUMCROSSHAIRS)
+ num = 0;
+ if (cl.viewentity)
+ {
+ int i = (cl.scores[cl.viewentity-1].colors & 0xF) << 4;
+ if (i >= 208 && i < 224) // blue
+ i += 8;
+ else if (i < 128 || i >= 224) // 128-224 are backwards ranges (bright to dark, rather than dark to bright)
+ i += 15;
+ color = (byte *) &d_8to24table[i];
+ }
+ else
+ color = (byte *) &d_8to24table[15];
+ if (crosshair_flashspeed.value >= 0.01f)
+// scale = (sin(realtime * crosshair_flashspeed.value * (M_PI*2.0f)) * crosshair_flashrange.value + 1.0f) * (1.0f / 255.0f);
+ base = (sin(realtime * crosshair_flashspeed.value * (M_PI*2.0f)) * crosshair_flashrange.value);
+ else
+ base = 0.0f;
+ scale = crosshair_brightness.value / 255.0f;
+ Draw_GenericPic(crosshairtex[num], color[0] * scale + base, color[1] * scale + base, color[2] * scale + base, crosshair_alpha.value, r_refdef.vrect.x + r_refdef.vrect.width * 0.5f - 8.0f, r_refdef.vrect.y + r_refdef.vrect.height * 0.5f - 8.0f, 16.0f, 16.0f);
+}
+
cvar_t r_lightmodels = {"r_lightmodels", "1"};
-void rlight_init()
+void r_light_start()
+{
+}
+
+void r_light_shutdown()
+{
+}
+
+void R_Light_Init()
{
Cvar_RegisterVariable(&r_lightmodels);
+ R_RegisterModule("R_Light", r_light_start, r_light_shutdown);
}
int r_dlightframecount;
R_OldMarkLights(lightorigin, light, bit, bitindex, model->nodes + model->hulls[0].firstclipnode);
}
+int lightframe = 0;
void R_VisMarkLights (vec3_t lightorigin, dlight_t *light, int bit, int bitindex, model_t *model)
{
mleaf_t *pvsleaf = Mod_PointInLeaf (lightorigin, model);
int i, k, l, m, c;
msurface_t *surf, **mark;
mleaf_t *leaf;
- static int lightframe = 0;
byte *in = pvsleaf->compressed_vis;
int row = (model->numleafs+7)>>3;
float low[3], high[3], radius;
if (leaf->contents == CONTENTS_SOLID)
continue;
// if out of the light radius, skip
+ /*
if (leaf->minmaxs[0] > high[0] || leaf->minmaxs[3] < low[0]
|| leaf->minmaxs[1] > high[1] || leaf->minmaxs[4] < low[1]
|| leaf->minmaxs[2] > high[2] || leaf->minmaxs[5] < low[2])
continue;
+ */
if (leaf->dlightframe != r_dlightframecount) // not dynamic until now
{
leaf->dlightbits[0] = leaf->dlightbits[1] = leaf->dlightbits[2] = leaf->dlightbits[3] = leaf->dlightbits[4] = leaf->dlightbits[5] = leaf->dlightbits[6] = leaf->dlightbits[7] = 0;
if (surf->visframe != r_framecount || surf->lightframe == lightframe)
continue;
surf->lightframe = lightframe;
- if (((surf->flags & SURF_PLANEBACK) == 0) == ((PlaneDiff(lightorigin, surf->plane)) >= 0))
+ //if (((surf->flags & SURF_PLANEBACK) == 0) == ((PlaneDiff(lightorigin, surf->plane)) >= 0))
{
if (surf->dlightframe != r_dlightframecount) // not dynamic until now
{
extern cvar_t r_ambient;
+/*
int RecursiveLightPoint (vec3_t color, mnode_t *node, vec3_t start, vec3_t end)
{
float front, back, frac;
color[0] = color[1] = color[2] = 255;
return;
}
+
+ end[0] = p[0];
+ end[1] = p[1];
+ end[2] = p[2] - 2048;
+
+ color[0] = color[1] = color[2] = r_ambient.value * 2.0f;
+ RecursiveLightPoint (color, cl.worldmodel->nodes, p, end);
+}
+
+void SV_LightPoint (vec3_t color, vec3_t p)
+{
+ vec3_t end;
+
+ if (!sv.worldmodel->lightdata)
+ {
+ color[0] = color[1] = color[2] = 255;
+ return;
+ }
end[0] = p[0];
end[1] = p[1];
end[2] = p[2] - 2048;
+ color[0] = color[1] = color[2] = 0;
+ RecursiveLightPoint (color, sv.worldmodel->nodes, p, end);
+}
+*/
+
+int RecursiveLightPoint (vec3_t color, mnode_t *node, float x, float y, float startz, float endz)
+{
+ int side, distz = endz - startz;
+ float front, back;
+ float mid;
+
+loc0:
+ if (node->contents < 0)
+ return false; // didn't hit anything
+
+ switch (node->plane->type)
+ {
+ case PLANE_X:
+ node = node->children[x < node->plane->dist];
+ goto loc0;
+ case PLANE_Y:
+ node = node->children[y < node->plane->dist];
+ goto loc0;
+ case PLANE_Z:
+ side = startz < node->plane->dist;
+ if ((endz < node->plane->dist) == side)
+ {
+ node = node->children[side];
+ goto loc0;
+ }
+ // found an intersection
+// mid = startz + (endz - startz) * (startz - node->plane->dist) / (startz - endz);
+// mid = startz + distz * (startz - node->plane->dist) / (-distz);
+// mid = startz + (-(startz - node->plane->dist));
+// mid = startz - (startz - node->plane->dist);
+// mid = startz + node->plane->dist - startz;
+ mid = node->plane->dist;
+ break;
+ default:
+ back = front = x * node->plane->normal[0] + y * node->plane->normal[1];
+ front += startz * node->plane->normal[2];
+ back += endz * node->plane->normal[2];
+ side = front < node->plane->dist;
+ if ((back < node->plane->dist) == side)
+ {
+ node = node->children[side];
+ goto loc0;
+ }
+ // found an intersection
+// mid = startz + (endz - startz) * ((front - node->plane->dist) / ((front - node->plane->dist) - (back - node->plane->dist)));
+// mid = startz + (endz - startz) * ((front - node->plane->dist) / (front - back));
+ mid = startz + distz * (front - node->plane->dist) / (front - back);
+ break;
+ }
+
+ // go down front side
+ if (node->children[side]->contents >= 0 && RecursiveLightPoint (color, node->children[side], x, y, startz, mid))
+ return true; // hit something
+ else
+ {
+ // check for impact on this node
+ if (node->numsurfaces)
+ {
+ int i, ds, dt;
+ msurface_t *surf;
+ lightspot[0] = x;
+ lightspot[1] = y;
+ lightspot[2] = mid;
+ lightplane = node->plane;
+
+ surf = cl.worldmodel->surfaces + node->firstsurface;
+ for (i = 0;i < node->numsurfaces;i++, surf++)
+ {
+ if (surf->flags & SURF_DRAWTILED)
+ continue; // no lightmaps
+
+ ds = (int) (x * surf->texinfo->vecs[0][0] + y * surf->texinfo->vecs[0][1] + mid * surf->texinfo->vecs[0][2] + surf->texinfo->vecs[0][3]);
+ dt = (int) (x * surf->texinfo->vecs[1][0] + y * surf->texinfo->vecs[1][1] + mid * surf->texinfo->vecs[1][2] + surf->texinfo->vecs[1][3]);
+
+ if (ds < surf->texturemins[0] || dt < surf->texturemins[1])
+ continue;
+
+ ds -= surf->texturemins[0];
+ dt -= surf->texturemins[1];
+
+ if (ds > surf->extents[0] || dt > surf->extents[1])
+ continue;
+
+ if (surf->samples)
+ {
+ byte *lightmap;
+ int maps, line3, size3, dsfrac = ds & 15, dtfrac = dt & 15, scale = 0, r00 = 0, g00 = 0, b00 = 0, r01 = 0, g01 = 0, b01 = 0, r10 = 0, g10 = 0, b10 = 0, r11 = 0, g11 = 0, b11 = 0;
+ line3 = ((surf->extents[0]>>4)+1)*3;
+ size3 = ((surf->extents[0]>>4)+1) * ((surf->extents[1]>>4)+1)*3; // LordHavoc: *3 for colored lighting
+
+ lightmap = surf->samples + ((dt>>4) * ((surf->extents[0]>>4)+1) + (ds>>4))*3; // LordHavoc: *3 for color
+
+ for (maps = 0;maps < MAXLIGHTMAPS && surf->styles[maps] != 255;maps++)
+ {
+ scale = d_lightstylevalue[surf->styles[maps]];
+ r00 += lightmap[ 0] * scale;g00 += lightmap[ 1] * scale;b00 += lightmap[ 2] * scale;
+ r01 += lightmap[ 3] * scale;g01 += lightmap[ 4] * scale;b01 += lightmap[ 5] * scale;
+ r10 += lightmap[line3+0] * scale;g10 += lightmap[line3+1] * scale;b10 += lightmap[line3+2] * scale;
+ r11 += lightmap[line3+3] * scale;g11 += lightmap[line3+4] * scale;b11 += lightmap[line3+5] * scale;
+ lightmap += size3;
+ }
+
+ color[0] += (float) ((((((((r11-r10) * dsfrac) >> 4) + r10)-((((r01-r00) * dsfrac) >> 4) + r00)) * dtfrac) >> 4) + ((((r01-r00) * dsfrac) >> 4) + r00)) * (1.0f / 256.0f);
+ color[1] += (float) ((((((((g11-g10) * dsfrac) >> 4) + g10)-((((g01-g00) * dsfrac) >> 4) + g00)) * dtfrac) >> 4) + ((((g01-g00) * dsfrac) >> 4) + g00)) * (1.0f / 256.0f);
+ color[2] += (float) ((((((((b11-b10) * dsfrac) >> 4) + b10)-((((b01-b00) * dsfrac) >> 4) + b00)) * dtfrac) >> 4) + ((((b01-b00) * dsfrac) >> 4) + b00)) * (1.0f / 256.0f);
+ }
+ return true; // success
+ }
+ }
+
+ // go down back side
+ node = node->children[side ^ 1];
+ startz = mid;
+ distz = endz - startz;
+ goto loc0;
+// return RecursiveLightPoint (color, node->children[side ^ 1], x, y, mid, endz);
+ }
+}
+
+void R_LightPoint (vec3_t color, vec3_t p)
+{
+ if (r_fullbright.value || !cl.worldmodel->lightdata)
+ {
+ color[0] = color[1] = color[2] = 255;
+ return;
+ }
+
color[0] = color[1] = color[2] = r_ambient.value * 2.0f;
- RecursiveLightPoint (color, cl.worldmodel->nodes, p, end);
+ RecursiveLightPoint (color, cl.worldmodel->nodes, p[0], p[1], p[2], p[2] - 65536);
+}
+
+// LordHavoc: added light checking to the server
+void SV_LightPoint (vec3_t color, vec3_t p)
+{
+ if (!sv.worldmodel->lightdata)
+ {
+ color[0] = color[1] = color[2] = 255;
+ return;
+ }
+
+ color[0] = color[1] = color[2] = 0;
+ RecursiveLightPoint (color, sv.worldmodel->nodes, p[0], p[1], p[2], p[2] - 65536);
}
// LordHavoc: R_DynamicLightPoint - acumulates the dynamic lighting
continue;
k = (j<<5)+i;
VectorSubtract (org, cl_dlights[k].origin, dist);
- f = DotProduct(dist, dist) + 65536.0f;
- r = cl_dlights[k].radius*cl_dlights[k].radius*16.0f;
+ f = DotProduct(dist, dist) + LIGHTOFFSET;
+ r = cl_dlights[k].radius*cl_dlights[k].radius*LIGHTSCALE;
if (f < r)
{
brightness = r * 16.0f / f;
if (cl_dlights[i].die < cl.time || !cl_dlights[i].radius)
continue;
VectorSubtract (org, cl_dlights[i].origin, dist);
- f = DotProduct(dist, dist) + 65536.0f;
- r = cl_dlights[i].radius*cl_dlights[i].radius*16.0f;
+ f = DotProduct(dist, dist) + LIGHTOFFSET;
+ r = cl_dlights[i].radius*cl_dlights[i].radius*LIGHTSCALE;
if (f < r)
{
brightness = r * 16.0f / f;
extern float *aliasvert;
extern float *aliasvertnorm;
extern byte *aliasvertcolor;
-extern vec_t shadecolor[];
extern float modelalpha;
extern qboolean lighthalf;
extern int modeldlightbits[8];
-void R_LightModel(int numverts, vec3_t center)
+void R_LightModel(int numverts, vec3_t center, vec3_t basecolor)
{
- int i, j, nearlights = 0;
- vec3_t dist;
+ // LordHavoc: warning: reliance on int being 4 bytes here (of course the d_8to24table relies on that too...)
+ int i, j, nearlights = 0, color;
+ vec3_t dist, mod;
float t, t1, t2, t3, *avn;
byte r,g,b,a, *avc;
struct
vec3_t color;
vec3_t origin;
} nearlight[MAX_DLIGHTS];
- if (!lighthalf)
- {
- shadecolor[0] *= 2.0f;
- shadecolor[1] *= 2.0f;
- shadecolor[2] *= 2.0f;
- }
avc = aliasvertcolor;
avn = aliasvertnorm;
a = (byte) bound((int) 0, (int) (modelalpha * 255.0f), (int) 255);
{
if (lighthalf)
{
- r = (byte) ((float) (128.0f * currententity->colormod[0]));
- g = (byte) ((float) (128.0f * currententity->colormod[1]));
- b = (byte) ((float) (128.0f * currententity->colormod[2]));
+ ((byte *)&color)[0] = (byte) ((float) (128.0f * currententity->colormod[0]));
+ ((byte *)&color)[1] = (byte) ((float) (128.0f * currententity->colormod[1]));
+ ((byte *)&color)[2] = (byte) ((float) (128.0f * currententity->colormod[2]));
}
else
{
- r = (byte) ((float) (255.0f * currententity->colormod[0]));
- g = (byte) ((float) (255.0f * currententity->colormod[1]));
- b = (byte) ((float) (255.0f * currententity->colormod[2]));
+ ((byte *)&color)[0] = (byte) ((float) (255.0f * currententity->colormod[0]));
+ ((byte *)&color)[1] = (byte) ((float) (255.0f * currententity->colormod[1]));
+ ((byte *)&color)[2] = (byte) ((float) (255.0f * currententity->colormod[2]));
}
+ ((byte *)&color)[3] = a;
for (i = 0;i < numverts;i++)
{
- *avc++ = r;
- *avc++ = g;
- *avc++ = b;
- *avc++ = a;
+ *((int *)avc) = color;
+ avc += 4;
}
return;
}
+ if (lighthalf)
+ {
+ mod[0] = currententity->colormod[0] * 0.5f;
+ mod[1] = currententity->colormod[1] * 0.5f;
+ mod[2] = currententity->colormod[2] * 0.5f;
+ }
+ else
+ {
+ mod[0] = currententity->colormod[0];
+ mod[1] = currententity->colormod[1];
+ mod[2] = currententity->colormod[2];
+ }
+ basecolor[0] *= mod[0];
+ basecolor[1] *= mod[1];
+ basecolor[2] *= mod[2];
if (r_lightmodels.value)
{
for (i = 0;i < MAX_DLIGHTS;i++)
}
if (!(modeldlightbits[i >> 5] & (1 << (i & 31))))
continue;
-// if (cl_dlights[i].die < cl.time || !cl_dlights[i].radius)
-// continue;
VectorSubtract (center, cl_dlights[i].origin, dist);
- t1 = cl_dlights[i].radius*cl_dlights[i].radius*16.0f;
- t2 = DotProduct(dist,dist) + 65536.0f;
+ t1 = cl_dlights[i].radius*cl_dlights[i].radius*LIGHTSCALE;
+ t2 = DotProduct(dist,dist) + LIGHTOFFSET;
if (t2 < t1)
{
VectorCopy(cl_dlights[i].origin, nearlight[nearlights].origin);
- nearlight[nearlights].color[0] = cl_dlights[i].color[0] * cl_dlights[i].radius * cl_dlights[i].radius * 0.5f;
- nearlight[nearlights].color[1] = cl_dlights[i].color[1] * cl_dlights[i].radius * cl_dlights[i].radius * 0.5f;
- nearlight[nearlights].color[2] = cl_dlights[i].color[2] * cl_dlights[i].radius * cl_dlights[i].radius * 0.5f;
- if (lighthalf)
- {
- nearlight[nearlights].color[0] *= 0.5f;
- nearlight[nearlights].color[1] *= 0.5f;
- nearlight[nearlights].color[2] *= 0.5f;
- }
- t1 = 0.5f / t2;
- shadecolor[0] += nearlight[nearlights].color[0] * t1;
- shadecolor[1] += nearlight[nearlights].color[1] * t1;
- shadecolor[2] += nearlight[nearlights].color[2] * t1;
- nearlight[nearlights].color[0] *= currententity->colormod[0];
- nearlight[nearlights].color[1] *= currententity->colormod[1];
- nearlight[nearlights].color[2] *= currententity->colormod[2];
+ nearlight[nearlights].color[0] = cl_dlights[i].color[0] * cl_dlights[i].radius * cl_dlights[i].radius * mod[0];
+ nearlight[nearlights].color[1] = cl_dlights[i].color[1] * cl_dlights[i].radius * cl_dlights[i].radius * mod[1];
+ nearlight[nearlights].color[2] = cl_dlights[i].color[2] * cl_dlights[i].radius * cl_dlights[i].radius * mod[2];
+ t1 = (128.0f / LIGHTSCALE) / t2;
+ basecolor[0] += nearlight[nearlights].color[0] * t1;
+ basecolor[1] += nearlight[nearlights].color[1] * t1;
+ basecolor[2] += nearlight[nearlights].color[2] * t1;
nearlights++;
}
}
}
if (!(modeldlightbits[i >> 5] & (1 << (i & 31))))
continue;
-// if (cl_dlights[i].die < cl.time || !cl_dlights[i].radius)
-// continue;
VectorSubtract (center, cl_dlights[i].origin, dist);
- t2 = DotProduct(dist,dist) + 65536.0f;
- t1 = cl_dlights[i].radius*cl_dlights[i].radius*16.0f;
+ t1 = cl_dlights[i].radius*cl_dlights[i].radius*LIGHTSCALE;
+ t2 = DotProduct(dist,dist) + LIGHTOFFSET;
if (t2 < t1)
{
- dist[0] = cl_dlights[i].color[0] * cl_dlights[i].radius * cl_dlights[i].radius * 0.5f;
- dist[1] = cl_dlights[i].color[1] * cl_dlights[i].radius * cl_dlights[i].radius * 0.5f;
- dist[2] = cl_dlights[i].color[2] * cl_dlights[i].radius * cl_dlights[i].radius * 0.5f;
- if (lighthalf)
- {
- dist[0] *= 0.5f;
- dist[1] *= 0.5f;
- dist[2] *= 0.5f;
- }
- t1 = 0.75f / t2;
- shadecolor[0] += dist[0] * t1;
- shadecolor[1] += dist[1] * t1;
- shadecolor[2] += dist[2] * t1;
+ dist[0] = cl_dlights[i].color[0] * cl_dlights[i].radius * cl_dlights[i].radius * mod[0];
+ dist[1] = cl_dlights[i].color[1] * cl_dlights[i].radius * cl_dlights[i].radius * mod[1];
+ dist[2] = cl_dlights[i].color[2] * cl_dlights[i].radius * cl_dlights[i].radius * mod[2];
+ t1 = (192.0f / LIGHTSCALE) / t2;
+ basecolor[0] += dist[0] * t1;
+ basecolor[1] += dist[1] * t1;
+ basecolor[2] += dist[2] * t1;
}
}
}
- shadecolor[0] *= currententity->colormod[0];
- shadecolor[1] *= currententity->colormod[1];
- shadecolor[2] *= currententity->colormod[2];
- t1 = bound(0, shadecolor[0], 255);r = (byte) t1;
- t1 = bound(0, shadecolor[1], 255);g = (byte) t1;
- t1 = bound(0, shadecolor[2], 255);b = (byte) t1;
+ t1 = bound(0, basecolor[0], 255);r = (byte) t1;
+ t1 = bound(0, basecolor[1], 255);g = (byte) t1;
+ t1 = bound(0, basecolor[2], 255);b = (byte) t1;
+ ((byte *)&color)[0] = r;
+ ((byte *)&color)[1] = g;
+ ((byte *)&color)[2] = b;
+ ((byte *)&color)[3] = a;
if (nearlights)
{
int temp;
if (t > 0)
{
t /= DotProduct(v,v);
- temp = (int) ((float) (shadecolor[0] + nearlight[0].color[0] * t));if (temp < 0) temp = 0;else if (temp > 255) temp = 255;*avc++ = temp;
- temp = (int) ((float) (shadecolor[1] + nearlight[0].color[1] * t));if (temp < 0) temp = 0;else if (temp > 255) temp = 255;*avc++ = temp;
- temp = (int) ((float) (shadecolor[2] + nearlight[0].color[2] * t));if (temp < 0) temp = 0;else if (temp > 255) temp = 255;*avc++ = temp;
+ temp = (int) ((float) (basecolor[0] + nearlight[0].color[0] * t));if (temp < 0) temp = 0;else if (temp > 255) temp = 255;avc[0] = temp;
+ temp = (int) ((float) (basecolor[1] + nearlight[0].color[1] * t));if (temp < 0) temp = 0;else if (temp > 255) temp = 255;avc[1] = temp;
+ temp = (int) ((float) (basecolor[2] + nearlight[0].color[2] * t));if (temp < 0) temp = 0;else if (temp > 255) temp = 255;avc[2] = temp;
+ avc[3] = a;
}
else
- {
- *avc++ = r;
- *avc++ = g;
- *avc++ = b;
- }
- *avc++ = a;
+ *((int *)avc) = color;
+ avc += 4;
av+=3;
avn+=3;
}
}
else
{
- int i1, i2, i3;
+ int i1, i2, i3, k;
for (i = 0;i < numverts;i++)
{
- t1 = shadecolor[0];
- t2 = shadecolor[1];
- t3 = shadecolor[2];
+ t1 = basecolor[0];
+ t2 = basecolor[1];
+ t3 = basecolor[2];
+ k = false;
for (j = 0;j < nearlights;j++)
{
VectorSubtract(nearlight[j].origin, av, v);
t1 += nearlight[j].color[0] * t;
t2 += nearlight[j].color[1] * t;
t3 += nearlight[j].color[2] * t;
+ k = true;
}
}
- i1 = t1;if (i1 < 0) i1 = 0;else if (i1 > 255) i1 = 255;
- i2 = t2;if (i2 < 0) i2 = 0;else if (i2 > 255) i2 = 255;
- i3 = t3;if (i3 < 0) i3 = 0;else if (i3 > 255) i3 = 255;
- *avc++ = i1;
- *avc++ = i2;
- *avc++ = i3;
- *avc++ = a;
+ if (k) // dodge the costly float -> int conversions
+ {
+ i1 = t1;if (i1 < 0) i1 = 0;else if (i1 > 255) i1 = 255;avc[0] = i1;
+ i2 = t2;if (i2 < 0) i2 = 0;else if (i2 > 255) i2 = 255;avc[1] = i2;
+ i3 = t3;if (i3 < 0) i3 = 0;else if (i3 > 255) i3 = 255;avc[2] = i3;
+ avc[3] = a;
+ }
+ else
+ *((int *)avc) = color;
+ avc += 4;
}
}
}
{
for (i = 0;i < numverts;i++)
{
- *avc++ = r;
- *avc++ = g;
- *avc++ = b;
- *avc++ = a;
+ *((int *)avc) = color;
+ avc += 4;
}
}
}
--- /dev/null
+
+// LordHavoc: 256 dynamic lights
+#define MAX_DLIGHTS 256
+typedef struct
+{
+ vec3_t origin;
+ float radius;
+ float die; // stop lighting after this time
+ float decay; // drop this each second
+ float minlight; // don't add when contributing less
+ int key;
+ vec3_t color; // LordHavoc: colored lighting
+ qboolean dark; // subtracts light instead of adding
+} dlight_t;
+
+// LordHavoc: this affects the lighting scale of the whole game
+#define LIGHTOFFSET 16384.0f
+#define LIGHTSCALE 4.0f
--- /dev/null
+
+#include "quakedef.h"
+
+typedef struct rendermodule_s
+{
+ int active; // set by start, cleared by shutdown
+ char *name;
+ void(*start)();
+ void(*shutdown)();
+}
+rendermodule_t;
+
+rendermodule_t rendermodule[64];
+
+void R_Modules_Init()
+{
+ int i;
+ for (i = 0;i < 64;i++)
+ rendermodule[i].name = NULL;
+}
+
+void R_RegisterModule(char *name, void(*start)(), void(*shutdown)())
+{
+ int i;
+ for (i = 0;i < 64;i++)
+ {
+ if (rendermodule[i].name == NULL)
+ break;
+ if (!strcmp(name, rendermodule[i].name))
+ Sys_Error("R_RegisterModule: module \"%s\" registered twice\n", name);
+ }
+ if (i >= 64)
+ Sys_Error("R_RegisterModule: ran out of renderer module slots (64)\n");
+ rendermodule[i].active = 0;
+ rendermodule[i].name = name;
+ rendermodule[i].start = start;
+ rendermodule[i].shutdown = shutdown;
+}
+
+void R_StartModules ()
+{
+ int i;
+ for (i = 0;i < 64;i++)
+ {
+ if (rendermodule[i].name == NULL)
+ continue;
+ if (rendermodule[i].active)
+ Sys_Error("R_StartModules: module \"%s\" already active\n", rendermodule[i].name);
+ rendermodule[i].active = 1;
+ rendermodule[i].start();
+ }
+}
+
+void R_ShutdownModules ()
+{
+ int i;
+ for (i = 0;i < 64;i++)
+ {
+ if (rendermodule[i].name == NULL)
+ continue;
+ if (!rendermodule[i].active)
+ continue;
+ rendermodule[i].active = 0;
+ rendermodule[i].shutdown();
+ }
+}
+
+void R_Restart ()
+{
+ R_ShutdownModules();
+ R_StartModules();
+}
--- /dev/null
+
+void R_Modules_Init();
+void R_RegisterModule(char *name, void(*start)(), void(*shutdown)());
+void R_StartModules ();
+void R_ShutdownModules ();
+void R_Restart ();
cvar_t r_particles = {"r_particles", "1"};
cvar_t r_dynamicparticles = {"r_dynamicparticles", "0", TRUE};
-void fractalnoise(char *noise, int size);
-void fractalnoise_zeroedge(char *noise, int size);
-
void R_InitParticleTexture (void)
{
int x,y,d,i;
byte data[32][32][4], noise1[32][32], noise2[32][32];
vec3_t normal, light;
- particletexture = texture_extension_number++;
- glBindTexture(GL_TEXTURE_2D, particletexture);
-
for (x=0 ; x<32 ; x++)
{
for (y=0 ; y<32 ; y++)
data[y][x][3] = (byte) d;
}
}
- glTexImage2D (GL_TEXTURE_2D, 0, 4, 32, 32, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
-
- glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
-
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-
+ particletexture = GL_LoadTexture ("particletexture", 32, 32, &data[0][0][0], true, true, 4);
for (i = 0;i < 8;i++)
{
data[y][x][3] = 0;
}
- smokeparticletexture[i] = texture_extension_number++;
- glBindTexture(GL_TEXTURE_2D, smokeparticletexture[i]);
- glTexImage2D (GL_TEXTURE_2D, 0, 4, 32, 32, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
- glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ smokeparticletexture[i] = GL_LoadTexture (va("smokeparticletexture%d", i), 32, 32, &data[0][0][0], true, true, 4);
}
- rainparticletexture = texture_extension_number++;
- glBindTexture(GL_TEXTURE_2D, rainparticletexture);
-
for (x=0 ; x<32 ; x++)
{
for (y=0 ; y<32 ; y++)
data[y][x][3] = (byte) d;
}
}
- glTexImage2D (GL_TEXTURE_2D, 0, 4, 32, 32, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
-
- glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
-
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-
- bubbleparticletexture = texture_extension_number++;
- glBindTexture(GL_TEXTURE_2D, bubbleparticletexture);
+ rainparticletexture = GL_LoadTexture ("rainparticletexture", 32, 32, &data[0][0][0], true, true, 4);
light[0] = 1;light[1] = 1;light[2] = 1;
VectorNormalize(light);
data[y][x][3] = 0;
}
}
- glTexImage2D (GL_TEXTURE_2D, 0, 4, 32, 32, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
+ bubbleparticletexture = GL_LoadTexture ("bubbleparticletexture", 32, 32, &data[0][0][0], true, true, 4);
+}
- glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+void r_part_start()
+{
+ particles = (particle_t *) malloc (r_numparticles * sizeof(particle_t));
+ freeparticles = (void *) malloc (r_numparticles * sizeof(particle_t *));
+ R_InitParticleTexture ();
+}
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+void r_part_shutdown()
+{
+ free(particles);
+ free(freeparticles);
}
/*
R_InitParticles
===============
*/
-void R_InitParticles (void)
+void R_Particles_Init (void)
{
int i;
r_numparticles = MAX_PARTICLES;
}
- particles = (particle_t *) Hunk_AllocName (r_numparticles * sizeof(particle_t), "particles");
- freeparticles = (void *) Hunk_AllocName (r_numparticles * sizeof(particle_t *), "particles");
-
Cvar_RegisterVariable (&r_particles);
Cvar_RegisterVariable (&r_dynamicparticles);
- R_InitParticleTexture ();
+
+ R_RegisterModule("R_Particles", r_part_start, r_part_shutdown);
}
#define particle(ptype, pcolor, ptex, pscale, palpha, ptime, px, py, pz, pvx, pvy, pvz)\
struct efrag_s *efrag; // linked list of efrags
int frame;
float syncbase; // for client-side animations
-// byte *colormap;
int colormap;
int effects; // light, particals, etc
int skinnum; // for Alias models
// LordHavoc: generic image loader
byte* loadimagepixels (char* filename, qboolean complain, int matchwidth, int matchheight);
-int loadtextureimage (int texnum, char* filename, qboolean complain, int matchwidth, int matchheight);
+int loadtextureimage (char* filename, int matchwidth, int matchheight, qboolean complain, qboolean mipmap);
void R_Init (void);
void R_InitTextures (void);
Con_DPrintf ("Server spawned.\n");
}
-
-// LordHavoc: added light checking to the server
-int RecursiveLightPoint (vec3_t color, mnode_t *node, vec3_t start, vec3_t end);
-void SV_LightPoint (vec3_t color, vec3_t p)
-{
- vec3_t end;
-
- if (!sv.worldmodel->lightdata)
- {
- color[0] = color[1] = color[2] = 255;
- return;
- }
-
- end[0] = p[0];
- end[1] = p[1];
- end[2] = p[2] - 2048;
-
- color[0] = color[1] = color[2] = 0;
- RecursiveLightPoint (color, sv.worldmodel->nodes, p, end);
-}
// LordHavoc: report supported extensions
Con_Printf ("\nQSG extensions: %s\n", QSG_EXTENSIONS);
-// glClearColor (1,0,0,0);
glCullFace(GL_FRONT);
-// glEnable(GL_TEXTURE_2D);
-//
-// glEnable(GL_ALPHA_TEST);
glAlphaFunc(GL_GREATER, 0.5);
-//
-// glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
-// glShadeModel (GL_FLAT);
-//
-// glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-// glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-// glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
-// glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
-//
-// glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-//
-// glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
-// glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
}
/*
}
// gamma correct the palette
- for (i=0 ; i<768 ; i++)
- pal[i] = qgamma[pal[i]];
+ //for (i=0 ; i<768 ; i++)
+ // pal[i] = qgamma[pal[i]];
// note: 32bit uploads are corrected by the upload functions
}
// LordHavoc: report supported extensions
Con_Printf ("\nQSG extensions: %s\n", QSG_EXTENSIONS);
// LordHavoc: set up state
-// glEnable(GL_DEPTH_TEST);
-// glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
-// glShadeModel(GL_SMOOTH);
-// glEnable(GL_TEXTURE_2D);
glAlphaFunc(GL_GREATER, 0.5);
-// if (isRagePro || isG200)
-// {
-// glEnable(GL_ALPHA_TEST);
-// glAlphaFunc(GL_GREATER, 0.5);
-// }
-// else
-// glDisable(GL_ALPHA_TEST);
-// glDepthMask(1);
-// glDisable(GL_DITHER); // LordHavoc: disable dithering
-// glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-// glEnable(GL_BLEND);
-
-// glClearColor (0,0,0,0); // LordHavoc: changed from red to black
glCullFace(GL_FRONT);
-
-// glAlphaFunc(GL_GREATER, 0.666);
}
/*
cvar_t cl_crossx = {"cl_crossx", "0", false};
cvar_t cl_crossy = {"cl_crossy", "0", false};
-cvar_t gl_cshiftpercent = {"gl_cshiftpercent", "100", false};
+//cvar_t gl_cshiftpercent = {"gl_cshiftpercent", "100", false};
+cvar_t gl_polyblend = {"gl_polyblend", "1", true};
float v_dmg_time, v_dmg_roll, v_dmg_pitch;
cl.faceanimtime = cl.time + 0.2; // but sbar face into pain frame
- cl.cshifts[CSHIFT_DAMAGE].percent += 3*count;
- if (cl.cshifts[CSHIFT_DAMAGE].percent < 0)
- cl.cshifts[CSHIFT_DAMAGE].percent = 0;
- if (cl.cshifts[CSHIFT_DAMAGE].percent > 150)
- cl.cshifts[CSHIFT_DAMAGE].percent = 150;
-
- if (armor > blood)
- {
- cl.cshifts[CSHIFT_DAMAGE].destcolor[0] = 200;
- cl.cshifts[CSHIFT_DAMAGE].destcolor[1] = 100;
- cl.cshifts[CSHIFT_DAMAGE].destcolor[2] = 100;
- }
- else if (armor)
- {
- cl.cshifts[CSHIFT_DAMAGE].destcolor[0] = 220;
- cl.cshifts[CSHIFT_DAMAGE].destcolor[1] = 50;
- cl.cshifts[CSHIFT_DAMAGE].destcolor[2] = 50;
- }
- else
+ if (gl_polyblend.value)
{
- cl.cshifts[CSHIFT_DAMAGE].destcolor[0] = 255;
- cl.cshifts[CSHIFT_DAMAGE].destcolor[1] = 0;
- cl.cshifts[CSHIFT_DAMAGE].destcolor[2] = 0;
+ cl.cshifts[CSHIFT_DAMAGE].percent += 3*count;
+ if (cl.cshifts[CSHIFT_DAMAGE].percent < 0)
+ cl.cshifts[CSHIFT_DAMAGE].percent = 0;
+ if (cl.cshifts[CSHIFT_DAMAGE].percent > 150)
+ cl.cshifts[CSHIFT_DAMAGE].percent = 150;
+
+ if (armor > blood)
+ {
+ cl.cshifts[CSHIFT_DAMAGE].destcolor[0] = 200;
+ cl.cshifts[CSHIFT_DAMAGE].destcolor[1] = 100;
+ cl.cshifts[CSHIFT_DAMAGE].destcolor[2] = 100;
+ }
+ else if (armor)
+ {
+ cl.cshifts[CSHIFT_DAMAGE].destcolor[0] = 220;
+ cl.cshifts[CSHIFT_DAMAGE].destcolor[1] = 50;
+ cl.cshifts[CSHIFT_DAMAGE].destcolor[2] = 50;
+ }
+ else
+ {
+ cl.cshifts[CSHIFT_DAMAGE].destcolor[0] = 255;
+ cl.cshifts[CSHIFT_DAMAGE].destcolor[1] = 0;
+ cl.cshifts[CSHIFT_DAMAGE].destcolor[2] = 0;
+ }
}
//
*/
void V_BonusFlash_f (void)
{
- cl.cshifts[CSHIFT_BONUS].destcolor[0] = 215;
- cl.cshifts[CSHIFT_BONUS].destcolor[1] = 186;
- cl.cshifts[CSHIFT_BONUS].destcolor[2] = 69;
- cl.cshifts[CSHIFT_BONUS].percent = 50;
+ if (gl_polyblend.value)
+ {
+ cl.cshifts[CSHIFT_BONUS].destcolor[0] = 215;
+ cl.cshifts[CSHIFT_BONUS].destcolor[1] = 186;
+ cl.cshifts[CSHIFT_BONUS].destcolor[2] = 69;
+ cl.cshifts[CSHIFT_BONUS].percent = 50;
+ }
}
/*
{
cshift_t* c;
c = &cl.cshifts[CSHIFT_CONTENTS]; // just to shorten the code below
+ if (!gl_polyblend.value)
+ {
+ c->percent = 0;
+ return;
+ }
switch (contents)
{
case CONTENTS_EMPTY:
*/
void V_CalcPowerupCshift (void)
{
+ if (!gl_polyblend.value)
+ {
+ cl.cshifts[CSHIFT_POWERUP].percent = 0;
+ return;
+ }
if (cl.items & IT_QUAD)
{
cl.cshifts[CSHIFT_POWERUP].destcolor[0] = 0;
b = 0;
a = 0;
- if (gl_cshiftpercent.value)
- {
+// if (gl_cshiftpercent.value)
+// {
for (j=0 ; j<NUM_CSHIFTS ; j++)
{
- a2 = ((cl.cshifts[j].percent * gl_cshiftpercent.value) / 100.0) / 255.0;
+// a2 = ((cl.cshifts[j].percent * gl_cshiftpercent.value) / 100.0) / 255.0;
+ a2 = cl.cshifts[j].percent * (1.0f / 255.0f);
if (!a2)
continue;
g *= a2;
b *= a2;
}
- }
+// }
v_blend[0] = bound(0, r * (1.0/255.0), 1);
v_blend[1] = bound(0, g * (1.0/255.0), 1);
view->model = cl.model_precache[cl.stats[STAT_WEAPON]];
view->frame = cl.stats[STAT_WEAPONFRAME];
- view->colormap = 0; //vid.colormap;
+ view->colormap = -1; // no special coloring
// set up the refresh position
if (!intimerefresh)
Cvar_RegisterVariable (&crosshair);
Cvar_RegisterVariable (&cl_crossx);
Cvar_RegisterVariable (&cl_crossy);
- Cvar_RegisterVariable (&gl_cshiftpercent);
+// Cvar_RegisterVariable (&gl_cshiftpercent);
+ Cvar_RegisterVariable (&gl_polyblend);
Cvar_RegisterVariable (&cl_rollspeed);
Cvar_RegisterVariable (&cl_rollangle);
testing object's origin to get a point to use with the returned hull.
================
*/
+extern qboolean hlbsp;
hull_t *SV_HullForEntity (edict_t *ent, vec3_t mins, vec3_t maxs, vec3_t offset)
{
model_t *model;
VectorSubtract (maxs, mins, size);
// LordHavoc: FIXME!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
- if (size[0] < 3)
- hull = &model->hulls[0];
- else if (size[0] <= 32)
- hull = &model->hulls[1];
+ if (hlbsp)
+ {
+ if (size[0] < 3)
+ hull = &model->hulls[0]; // 0x0x0
+ else if (size[0] <= 32)
+ {
+ if (size[2] < 54) // pick the nearest of 36 or 72
+ hull = &model->hulls[3]; // 32x32x36
+ else
+ hull = &model->hulls[1]; // 32x32x72
+ }
+ else
+ hull = &model->hulls[2]; // 64x64x64
+ }
else
- hull = &model->hulls[2];
+ {
+ if (size[0] < 3)
+ hull = &model->hulls[0]; // 0x0x0
+ else if (size[0] <= 32)
+ hull = &model->hulls[1]; // 32x32x56
+ else
+ hull = &model->hulls[2]; // 64x64x88
+ }
// calculate an offset value to center the origin
VectorSubtract (hull->clip_mins, mins, offset);