/* ================= Mod_LoadTextures ================= */ void Mod_LoadTextures (lump_t *l) { int i, j, pixels, num, max, altmax; miptex_t *mt; texture_t *tx, *tx2; texture_t *anims[10]; texture_t *altanims[10]; dmiptexlump_t *m; if (!l->filelen) { loadmodel->textures = NULL; return; } m = (dmiptexlump_t *)(mod_base + l->fileofs); m->nummiptex = LittleLong (m->nummiptex); loadmodel->numtextures = m->nummiptex; loadmodel->textures = Hunk_AllocName (m->nummiptex * sizeof(*loadmodel->textures) , loadname); for (i=0 ; i<m->nummiptex ; i++) { m->dataofs[i] = LittleLong(m->dataofs[i]); if (m->dataofs[i] == -1) continue; mt = (miptex_t *)((byte *)m + m->dataofs[i]); mt->width = LittleLong (mt->width); mt->height = LittleLong (mt->height); for (j=0 ; j<MIPLEVELS ; j++) mt->offsets[j] = LittleLong (mt->offsets[j]); if ( (mt->width & 15) || (mt->height & 15) ) Sys_Error ("Texture %s is not 16 aligned", mt->name); pixels = mt->width*mt->height/64*85; tx = Hunk_AllocName (sizeof(texture_t) +pixels, loadname ); loadmodel->textures[i] = tx; memcpy (tx->name, mt->name, sizeof(tx->name)); tx->width = mt->width; tx->height = mt->height; for (j=0 ; j<MIPLEVELS ; j++) tx->offsets[j] = mt->offsets[j] + sizeof(texture_t) - sizeof(miptex_t); // the pixels immediately follow the structures memcpy ( tx+1, mt+1, pixels); if (!Q_strncmp(mt->name,"sky",3)) R_InitSky (tx); else { texture_mode = GL_LINEAR_MIPMAP_NEAREST; //_LINEAR; tx->gl_texturenum = GL_LoadTexture (mt->name, tx->width, tx->height, (byte *)(tx+1), true, false); texture_mode = GL_LINEAR; } } // // sequence the animations // for (i=0 ; i<m->nummiptex ; i++) { tx = loadmodel->textures[i]; if (!tx || tx->name[0] != '+') continue; if (tx->anim_next) continue; // allready sequenced // find the number of frames in the animation memset (anims, 0, sizeof(anims)); memset (altanims, 0, sizeof(altanims)); max = tx->name[1]; altmax = 0; if (max >= 'a' && max <= 'z') max -= 'a' - 'A'; if (max >= '0' && max <= '9') { max -= '0'; altmax = 0; anims[max] = tx; max++; } else if (max >= 'A' && max <= 'J') { altmax = max - 'A'; max = 0; altanims[altmax] = tx; altmax++; } else Sys_Error ("Bad animating texture %s", tx->name); for (j=i+1 ; j<m->nummiptex ; j++) { tx2 = loadmodel->textures[j]; if (!tx2 || tx2->name[0] != '+') continue; if (strcmp (tx2->name+2, tx->name+2)) continue; num = tx2->name[1]; if (num >= 'a' && num <= 'z') num -= 'a' - 'A'; if (num >= '0' && num <= '9') { num -= '0'; anims[num] = tx2; if (num+1 > max) max = num + 1; } else if (num >= 'A' && num <= 'J') { num = num - 'A'; altanims[num] = tx2; if (num+1 > altmax) altmax = num+1; } else Sys_Error ("Bad animating texture %s", tx->name); } #define ANIM_CYCLE 2 // link them all together for (j=0 ; j<max ; j++) { tx2 = anims[j]; if (!tx2) Sys_Error ("Missing frame %i of %s",j, tx->name); tx2->anim_total = max * ANIM_CYCLE; tx2->anim_min = j * ANIM_CYCLE; tx2->anim_max = (j+1) * ANIM_CYCLE; tx2->anim_next = anims[ (j+1)%max ]; if (altmax) tx2->alternate_anims = altanims[0]; } for (j=0 ; j<altmax ; j++) { tx2 = altanims[j]; if (!tx2) Sys_Error ("Missing frame %i of %s",j, tx->name); tx2->anim_total = altmax * ANIM_CYCLE; tx2->anim_min = j * ANIM_CYCLE; tx2->anim_max = (j+1) * ANIM_CYCLE; tx2->anim_next = altanims[ (j+1)%altmax ]; if (max) tx2->alternate_anims = anims[0]; } } }
/* ================= Mod_LoadTextures ================= */ void Mod_LoadTextures (lump_t *l) { // 1999-12-28 OpenGL fullbright fix by Neal White III start // Neal White III - 12-28-1999 - OpenGL fullbright bugfix // [email protected] // http://home.telefragged.com/wally/ // // Problem: // // There was a problem in the original glquake with fullbright texels. // In the software renderer, fullbrights glow brightly in the dark. // Essentially, the fullbrights were ignored. I've fixed it by // adding another rendering pass and creating a new glowmap texture. // // Fix: // // When a texture with fullbright (FB) texels is loaded, a copy is made, // then the FB pixels are cleared to black in the original texture. In // the copy, all normal colors are cleared and only the FBs remain. When // it comes time to render the polygons, I do an additional pass and ADD // the glowmap on top of the current polygon. byte *ptexel; qboolean hasfullbrights; // qboolean noglow = COM_CheckParm("-noglow"); // int i, j, pixels, num, max, altmax; int i, num, max, altmax; unsigned long j, pixels; // 1999-12-28 OpenGL fullbright fix by Neal White III end miptex_t *mt; texture_t *tx, *tx2; texture_t *anims[10]; texture_t *altanims[10]; dmiptexlump_t *m; if (!l->filelen) { loadmodel->textures = NULL; return; } m = (dmiptexlump_t *)(mod_base + l->fileofs); m->nummiptex = LittleLong (m->nummiptex); loadmodel->numtextures = m->nummiptex; loadmodel->textures = Hunk_AllocName (m->nummiptex * sizeof(*loadmodel->textures) , loadname); for (i=0 ; i<m->nummiptex ; i++) { m->dataofs[i] = LittleLong(m->dataofs[i]); if (m->dataofs[i] == -1) continue; mt = (miptex_t *)((byte *)m + m->dataofs[i]); mt->width = LittleLong (mt->width); mt->height = LittleLong (mt->height); for (j=0 ; j<MIPLEVELS ; j++) mt->offsets[j] = LittleLong (mt->offsets[j]); if ( (mt->width & 15) || (mt->height & 15) ) Sys_Error ("Texture %s is not 16 aligned", mt->name); pixels = mt->width*mt->height/64*85; // 1999-12-28 OpenGL fullbright fix by Neal White III start hasfullbrights = false; if ((!strncmp(mt->name,"sky",3)) || (!strncmp(mt->name,"*",1)) || // turbulent (liquid) (!gl_glowmap->value) || (! gl_mtexable) ) { // sky has no lightmap, nor do liquids (so never needs a glowmap), // -noglow command line parameter, or no multi-texture support // // hasfullbrights is already false } else // check this texture for fullbright texels { ptexel = (byte *)(mt+1); for (j=0 ; j<pixels ; j++) { if (ptexel[j] >= 256-32) // 32 fullbright colors { hasfullbrights = true; break; } } } if (hasfullbrights) { tx = Hunk_AllocName (sizeof(texture_t) +pixels*2, loadname ); } else { // 1999-12-28 OpenGL fullbright fix by Neal White III end tx = Hunk_AllocName (sizeof(texture_t) +pixels, loadname ); } // 1999-12-28 OpenGL fullbright fix by Neal White III loadmodel->textures[i] = tx; memcpy (tx->name, mt->name, sizeof(tx->name)); tx->width = mt->width; tx->height = mt->height; for (j=0 ; j<MIPLEVELS ; j++) { // 1999-12-28 OpenGL fullbright fix by Neal White III tx->offsets[j] = mt->offsets[j] + sizeof(texture_t) - sizeof(miptex_t); // 1999-12-28 OpenGL fullbright fix by Neal White III start if (hasfullbrights) { tx->glowoffsets[j] = mt->offsets[j] + sizeof(texture_t) - sizeof(miptex_t) + pixels; } else { tx->glowoffsets[j] = 0; } } // 1999-12-28 OpenGL fullbright fix by Neal White III end // the pixels immediately follow the structures memcpy ( tx+1, mt+1, pixels); // 1999-12-28 OpenGL fullbright fix by Neal White III start if (hasfullbrights) { ptexel = (byte *)(tx+1); memcpy ( ptexel+pixels, mt+1, pixels); } tx->flags = 0; // 1999-12-28 OpenGL fullbright fix by Neal White III end if (!strncmp(mt->name,"sky",3)) // 2000-07-09 Dedicated server bug in GLQuake fix by Nathan Cline start { if (cls.state != ca_dedicated) { // 2000-07-09 Dedicated server bug in GLQuake fix by Nathan Cline end R_InitSky (tx); // 2000-07-09 Dedicated server bug in GLQuake fix by Nathan Cline start } } // 2000-07-09 Dedicated server bug in GLQuake fix by Nathan Cline end else { texture_mode = GL_LINEAR_MIPMAP_NEAREST; //_LINEAR; // 1999-12-28 OpenGL fullbright fix by Neal White III start // remove glowing fullbright colors from base texture (make black) if (hasfullbrights) { #ifdef _DEBUG qboolean bColorUsed[256]; Con_DPrintf ("*** Fullbright Texture: \"%s\", %dx%d, %d pixels\n", mt->name, mt->width, mt->height, pixels); for (j=0 ; j<256 ; j++) bColorUsed[j] = false; #endif ptexel = (byte *)(tx+1); for (j=0 ; j<pixels ; j++) { #ifdef _DEBUG bColorUsed[ptexel[j]] = true; #endif if (ptexel[j] >= 256-32) // 32 fullbright colors { ptexel[j] = 0; // make fullbrights black } } #ifdef _DEBUG Con_DPrintf ("*** Normal colors: "); for (j=0 ; j<256-32 ; j++) { if (bColorUsed[j]) Con_DPrintf ("%d ", j); } Con_DPrintf ("\n"); Con_DPrintf ("*** Fullbrights: "); for (j=256-32 ; j<256 ; j++) { if (bColorUsed[j]) Con_DPrintf ("%d ", j); } Con_DPrintf ("\n"); #endif } #ifdef _DEBUG else { Con_DPrintf ("*** Normal Texture: \"%s\", %dx%d\n", mt->name, mt->width, mt->height); } #endif // 1999-12-28 OpenGL fullbright fix by Neal White III end tx->gl_texturenum = GL_LoadTexture (mt->name, tx->width, tx->height, (byte *)(tx+1), true, false); // 1999-12-28 OpenGL fullbright fix by Neal White III start // create glowmap texture (all black except for glowing fullbright colors) if (hasfullbrights) { #ifdef _DEBUG qboolean bGlowDoubleCheck = false; #endif char glowname[32]; memcpy (glowname, mt->name, sizeof(mt->name)); glowname[16] = '\0'; for (j=0 ; glowname[j] != '\0'; j++) ; glowname[j++] = '<'; glowname[j++] = 'G'; glowname[j++] = 'L'; glowname[j++] = 'O'; glowname[j++] = 'W'; glowname[j++] = '>'; glowname[j++] = '\0'; ptexel = (byte *)(tx+1) + pixels; for (j=0 ; j<pixels ; j++) { if (ptexel[j] < 256-32) // build glowmap { ptexel[j] = 0; // make non-fullbrights black } #ifdef _DEBUG else { bGlowDoubleCheck = true; } #endif } tx->gl_glowtexnum = GL_LoadTexture (glowname, tx->width, tx->height, ptexel, true, false); tx->flags |= FLAG_HAS_GLOWMAP; #ifdef _DEBUG if (! bGlowDoubleCheck) Con_DPrintf ("INTERNAL ERROR: Mod_LoadTextures - FullBright texture \"%s\" has no FullBright colors!\n", glowname); #endif } // 1999-12-28 OpenGL fullbright fix by Neal White III end texture_mode = GL_LINEAR; } } // // sequence the animations // for (i=0 ; i<m->nummiptex ; i++) { tx = loadmodel->textures[i]; if (!tx || tx->name[0] != '+') continue; if (tx->anim_next) continue; // already sequenced // find the number of frames in the animation memset (anims, 0, sizeof(anims)); memset (altanims, 0, sizeof(altanims)); max = tx->name[1]; altmax = 0; if (max >= 'a' && max <= 'z') max -= 'a' - 'A'; if (max >= '0' && max <= '9') { max -= '0'; altmax = 0; anims[max] = tx; max++; } else if (max >= 'A' && max <= 'J') { altmax = max - 'A'; max = 0; altanims[altmax] = tx; altmax++; } else Sys_Error ("Bad animating texture %s", tx->name); for (j=i+1 ; j<m->nummiptex ; j++) { tx2 = loadmodel->textures[j]; if (!tx2 || tx2->name[0] != '+') continue; if (strcmp (tx2->name+2, tx->name+2)) continue; num = tx2->name[1]; if (num >= 'a' && num <= 'z') num -= 'a' - 'A'; if (num >= '0' && num <= '9') { num -= '0'; anims[num] = tx2; if (num+1 > max) max = num + 1; } else if (num >= 'A' && num <= 'J') { num = num - 'A'; altanims[num] = tx2; if (num+1 > altmax) altmax = num+1; } else Sys_Error ("Bad animating texture %s", tx->name); } #define ANIM_CYCLE 2 // link them all together for (j=0 ; j<max ; j++) { tx2 = anims[j]; if (!tx2) Sys_Error ("Missing frame %i of %s",j, tx->name); tx2->anim_total = max * ANIM_CYCLE; tx2->anim_min = j * ANIM_CYCLE; tx2->anim_max = (j+1) * ANIM_CYCLE; tx2->anim_next = anims[ (j+1)%max ]; if (altmax) tx2->alternate_anims = altanims[0]; } for (j=0 ; j<altmax ; j++) { tx2 = altanims[j]; if (!tx2) Sys_Error ("Missing frame %i of %s",j, tx->name); tx2->anim_total = altmax * ANIM_CYCLE; tx2->anim_min = j * ANIM_CYCLE; tx2->anim_max = (j+1) * ANIM_CYCLE; tx2->anim_next = altanims[ (j+1)%altmax ]; if (max) tx2->alternate_anims = anims[0]; } } }
void R_ReloadSky() { if (current_sky_mt) { R_InitSky(current_sky_mt); } }
/* ================= Mod_LoadTextures ================= */ void Mod_LoadTextures (lump_t *l) { int i, j, num, max, altmax, texture_flag, brighten_flag; miptex_t *mt; texture_t *tx, *tx2, *txblock, *anims[10], *altanims[10]; dmiptexlump_t *m; #ifndef RQM_SV_ONLY byte *data; #endif if (!l->filelen) { loadmodel->textures = NULL; return; } m = (dmiptexlump_t *)(mod_base + l->fileofs); m->nummiptex = LittleLong (m->nummiptex); loadmodel->numtextures = m->nummiptex; loadmodel->textures = Hunk_AllocName (m->nummiptex * sizeof(*loadmodel->textures), mod_loadname); txblock = Hunk_AllocName (m->nummiptex * sizeof(**loadmodel->textures), mod_loadname); #ifndef RQM_SV_ONLY #ifdef HEXEN2_SUPPORT if (hexen2) brighten_flag = 0; else #endif // brighten_flag = (gl_lightmode.value == 1) ? TEX_BRIGHTEN : 0; brighten_flag = 0; texture_flag = (gl_picmip_all.value || loadmodel->isworldmodel) ? TEX_MIPMAP : 0; #else brighten_flag = texture_flag = 0; #endif for (i = 0 ; i < m->nummiptex ; i++) { m->dataofs[i] = LittleLong (m->dataofs[i]); if (m->dataofs[i] == -1) continue; mt = (miptex_t *)((byte *)m + m->dataofs[i]); loadmodel->textures[i] = tx = txblock + i; memcpy (tx->name, mt->name, sizeof(tx->name)); if (!tx->name[0]) { Q_snprintfz (tx->name, sizeof(tx->name), "unnamed%d", i); Con_DPrintf ("Warning: unnamed texture in %s, renaming to %s\n", loadmodel->name, tx->name); } tx->width = mt->width = LittleLong (mt->width); tx->height = mt->height = LittleLong (mt->height); // if ((mt->width & 15) || (mt->height & 15)) // Host_Error ("Mod_LoadTextures: Texture %s is not 16 aligned", mt->name); // was Sys_Error for (j=0 ; j<MIPLEVELS ; j++) mt->offsets[j] = LittleLong (mt->offsets[j]); // HACK HACK HACK if (!strcmp(mt->name, "shot1sid") && mt->width == 32 && mt->height == 32 && CRC_Block((byte*)(mt+1), mt->width*mt->height) == 65393) { // This texture in b_shell1.bsp has some of the first 32 pixels painted white. // They are invisible in software, but look really ugly in GL. So we just copy // 32 pixels from the bottom to make it look nice. memcpy (mt+1, (byte *)(mt+1) + 32*31, 32); } #ifndef RQM_SV_ONLY if (loadmodel->isworldmodel && ISSKYTEX(tx->name)) { R_InitSky (mt); continue; } if (Mod_LoadBrushModelTexture(tx, texture_flag)) continue; if (mt->offsets[0]) { data = (byte *)mt + mt->offsets[0]; tx2 = tx; } else { data = (byte *)tx2 + tx2->offsets[0]; // JDH: what is tx2 equal to at this point ??? tx2 = r_notexture_mip; } #ifdef _DEBUG // for (j = tx2->width*tx2->height; j >= 0; j--) // if (data[j] == 255) // break; #endif // tx->gl_texturenum = GL_LoadTexture (tx2->name, tx2->width, tx2->height, data, texture_flag | brighten_flag, 1); tx->gl_texturenum = GL_LoadTexture (tx2->name, tx2->width, tx2->height, data, texture_flag | TEX_BMODEL, 1); if (!ISTURBTEX(tx->name) && Img_HasFullbrights(data, tx2->width * tx2->height)) tx->fb_texturenum = GL_LoadTexture (va("@fb_%s", tx2->name), tx2->width, tx2->height, data, texture_flag | TEX_FULLBRIGHT, 1); /************** JDH ***************/ else tx->fb_texturenum = 0; /************** JDH ***************/ #endif } // sequence the animations for (i=0 ; i<m->nummiptex ; i++) { tx = loadmodel->textures[i]; if (!tx || tx->name[0] != '+') continue; if (tx->anim_next) continue; // already sequenced // find the number of frames in the animation memset (anims, 0, sizeof(anims)); memset (altanims, 0, sizeof(altanims)); max = tx->name[1]; altmax = 0; if (max >= 'a' && max <= 'z') max -= 'a' - 'A'; if (max >= '0' && max <= '9') { max -= '0'; altmax = 0; anims[max] = tx; max++; } else if (max >= 'A' && max <= 'J') { altmax = max - 'A'; max = 0; altanims[altmax] = tx; altmax++; } else { Host_Error ("Bad animating texture %s", tx->name); // was Sys_Error } for (j=i+1 ; j<m->nummiptex ; j++) { tx2 = loadmodel->textures[j]; if (!tx2 || tx2->name[0] != '+') continue; if (strcmp(tx2->name+2, tx->name+2)) continue; num = tx2->name[1]; if (num >= 'a' && num <= 'z') num -= 'a' - 'A'; if (num >= '0' && num <= '9') { num -= '0'; anims[num] = tx2; if (num+1 > max) max = num + 1; } else if (num >= 'A' && num <= 'J') { num = num - 'A'; altanims[num] = tx2; if (num+1 > altmax) altmax = num+1; } else { Host_Error ("Bad animating texture %s", tx->name); // was Sys_Error } } #define ANIM_CYCLE 2 // link them all together for (j=0 ; j<max ; j++) { tx2 = anims[j]; if (!tx2) Host_Error ("Mod_LoadTextures: Missing frame %i of %s", j, tx->name); // was Sys_Error tx2->anim_total = max * ANIM_CYCLE; tx2->anim_min = j * ANIM_CYCLE; tx2->anim_max = (j+1) * ANIM_CYCLE; tx2->anim_next = anims[(j+1)%max]; if (altmax) tx2->alternate_anims = altanims[0]; } for (j=0 ; j<altmax ; j++) { tx2 = altanims[j]; if (!tx2) Host_Error ("Mod_LoadTextures: Missing frame %i of %s", j, tx->name); // was Sys_Error tx2->anim_total = altmax * ANIM_CYCLE; tx2->anim_min = j * ANIM_CYCLE; tx2->anim_max = (j+1) * ANIM_CYCLE; tx2->anim_next = altanims[(j+1)%altmax]; if (max) tx2->alternate_anims = anims[0]; } } }