From: lordhavoc Date: Fri, 17 Nov 2000 08:35:39 +0000 (+0000) Subject: updated to version 1.50, build 75. X-Git-Tag: RELEASE_0_2_0_RC1~944 X-Git-Url: https://git.xonotic.org/?a=commitdiff_plain;ds=sidebyside;h=855932aeb5707c5efb2858c3e51b913d8203ebbe;p=xonotic%2Fdarkplaces.git updated to version 1.50, build 75. change log as best I can remember: rewrote model loading and rendering multi-pass colormapping on any model (NO UPLOADS!) fullbrights on models (feature of new multi-pass model renderer) rewrote texture management rewrote texture uploading heavily optimized static light sampling fancy new crosshair fixed network angle rounding (shots are fired where you're pointing, not down and to the right) HL map hull sizes are supported (still sink into grates though) removal of some commented out junk other minor stuff I can't remember now git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@76 d7cf8633-e32d-0410-b094-e92efae38249 --- diff --git a/buildnumber.c b/buildnumber.c index f2fa7865..cd041315 100644 --- a/buildnumber.c +++ b/buildnumber.c @@ -1,4 +1,4 @@ -#define BUILDNUMBER 73 +#define BUILDNUMBER 75 int buildnumber = BUILDNUMBER; diff --git a/cl_main.c b/cl_main.c index 34a0b42f..538b19c5 100644 --- a/cl_main.c +++ b/cl_main.c @@ -466,9 +466,31 @@ void CL_RelinkEntities (void) 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) diff --git a/cl_parse.c b/cl_parse.c index 75d53fe7..028dda20 100644 --- a/cl_parse.c +++ b/cl_parse.c @@ -105,7 +105,7 @@ entity_t *CL_EntityNum (int num) 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++; } } @@ -516,8 +516,6 @@ void CL_ParseUpdate (int bits) 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)); @@ -525,20 +523,18 @@ void CL_ParseUpdate (int bits) 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; @@ -769,7 +765,7 @@ void CL_ParseStatic (void) // 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; @@ -963,7 +959,6 @@ void CL_ParseServerMessage (void) 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: diff --git a/cl_tent.c b/cl_tent.c index d60ed56e..d6d42475 100644 --- a/cl_tent.c +++ b/cl_tent.c @@ -104,6 +104,21 @@ void R_BloodShower (vec3_t mins, vec3_t maxs, float velspeed, int count); 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 @@ -345,6 +360,7 @@ void CL_ParseTEnt (void) 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); @@ -360,6 +376,7 @@ void CL_ParseTEnt (void) 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); @@ -376,6 +393,7 @@ void CL_ParseTEnt (void) 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); @@ -391,6 +409,7 @@ void CL_ParseTEnt (void) 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); @@ -406,6 +425,7 @@ void CL_ParseTEnt (void) 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); @@ -421,6 +441,7 @@ void CL_ParseTEnt (void) pos[0] = MSG_ReadCoord (); pos[1] = MSG_ReadCoord (); pos[2] = MSG_ReadCoord (); + FindNonSolidLocation(pos); R_BlobExplosion (pos); // R_BlastParticles (pos, 120, 120); @@ -475,6 +496,7 @@ void CL_ParseTEnt (void) 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); @@ -514,8 +536,7 @@ entity_t *CL_NewTempEntity (void) 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; diff --git a/client.h b/client.h index 45ae787e..563f3cd0 100644 --- a/client.h +++ b/client.h @@ -41,7 +41,7 @@ typedef struct 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 @@ -65,20 +65,7 @@ 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 diff --git a/common.c b/common.c index 2c9c8cc1..e31b48d7 100644 --- a/common.c +++ b/common.c @@ -588,17 +588,18 @@ void MSG_WriteCoord (sizebuf_t *sb, float f) 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); } // diff --git a/draw.h b/draw.h index db8a8601..ddb8e35b 100644 --- a/draw.h +++ b/draw.h @@ -25,6 +25,7 @@ extern qpic_t *draw_disc; // also used on sbar void Draw_Init (void); void Draw_Character (int x, int y, int num); +void Draw_GenericPic (int texnum, float red, float green, float blue, float alpha, 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); diff --git a/gl_draw.c b/gl_draw.c index 7777801f..69c8d7b8 100644 --- a/gl_draw.c +++ b/gl_draw.c @@ -28,15 +28,12 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 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 @@ -48,29 +45,6 @@ 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; - /* ============================================================================= @@ -89,7 +63,6 @@ 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) @@ -134,6 +107,7 @@ int Scrap_AllocBlock (int w, int h, int *x, int *y) } int scrap_uploads; +int scraptexnum[MAX_SCRAPS]; void Scrap_Upload (void) { @@ -142,10 +116,7 @@ void Scrap_Upload (void) scrap_uploads++; for (texnum=0 ; texnumheight ; i++) for (j=0 ; jwidth ; 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; @@ -200,9 +172,6 @@ qpic_t *Draw_PicFromWad (char *name) 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 { @@ -211,9 +180,6 @@ qpic_t *Draw_PicFromWad (char *name) 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; } @@ -267,7 +233,7 @@ qpic_t *Draw_CachePic (char *path) return &pic->pic; } - +/* void Draw_CharToConback (int num, byte *dest) { int row, col; @@ -291,69 +257,7 @@ void Draw_CharToConback (int num, byte *dest) } } - -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 ; imipmap) - { - 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); @@ -366,101 +270,85 @@ Draw_Init */ 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 ; xdata; - 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 @@ -566,6 +454,30 @@ void Draw_String (int x, int y, char *str, int maxlen) 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 @@ -660,8 +572,6 @@ void Draw_TransPicTranslate (int x, int y, qpic_t *pic, byte *translation) byte *src; int p; - glBindTexture(GL_TEXTURE_2D, translate_texture); - c = pic->width * pic->height; dest = trans; @@ -678,10 +588,7 @@ void Draw_TransPicTranslate (int x, int y, qpic_t *pic, byte *translation) } } - 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); @@ -713,6 +620,8 @@ void Draw_ConsoleBackground (int lines) 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); } /* @@ -845,587 +754,3 @@ void SHOWLMP_clear() 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 ; iidentifier)) - 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> 1; - for (j=0 ; j> 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> 1; - for (j=0 ; j>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>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>=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 ; iidentifier)) - { - // 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; -} diff --git a/gl_models.c b/gl_models.c new file mode 100644 index 00000000..636018d6 --- /dev/null +++ b/gl_models.c @@ -0,0 +1,802 @@ + +#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); +} diff --git a/gl_poly.c b/gl_poly.c index 3947bbd8..9750a346 100644 --- a/gl_poly.c +++ b/gl_poly.c @@ -34,11 +34,9 @@ float transviewdist; // distance of view origin along the view normal 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)); @@ -50,6 +48,23 @@ void glpoly_init() 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() { diff --git a/gl_rmain.c b/gl_rmain.c index 753f34e7..e880dbd5 100644 --- a/gl_rmain.c +++ b/gl_rmain.c @@ -39,7 +39,7 @@ qboolean envmap; // true during envmap command capture // 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 @@ -82,17 +82,9 @@ cvar_t r_novis = {"r_novis","0"}; 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"}; @@ -105,74 +97,6 @@ cvar_t gl_fogstart = {"gl_fogstart", "0"}; 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; @@ -286,22 +210,16 @@ void FOG_registercvars() } } -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); @@ -315,10 +233,34 @@ void rmain_registercvars() // 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(); } /* @@ -347,32 +289,9 @@ vec3_t shadecolor; 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); /* ============================================================= @@ -530,668 +449,6 @@ void R_DrawSpriteModel (entity_t *e) 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); @@ -1235,7 +492,7 @@ void R_DrawEntitiesOnList2 (void) 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: @@ -1266,7 +523,7 @@ void R_DrawViewModel (void) // 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); } diff --git a/gl_rmisc.c b/gl_rmisc.c index ab7573c1..99ff6ecb 100644 --- a/gl_rmisc.c +++ b/gl_rmisc.c @@ -125,21 +125,25 @@ void R_Envmap_f (void) 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); @@ -149,175 +153,11 @@ void R_Init (void) 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 ; iskinwidth, 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> 1; - for (j=0 ; j>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> 1; - for (j=0 ; j>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); diff --git a/gl_rsurf.c b/gl_rsurf.c index fe5bb6ca..be07117c 100644 --- a/gl_rsurf.c +++ b/gl_rsurf.c @@ -51,15 +51,22 @@ cvar_t gl_vertex = {"gl_vertex", "0"}; 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++) @@ -80,6 +87,8 @@ void glrsurf_init() // Cvar_SetValue("gl_nosubimage", 1); Cvar_SetValue("gl_lightmode", 0); } + + R_RegisterModule("GL_Surf", gl_surf_start, gl_surf_shutdown); } extern qboolean lighthalf; @@ -303,12 +312,9 @@ extern int solidskytexture; 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" @@ -347,7 +353,9 @@ void UploadLightmaps() } } -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; @@ -379,11 +387,11 @@ void R_SkySurf(msurface_t *s, qboolean transform) } } -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; @@ -391,18 +399,18 @@ void R_LightSurface(int *dlightbits, glpoly_t *polys, float *wvert) { 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) { @@ -411,28 +419,28 @@ void R_LightSurface(int *dlightbits, glpoly_t *polys, float *wvert) 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) { @@ -449,7 +457,7 @@ void R_WaterSurf(msurface_t *s, texture_t *t, qboolean transform, int alpha) } } 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) @@ -461,12 +469,8 @@ void R_WaterSurf(msurface_t *s, texture_t *t, qboolean transform, int alpha) } } -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 @@ -476,8 +480,13 @@ void R_WallSurf(msurface_t *s, texture_t *t, qboolean transform) || (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) { @@ -489,77 +498,112 @@ void R_WallSurf(msurface_t *s, texture_t *t, qboolean transform) 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;inumverts;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) { @@ -590,31 +634,14 @@ void R_WallSurfVertex(msurface_t *s, texture_t *t, qboolean transform, qboolean 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)); } /* @@ -624,27 +651,26 @@ DrawTextureChains */ 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) @@ -667,7 +693,7 @@ 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]); @@ -676,15 +702,15 @@ void DrawTextureChains (void) { 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); } } @@ -701,7 +727,7 @@ void R_DrawBrushModel (entity_t *e) vec3_t mins, maxs; msurface_t *s; model_t *clmodel; - qboolean rotated, vertexlit = false; + int rotated, vertexlit = false; texture_t *t; vec3_t org; @@ -767,19 +793,19 @@ e->angles[0] = -e->angles[0]; // stupid quake bug // 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(); diff --git a/gl_screen.c b/gl_screen.c index 43923c65..e2a35ffa 100644 --- a/gl_screen.c +++ b/gl_screen.c @@ -369,12 +369,23 @@ void SCR_SizeDown_f (void) //============================================================================ +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); @@ -394,11 +405,9 @@ void SCR_Init (void) 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); } @@ -780,9 +789,9 @@ void SCR_BringDownConsole (void) 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(); @@ -892,7 +901,7 @@ void SCR_UpdateScreen (void) 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) // @@ -928,7 +937,7 @@ void SCR_UpdateScreen (void) 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 (); diff --git a/gl_textures.c b/gl_textures.c new file mode 100644 index 00000000..7534ab4b --- /dev/null +++ b/gl_textures.c @@ -0,0 +1,924 @@ +#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 ; imipmap) + { + 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 ; iidentifier)) + 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> 1; + for (j=0 ; j> 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> 1; + for (j=0 ; j>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>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>=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 ; itexels[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 ; iidentifier)) + { + // 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; +} diff --git a/gl_warp.c b/gl_warp.c index 5bf52b35..812b82a6 100644 --- a/gl_warp.c +++ b/gl_warp.c @@ -178,7 +178,7 @@ void GL_SubdivideSurface (msurface_t *fa) extern qboolean lighthalf; -#define SKY_TEX 4000 +int skyboxside[6]; char skyname[256]; @@ -201,7 +201,6 @@ void R_LoadSkyBox (void) 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))) { @@ -212,10 +211,8 @@ void R_LoadSkyBox (void) 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); } } @@ -260,42 +257,42 @@ void R_SkyBox() 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); @@ -430,18 +427,14 @@ R_InitSky 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++) @@ -470,16 +463,7 @@ void R_InitSky (byte *src, int bytesperpixel) //texture_t *mt) ((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) { @@ -500,14 +484,6 @@ void R_InitSky (byte *src, int bytesperpixel) //texture_t *mt) } } - 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); } diff --git a/glquake.h b/glquake.h index bed1e189..bab055b6 100644 --- a/glquake.h +++ b/glquake.h @@ -37,17 +37,17 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include //#include -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 { @@ -70,8 +70,8 @@ extern int glx, gly, glwidth, glheight; #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); //==================================================== @@ -103,39 +103,20 @@ extern texture_t *r_notexture_mip; 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]; @@ -144,8 +125,6 @@ extern const char *gl_renderer; extern const char *gl_version; extern const char *gl_extensions; -void R_TranslatePlayerSkin (int playernum); - // Multitexture #define TEXTURE0_SGIS 0x835E #define TEXTURE1_SGIS 0x835F @@ -259,3 +238,7 @@ extern vec_t fogdensity; //#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); diff --git a/host.c b/host.c index e9c697ea..15ee3138 100644 --- a/host.c +++ b/host.c @@ -53,7 +53,6 @@ client_t *host_client; // current client 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 @@ -557,74 +556,6 @@ Host_ServerFrame ================== */ -#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) { @@ -655,8 +586,6 @@ void Host_ServerFrame (void) SV_SendClientMessages (); } -#endif - /* ================== @@ -862,6 +791,8 @@ void Host_InitVCR (quakeparms_t *parms) } +void Render_Init(); + /* ==================== Host_Init @@ -914,18 +845,13 @@ void Host_Init (quakeparms_t *parms) 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 (); @@ -977,6 +903,7 @@ void Host_Shutdown(void) if (cls.state != ca_dedicated) { + R_ShutdownModules(); VID_Shutdown(); } } diff --git a/host_cmd.c b/host_cmd.c index c08e9212..1e18df99 100644 --- a/host_cmd.c +++ b/host_cmd.c @@ -1469,15 +1469,15 @@ void Host_Viewframe_f (void) 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); } /* diff --git a/image.c b/image.c index d48bee4e..6740daca 100644 --- a/image.c +++ b/image.c @@ -4,6 +4,59 @@ 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; + } +} + + /* ================================================================= @@ -101,6 +154,7 @@ byte* LoadPCX (FILE *f, int matchwidth, int matchheight) } } } + fclose(f); image_width = pcx->xmax+1; image_height = pcx->ymax+1; return image_rgba; @@ -184,7 +238,7 @@ byte* LoadTGA (FILE *fin, int matchwidth, int matchheight) 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; @@ -309,12 +363,50 @@ byte* LoadTGA (FILE *fin, int matchwidth, int matchheight) 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) @@ -331,6 +423,13 @@ byte* loadimagepixels (char* filename, qboolean complain, int matchwidth, int ma 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) @@ -338,22 +437,28 @@ byte* loadimagepixels (char* filename, qboolean complain, int matchwidth, int ma 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; } + */ } diff --git a/image.h b/image.h new file mode 100644 index 00000000..375f5118 --- /dev/null +++ b/image.h @@ -0,0 +1,3 @@ + +extern void Image_Copy8bitRGBA(byte *in, byte *out, int pixels, int *pal); +extern void Image_CopyRGBAGamma(byte *in, byte *out, int pixels); diff --git a/model_alias.c b/model_alias.c index d290c4b8..2f7b5f24 100644 --- a/model_alias.c +++ b/model_alias.c @@ -29,14 +29,14 @@ void Mod_AliasInit (void) { } -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]; @@ -50,16 +50,23 @@ byte *player_8bit_texels; 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]; @@ -70,62 +77,23 @@ void Mod_ConvertAliasVerts (int numverts, int numtris, vec3_t scale, vec3_t tran 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); } - */ } /* @@ -133,35 +101,25 @@ void Mod_ConvertAliasVerts (int numverts, int numtris, vec3_t scale, vec3_t tran 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; } @@ -172,44 +130,31 @@ void * Mod_LoadAliasFrame (void * pin, maliasframedesc_t *frame) 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 ; inumverts, 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; @@ -293,84 +238,179 @@ void Mod_FloodFillSkin( byte *skin, int skinwidth, int skinheight ) } } +int GL_SkinSplitShirt(byte *in, byte *out, int width, int height, unsigned short bits, char *name) +{ + 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); @@ -384,164 +424,164 @@ Mod_LoadAliasModel #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 ; itype) == 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 ; inumtris ; 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 ; inumtris ; 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; @@ -549,18 +589,12 @@ void Mod_LoadAliasModel (model_t *mod, void *buffer) for (i=0 ; itype); - - 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; @@ -577,17 +611,91 @@ void Mod_LoadAliasModel (model_t *mod, void *buffer) 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; @@ -597,12 +705,12 @@ void Mod_LoadQ2AliasModel (model_t *mod, void *buffer) 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; @@ -628,6 +736,7 @@ void Mod_LoadQ2AliasModel (model_t *mod, void *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); @@ -644,7 +753,7 @@ void Mod_LoadQ2AliasModel (model_t *mod, void *buffer) 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)); @@ -660,25 +769,39 @@ void Mod_LoadQ2AliasModel (model_t *mod, void *buffer) // 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 ; inum_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); @@ -687,7 +810,6 @@ void Mod_LoadQ2AliasModel (model_t *mod, void *buffer) } pintriangles++; pouttriangles++; - tris++; } // LordHavoc: doing proper bbox for model @@ -705,7 +827,7 @@ void Mod_LoadQ2AliasModel (model_t *mod, void *buffer) 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]; } diff --git a/model_alias.h b/model_alias.h index a00d41e1..aafcb33d 100644 --- a/model_alias.h +++ b/model_alias.h @@ -29,6 +29,7 @@ Alias models are position independent, so the cache manager can move them. #include "modelgen.h" +/* typedef struct { int firstpose; @@ -54,11 +55,11 @@ typedef struct 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 { @@ -83,30 +84,34 @@ 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]; - /* ======================================================================== @@ -146,7 +151,7 @@ typedef struct 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 @@ -154,7 +159,7 @@ typedef struct { 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; @@ -205,8 +210,6 @@ typedef struct 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 diff --git a/model_brush.c b/model_brush.c index 03f9dc92..913e9b3d 100644 --- a/model_brush.c +++ b/model_brush.c @@ -867,29 +867,70 @@ void Mod_LoadClipnodes (lump_t *l) 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 ; ineedload) { @@ -168,7 +168,8 @@ model_t *Mod_LoadModel (model_t *mod, qboolean crash) } // 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) @@ -202,6 +203,7 @@ model_t *Mod_LoadModel (model_t *mod, qboolean crash) Mod_LoadBrushModel (mod, buf); break; } + free(buf); return mod; } diff --git a/model_shared.h b/model_shared.h index 865ef39e..d3a701a7 100644 --- a/model_shared.h +++ b/model_shared.h @@ -105,6 +105,12 @@ typedef struct model_s 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 diff --git a/modelgen.h b/modelgen.h index b8b75dd3..41691072 100644 --- a/modelgen.h +++ b/modelgen.h @@ -28,7 +28,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // ********************************************************* #define ALIAS_VERSION 6 -#define ALIAS32_VERSION 7 #define ALIAS_ONSEAM 0x0020 diff --git a/net_wins.c b/net_wins.c index 3c5a773b..0d5265ed 100644 --- a/net_wins.c +++ b/net_wins.c @@ -129,7 +129,7 @@ int WINS_Init (void) 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; } @@ -156,7 +156,7 @@ int WINS_Init (void) !pgethostname || !pgethostbyname || !pgethostbyaddr || !pgetsockname) { - Con_SafePrintf ("Couldn't GetProcAddress from winsock.dll\n"); + Con_SafePrintf ("Couldn't GetProcAddress from wsock32.dll\n"); return -1; } diff --git a/pr_exec.c b/pr_exec.c index 4dd41a93..a608a074 100644 --- a/pr_exec.c +++ b/pr_exec.c @@ -358,318 +358,6 @@ int PR_LeaveFunction (void) 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]) @@ -706,7 +394,7 @@ void PR_ExecuteProgram (func_t fnum) 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"); @@ -991,11 +679,7 @@ void PR_ExecuteProgram (func_t fnum) 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; @@ -1011,7 +695,7 @@ void PR_ExecuteProgram (func_t fnum) 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"); @@ -1296,11 +980,7 @@ void PR_ExecuteProgram (func_t fnum) 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; diff --git a/quakedef.h b/quakedef.h index 8b4d26af..573af6e7 100644 --- a/quakedef.h +++ b/quakedef.h @@ -19,11 +19,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // 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 @@ -31,6 +29,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #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" @@ -261,7 +264,6 @@ extern cvar_t developer; 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 @@ -298,3 +300,7 @@ extern cvar_t chase_active; void Chase_Init (void); void Chase_Reset (void); void Chase_Update (void); + +void fractalnoise(unsigned char *noise, int size); + +#include "image.h" diff --git a/r_crosshairs.c b/r_crosshairs.c new file mode 100644 index 00000000..e2be8674 --- /dev/null +++ b/r_crosshairs.c @@ -0,0 +1,82 @@ +#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); +} + diff --git a/r_light.c b/r_light.c index 775beee8..bb50a11c 100644 --- a/r_light.c +++ b/r_light.c @@ -23,9 +23,18 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 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; @@ -146,6 +155,7 @@ void R_NoVisMarkLights (vec3_t lightorigin, dlight_t *light, int bit, int bitind 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); @@ -160,7 +170,6 @@ void R_VisMarkLights (vec3_t lightorigin, dlight_t *light, int bit, int bitindex 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; @@ -190,10 +199,12 @@ void R_VisMarkLights (vec3_t lightorigin, dlight_t *light, int bit, int bitindex 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; @@ -209,7 +220,7 @@ void R_VisMarkLights (vec3_t lightorigin, dlight_t *light, int bit, int bitindex 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 { @@ -273,6 +284,7 @@ vec3_t lightspot; extern cvar_t r_ambient; +/* int RecursiveLightPoint (vec3_t color, mnode_t *node, vec3_t start, vec3_t end) { float front, back, frac; @@ -368,13 +380,176 @@ void R_LightPoint (vec3_t color, vec3_t p) 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 @@ -397,8 +572,8 @@ void R_DynamicLightPoint(vec3_t color, vec3_t org, int *dlightbits) 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; @@ -426,8 +601,8 @@ void R_DynamicLightPointNoMask(vec3_t color, vec3_t org) 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; @@ -449,14 +624,14 @@ void R_CompleteLightPoint (vec3_t color, vec3_t p) 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 @@ -464,12 +639,6 @@ void R_LightModel(int numverts, vec3_t center) 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); @@ -477,25 +646,39 @@ void R_LightModel(int numverts, vec3_t center) { 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++) @@ -507,30 +690,19 @@ void R_LightModel(int numverts, vec3_t center) } 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++; } } @@ -546,35 +718,28 @@ void R_LightModel(int numverts, vec3_t center) } 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; @@ -590,29 +755,27 @@ void R_LightModel(int numverts, vec3_t center) 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); @@ -623,15 +786,19 @@ void R_LightModel(int numverts, vec3_t center) 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; } } } @@ -639,10 +806,8 @@ void R_LightModel(int numverts, vec3_t center) { for (i = 0;i < numverts;i++) { - *avc++ = r; - *avc++ = g; - *avc++ = b; - *avc++ = a; + *((int *)avc) = color; + avc += 4; } } } diff --git a/r_light.h b/r_light.h new file mode 100644 index 00000000..ac6d2563 --- /dev/null +++ b/r_light.h @@ -0,0 +1,18 @@ + +// 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 diff --git a/r_modules.c b/r_modules.c new file mode 100644 index 00000000..1c30a4ca --- /dev/null +++ b/r_modules.c @@ -0,0 +1,72 @@ + +#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(); +} diff --git a/r_modules.h b/r_modules.h new file mode 100644 index 00000000..38aa9c62 --- /dev/null +++ b/r_modules.h @@ -0,0 +1,6 @@ + +void R_Modules_Init(); +void R_RegisterModule(char *name, void(*start)(), void(*shutdown)()); +void R_StartModules (); +void R_ShutdownModules (); +void R_Restart (); diff --git a/r_part.c b/r_part.c index 24824c2f..b2f6baf2 100644 --- a/r_part.c +++ b/r_part.c @@ -70,9 +70,6 @@ particle_t **freeparticles; // list used only in compacting particles array 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; @@ -80,9 +77,6 @@ void R_InitParticleTexture (void) 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++) @@ -95,13 +89,7 @@ void R_InitParticleTexture (void) 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++) { @@ -127,17 +115,9 @@ void R_InitParticleTexture (void) 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++) @@ -159,15 +139,7 @@ void R_InitParticleTexture (void) 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); @@ -206,12 +178,20 @@ void R_InitParticleTexture (void) 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); } /* @@ -219,7 +199,7 @@ void R_InitParticleTexture (void) R_InitParticles =============== */ -void R_InitParticles (void) +void R_Particles_Init (void) { int i; @@ -236,12 +216,10 @@ void R_InitParticles (void) 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)\ diff --git a/render.h b/render.h index c4ed70e7..2347d941 100644 --- a/render.h +++ b/render.h @@ -68,7 +68,6 @@ typedef struct entity_s 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 @@ -129,7 +128,7 @@ extern struct texture_s *r_notexture_mip; // 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); diff --git a/sv_main.c b/sv_main.c index f2bf0ad5..a22d9395 100644 --- a/sv_main.c +++ b/sv_main.c @@ -1341,23 +1341,3 @@ void SV_SpawnServer (char *server) 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); -} diff --git a/vid_glx.c b/vid_glx.c index 99ec8842..6ac56f8b 100644 --- a/vid_glx.c +++ b/vid_glx.c @@ -597,25 +597,8 @@ void GL_Init (void) // 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); } /* diff --git a/vid_shared.c b/vid_shared.c index f6d5654f..719e0203 100644 --- a/vid_shared.c +++ b/vid_shared.c @@ -98,7 +98,7 @@ void Check_Gamma (unsigned char *pal) } // 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 } diff --git a/vid_wgl.c b/vid_wgl.c index d28c8d2f..64f9c41a 100644 --- a/vid_wgl.c +++ b/vid_wgl.c @@ -568,27 +568,8 @@ void GL_Init (void) // 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); } /* diff --git a/view.c b/view.c index f2daebbd..3645467c 100644 --- a/view.c +++ b/view.c @@ -54,7 +54,8 @@ cvar_t crosshair = {"crosshair", "0", true}; 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; @@ -277,29 +278,32 @@ void V_ParseDamage (void) 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; + } } // @@ -345,10 +349,13 @@ When you run over an item, the server sends this command */ 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; + } } /* @@ -362,6 +369,11 @@ void V_SetContentsColor (int contents) { 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: @@ -402,6 +414,11 @@ V_CalcPowerupCshift */ 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; @@ -450,11 +467,12 @@ void V_CalcBlend (void) b = 0; a = 0; - if (gl_cshiftpercent.value) - { +// if (gl_cshiftpercent.value) +// { for (j=0 ; jmodel = 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) @@ -885,7 +903,8 @@ void V_Init (void) 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); diff --git a/world.c b/world.c index a83dd216..0519bd85 100644 --- a/world.c +++ b/world.c @@ -124,6 +124,7 @@ Offset is filled in to contain the adjustment that must be added to the 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; @@ -149,12 +150,29 @@ hull_t *SV_HullForEntity (edict_t *ent, vec3_t mins, vec3_t maxs, vec3_t offset) 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);