X-Git-Url: https://git.xonotic.org/?a=blobdiff_plain;f=model_shared.c;h=393e7bb3baa8375e3fb7555625130a289ac8fc79;hb=527e9653a8a8f629a452a1b2a77347e149282349;hp=b9098816d0159d7b72492cb5ff0827507fe9e070;hpb=dc9c3c045d3685a2e32ace6cd30efe05114897fc;p=xonotic%2Fdarkplaces.git diff --git a/model_shared.c b/model_shared.c index b9098816..393e7bb3 100644 --- a/model_shared.c +++ b/model_shared.c @@ -26,6 +26,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "image.h" #include "r_shadow.h" +cvar_t r_mipskins = {CVAR_SAVE, "r_mipskins", "0"}; + model_t *loadmodel; // LordHavoc: increased from 512 to 2048 @@ -148,6 +150,7 @@ void Mod_Init (void) Mod_AliasInit(); Mod_SpriteInit(); + Cvar_RegisterVariable(&r_mipskins); Cmd_AddCommand ("modellist", Mod_Print); Cmd_AddCommand ("modelprecache", Mod_Precache); } @@ -775,7 +778,7 @@ int Mod_LoadSkinFrame(skinframe_t *skinframe, char *basename, int textureflags, skinframe->detail = mod_shared_detailtextures[(detailtexturecycle++) % NUM_DETAILTEXTURES]; skinframe->base = R_LoadTexture2D (loadmodel->texturepool, basename, s.basepixels_width, s.basepixels_height, s.basepixels, TEXTYPE_RGBA, textureflags, NULL); if (s.nmappixels != NULL) - skinframe->nmap = R_LoadTexture2D (loadmodel->texturepool, va("%s_nmap", basename), s.basepixels_width, s.basepixels_height, s.nmappixels, TEXTYPE_RGBA, textureflags, NULL); + skinframe->nmap = R_LoadTexture2D (loadmodel->texturepool, va("%s_nmap", basename), s.nmappixels_width, s.nmappixels_height, s.nmappixels, TEXTYPE_RGBA, textureflags, NULL); if (s.glosspixels != NULL) skinframe->gloss = R_LoadTexture2D (loadmodel->texturepool, va("%s_gloss", basename), s.glosspixels_width, s.glosspixels_height, s.glosspixels, TEXTYPE_RGBA, textureflags, NULL); if (s.glowpixels != NULL && loadglowtexture) @@ -899,3 +902,141 @@ void Mod_ConstructTerrainPatchFromRGBA(const qbyte *imagepixels, int imagewidth, Mod_GetTerrainVertexFromRGBA(imagepixels, imagewidth, imageheight, ix, iy, vertex3f, texcoord2f, svector3f, tvector3f, normal3f, pixelstepmatrix, pixeltexturestepmatrix); } +skinfile_t *Mod_LoadSkinFiles(void) +{ + int i, words, numtags, line, tagsetsused = false, wordsoverflow; + char *text; + const char *data; + skinfile_t *skinfile, *first = NULL; + skinfileitem_t *skinfileitem; + char word[10][MAX_QPATH]; + overridetagnameset_t tagsets[MAX_SKINS]; + overridetagname_t tags[256]; + +/* +sample file: +U_bodyBox,models/players/Legoman/BikerA2.tga +U_RArm,models/players/Legoman/BikerA1.tga +U_LArm,models/players/Legoman/BikerA1.tga +U_armor,common/nodraw +U_sword,common/nodraw +U_shield,common/nodraw +U_homb,common/nodraw +U_backpack,common/nodraw +U_colcha,common/nodraw +tag_head, +tag_weapon, +tag_torso, +*/ + memset(tagsets, 0, sizeof(tagsets)); + memset(word, 0, sizeof(word)); + for (i = 0;i < MAX_SKINS && (data = text = FS_LoadFile(va("%s_%i.skin", loadmodel->name, i), true));i++) + { + numtags = 0; + skinfile = Mem_Alloc(tempmempool, sizeof(skinfile_t)); + skinfile->next = first; + first = skinfile; + for(line = 0;;line++) + { + // parse line + if (!COM_ParseToken(&data, true)) + break; + if (!strcmp(com_token, "\n")) + continue; + words = 0; + wordsoverflow = false; + do + { + if (words < 10) + strncpy(word[words++], com_token, MAX_QPATH - 1); + else + wordsoverflow = true; + } + while (COM_ParseToken(&data, true) && strcmp(com_token, "\n")); + if (wordsoverflow) + { + Con_Printf("Mod_LoadSkinFiles: parsing error in file \"%s_%i.skin\" on line #%i: line with too many statements, skipping\n", loadmodel->name, i, line); + continue; + } + // words is always >= 1 + if (!strcmp(word[0], "replace")) + { + if (words == 3) + { + Con_DPrintf("Mod_LoadSkinFiles: parsed mesh \"%s\" shader replacement \"%s\"\n", word[1], word[2]); + skinfileitem = Mem_Alloc(tempmempool, sizeof(skinfileitem_t)); + skinfileitem->next = skinfile->items; + skinfile->items = skinfileitem; + strncpy(skinfileitem->name, word[1], sizeof(skinfileitem->name) - 1); + strncpy(skinfileitem->replacement, word[2], sizeof(skinfileitem->replacement) - 1); + } + else + Con_Printf("Mod_LoadSkinFiles: parsing error in file \"%s_%i.skin\" on line #%i: wrong number of parameters to command \"%s\", see documentation in DP_GFX_SKINFILES extension in dpextensions.qc\n", loadmodel->name, i, line, word[0]); + } + else if (words == 2 && !strcmp(word[1], ",")) + { + // tag name, like "tag_weapon," + Con_DPrintf("Mod_LoadSkinFiles: parsed tag #%i \"%s\"\n", numtags, word[0]); + memset(tags + numtags, 0, sizeof(tags[numtags])); + strncpy(tags[numtags].name, word[0], sizeof(tags[numtags].name) - 1); + numtags++; + } + else if (words == 3 && !strcmp(word[1], ",")) + { + // mesh shader name, like "U_RArm,models/players/Legoman/BikerA1.tga" + Con_DPrintf("Mod_LoadSkinFiles: parsed mesh \"%s\" shader replacement \"%s\"\n", word[0], word[2]); + skinfileitem = Mem_Alloc(tempmempool, sizeof(skinfileitem_t)); + skinfileitem->next = skinfile->items; + skinfile->items = skinfileitem; + strncpy(skinfileitem->name, word[0], sizeof(skinfileitem->name) - 1); + strncpy(skinfileitem->replacement, word[2], sizeof(skinfileitem->replacement) - 1); + } + else + Con_Printf("Mod_LoadSkinFiles: parsing error in file \"%s_%i.skin\" on line #%i: does not look like tag or mesh specification, or replace command, see documentation in DP_GFX_SKINFILES extension in dpextensions.qc\n", loadmodel->name, i, line); + } + Mem_Free(text); + + if (numtags) + { + overridetagnameset_t *t; + t = tagsets + i; + t->num_overridetagnames = numtags; + t->data_overridetagnames = Mem_Alloc(loadmodel->mempool, t->num_overridetagnames * sizeof(overridetagname_t)); + memcpy(t->data_overridetagnames, tags, t->num_overridetagnames * sizeof(overridetagname_t)); + tagsetsused = true; + } + } + if (tagsetsused) + { + loadmodel->data_overridetagnamesforskin = Mem_Alloc(loadmodel->mempool, i * sizeof(overridetagnameset_t)); + memcpy(loadmodel->data_overridetagnamesforskin, tagsets, i * sizeof(overridetagnameset_t)); + } + if (i) + loadmodel->numskins = i; + return first; +} + +void Mod_FreeSkinFiles(skinfile_t *skinfile) +{ + skinfile_t *next; + skinfileitem_t *skinfileitem, *nextitem; + for (;skinfile;skinfile = next) + { + next = skinfile->next; + for (skinfileitem = skinfile->items;skinfileitem;skinfileitem = nextitem) + { + nextitem = skinfileitem->next; + Mem_Free(skinfileitem); + } + Mem_Free(skinfile); + } +} + +int Mod_CountSkinFiles(skinfile_t *skinfile) +{ + int i; + for (i = 0;skinfile;skinfile = skinfile->next, i++); + return i; +} + +