X-Git-Url: http://de.git.xonotic.org/?a=blobdiff_plain;f=model_shared.c;h=2b9f947615d2f0f834547adfe9ca2037240fefd0;hb=2567e3f2ba76e6baa9dcffd22122866b2d9e4e1d;hp=0fee37121485fe29a90e2276d34a2c93ab796c4b;hpb=0cc298d3c03cc31166905b782f9f6545f8eee742;p=xonotic%2Fdarkplaces.git diff --git a/model_shared.c b/model_shared.c index 0fee3712..2b9f9476 100644 --- a/model_shared.c +++ b/model_shared.c @@ -26,7 +26,7 @@ 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"}; +cvar_t r_mipskins = {CVAR_SAVE, "r_mipskins", "0", "mipmaps skins (so they become blurrier in the distance), disabled by default because it tends to blur with strange border colors from the skin"}; model_t *loadmodel; @@ -95,8 +95,8 @@ void Mod_Init (void) Mod_SpriteInit(); Cvar_RegisterVariable(&r_mipskins); - Cmd_AddCommand ("modellist", Mod_Print); - Cmd_AddCommand ("modelprecache", Mod_Precache); + Cmd_AddCommand ("modellist", Mod_Print, "prints a list of loaded models"); + Cmd_AddCommand ("modelprecache", Mod_Precache, "load a model"); } void Mod_RenderInit(void) @@ -136,6 +136,7 @@ model_t *Mod_LoadModel(model_t *mod, qboolean crash, qboolean checkdisk, qboolea int num; unsigned int crc; void *buf; + fs_offset_t filesize; mod->used = true; @@ -150,10 +151,10 @@ model_t *Mod_LoadModel(model_t *mod, qboolean crash, qboolean checkdisk, qboolea { if (checkdisk && mod->loaded) Con_DPrintf("checking model %s\n", mod->name); - buf = FS_LoadFile (mod->name, tempmempool, false); + buf = FS_LoadFile (mod->name, tempmempool, false, &filesize); if (buf) { - crc = CRC_Block((qbyte *)buf, fs_filesize); + crc = CRC_Block((unsigned char *)buf, filesize); if (mod->crc != crc) mod->loaded = false; } @@ -163,7 +164,8 @@ model_t *Mod_LoadModel(model_t *mod, qboolean crash, qboolean checkdisk, qboolea Con_DPrintf("loading model %s\n", mod->name); // LordHavoc: unload the existing model in this slot (if there is one) - Mod_UnloadModel(mod); + if (mod->loaded) + Mod_UnloadModel(mod); // load the model mod->isworldmodel = isworldmodel; @@ -189,7 +191,7 @@ model_t *Mod_LoadModel(model_t *mod, qboolean crash, qboolean checkdisk, qboolea if (buf) { - char *bufend = (char *)buf + fs_filesize; + char *bufend = (char *)buf + filesize; num = LittleLong(*((int *)buf)); // call the apropriate loader loadmodel = mod; @@ -307,7 +309,7 @@ model_t *Mod_FindName(const char *name) return mod; } - Host_Error ("Mod_FindName: ran out of models\n"); + Host_Error ("Mod_FindName: ran out of models"); return NULL; } @@ -322,12 +324,12 @@ model_t *Mod_ForName(const char *name, qboolean crash, qboolean checkdisk, qbool { model_t *model; model = Mod_FindName(name); - if (!model->loaded || checkdisk) + if (model->name[0] != '*' && (!model->loaded || checkdisk)) Mod_LoadModel(model, crash, checkdisk, isworldmodel); return model; } -qbyte *mod_base; +unsigned char *mod_base; //============================================================================= @@ -364,8 +366,8 @@ static void Mod_Precache(void) int Mod_BuildVertexRemapTableFromElements(int numelements, const int *elements, int numvertices, int *remapvertices) { int i, count; - qbyte *used; - used = (qbyte *)Mem_Alloc(tempmempool, numvertices); + unsigned char *used; + used = (unsigned char *)Mem_Alloc(tempmempool, numvertices); memset(used, 0, numvertices); for (i = 0;i < numelements;i++) used[elements[i]] = 1; @@ -551,9 +553,9 @@ void Mod_BuildBumpVectors(const float *v0, const float *v1, const float *v2, con // 6 multiply, 9 subtract VectorSubtract(v1, v0, v10); VectorSubtract(v2, v0, v20); - normal3f[0] = v10[1] * v20[2] - v10[2] * v20[1]; - normal3f[1] = v10[2] * v20[0] - v10[0] * v20[2]; - normal3f[2] = v10[0] * v20[1] - v10[1] * v20[0]; + normal3f[0] = v20[1] * v10[2] - v20[2] * v10[1]; + normal3f[1] = v20[2] * v10[0] - v20[0] * v10[2]; + normal3f[2] = v20[0] * v10[1] - v20[1] * v10[0]; // 12 multiply, 10 subtract tc10[1] = tc1[1] - tc0[1]; tc20[1] = tc2[1] - tc0[1]; @@ -638,11 +640,11 @@ void Mod_BuildTextureVectorsAndNormals(int firstvertex, int numvertices, int num surfmesh_t *Mod_AllocSurfMesh(mempool_t *mempool, int numvertices, int numtriangles, qboolean lightmapoffsets, qboolean vertexcolors, qboolean neighbors) { surfmesh_t *mesh; - qbyte *data; + unsigned char *data; mesh = (surfmesh_t *)Mem_Alloc(mempool, sizeof(surfmesh_t) + numvertices * (3 + 3 + 3 + 3 + 2 + 2 + (vertexcolors ? 4 : 0)) * sizeof(float) + numvertices * (lightmapoffsets ? 1 : 0) * sizeof(int) + numtriangles * (3 + (neighbors ? 3 : 0)) * sizeof(int)); mesh->num_vertices = numvertices; mesh->num_triangles = numtriangles; - data = (qbyte *)(mesh + 1); + data = (unsigned char *)(mesh + 1); if (mesh->num_vertices) { mesh->data_vertex3f = (float *)data, data += sizeof(float[3]) * mesh->num_vertices; @@ -668,7 +670,7 @@ surfmesh_t *Mod_AllocSurfMesh(mempool_t *mempool, int numvertices, int numtriang shadowmesh_t *Mod_ShadowMesh_Alloc(mempool_t *mempool, int maxverts, int maxtriangles, rtexture_t *map_diffuse, rtexture_t *map_specular, rtexture_t *map_normal, int light, int neighbors, int expandable) { shadowmesh_t *newmesh; - qbyte *data; + unsigned char *data; int size; size = sizeof(shadowmesh_t); size += maxverts * sizeof(float[3]); @@ -679,7 +681,7 @@ shadowmesh_t *Mod_ShadowMesh_Alloc(mempool_t *mempool, int maxverts, int maxtria size += maxtriangles * sizeof(int[3]); if (expandable) size += SHADOWMESHVERTEXHASH * sizeof(shadowmeshvertexhash_t *) + maxverts * sizeof(shadowmeshvertexhash_t); - data = (qbyte *)Mem_Alloc(mempool, size); + data = (unsigned char *)Mem_Alloc(mempool, size); newmesh = (shadowmesh_t *)data;data += sizeof(*newmesh); newmesh->map_diffuse = map_diffuse; newmesh->map_specular = map_specular; @@ -907,19 +909,21 @@ void Mod_ShadowMesh_Free(shadowmesh_t *mesh) } } -static rtexture_t *GL_TextureForSkinLayer(const qbyte *in, int width, int height, const char *name, const unsigned int *palette, int textureflags) +static rtexture_t *GL_TextureForSkinLayer(const unsigned char *in, int width, int height, const char *name, const unsigned int *palette, int textureflags) { int i; for (i = 0;i < width*height;i++) - if (((qbyte *)&palette[in[i]])[3] > 0) + if (((unsigned char *)&palette[in[i]])[3] > 0) return R_LoadTexture2D (loadmodel->texturepool, name, width, height, in, TEXTYPE_PALETTE, textureflags, palette); return NULL; } -int Mod_LoadSkinFrame(skinframe_t *skinframe, char *basename, int textureflags, int loadpantsandshirt, int loadglowtexture) +int Mod_LoadSkinFrame(skinframe_t *skinframe, const char *basename, int textureflags, int loadpantsandshirt, int loadglowtexture) { imageskin_t s; memset(skinframe, 0, sizeof(*skinframe)); + if (cls.state == ca_dedicated) + return false; if (!image_loadskin(&s, basename)) return false; skinframe->base = R_LoadTexture2D (loadmodel->texturepool, basename, s.basepixels_width, s.basepixels_height, s.basepixels, TEXTYPE_RGBA, textureflags, NULL); @@ -946,50 +950,90 @@ int Mod_LoadSkinFrame(skinframe_t *skinframe, char *basename, int textureflags, return true; } -int Mod_LoadSkinFrame_Internal(skinframe_t *skinframe, char *basename, int textureflags, int loadpantsandshirt, int loadglowtexture, qbyte *skindata, int width, int height) +int Mod_LoadSkinFrame_Internal(skinframe_t *skinframe, const char *basename, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height, int bitsperpixel, const unsigned int *palette, const unsigned int *alphapalette) { - qbyte *temp1, *temp2; + int i; + unsigned char *temp1, *temp2; memset(skinframe, 0, sizeof(*skinframe)); + if (cls.state == ca_dedicated) + return false; if (!skindata) return false; - if (r_shadow_bumpscale_basetexture.value > 0) - { - temp1 = (qbyte *)Mem_Alloc(loadmodel->mempool, width * height * 8); - temp2 = temp1 + width * height * 4; - Image_Copy8bitRGBA(skindata, temp1, width * height, palette_nofullbrights); - Image_HeightmapToNormalmap(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value); - skinframe->nmap = R_LoadTexture2D(loadmodel->texturepool, va("%s_nmap", basename), width, height, temp2, TEXTYPE_RGBA, textureflags, NULL); - Mem_Free(temp1); - } - if (loadglowtexture) + if (bitsperpixel == 32) { - skinframe->glow = GL_TextureForSkinLayer(skindata, width, height, va("%s_glow", basename), palette_onlyfullbrights, textureflags); // glow - skinframe->base = skinframe->merged = GL_TextureForSkinLayer(skindata, width, height, va("%s_merged", basename), palette_nofullbrights, textureflags); // all but fullbrights - if (loadpantsandshirt) + if (r_shadow_bumpscale_basetexture.value > 0) { - skinframe->pants = GL_TextureForSkinLayer(skindata, width, height, va("%s_pants", basename), palette_pantsaswhite, textureflags); // pants - skinframe->shirt = GL_TextureForSkinLayer(skindata, width, height, va("%s_shirt", basename), palette_shirtaswhite, textureflags); // shirt - if (skinframe->pants || skinframe->shirt) - skinframe->base = GL_TextureForSkinLayer(skindata, width, height, va("%s_nospecial", basename), palette_nocolormapnofullbrights, textureflags); // no special colors + temp1 = (unsigned char *)Mem_Alloc(loadmodel->mempool, width * height * 8); + temp2 = temp1 + width * height * 4; + Image_HeightmapToNormalmap(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value); + skinframe->nmap = R_LoadTexture2D(loadmodel->texturepool, va("%s_nmap", basename), width, height, temp2, TEXTYPE_RGBA, textureflags | TEXF_ALPHA, NULL); + Mem_Free(temp1); + } + skinframe->base = skinframe->merged = R_LoadTexture2D(loadmodel->texturepool, basename, width, height, skindata, TEXTYPE_RGBA, textureflags, NULL); + if (textureflags & TEXF_ALPHA) + { + for (i = 3;i < width * height * 4;i += 4) + if (skindata[i] < 255) + break; + if (i < width * height * 4) + { + unsigned char *fogpixels = Mem_Alloc(loadmodel->mempool, width * height * 4); + memcpy(fogpixels, skindata, width * height * 4); + for (i = 0;i < width * height * 4;i += 4) + fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255; + skinframe->fog = R_LoadTexture2D(loadmodel->texturepool, va("%s_fog", basename), width, height, fogpixels, TEXTYPE_RGBA, textureflags, NULL); + Mem_Free(fogpixels); + } } } - else + else if (bitsperpixel == 8) { - skinframe->base = skinframe->merged = GL_TextureForSkinLayer(skindata, width, height, va("%s_merged", basename), palette_complete, textureflags); // all - if (loadpantsandshirt) + if (r_shadow_bumpscale_basetexture.value > 0) + { + temp1 = (unsigned char *)Mem_Alloc(loadmodel->mempool, width * height * 8); + temp2 = temp1 + width * height * 4; + if (bitsperpixel == 32) + Image_HeightmapToNormalmap(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value); + else + { + // use either a custom palette or the quake palette + Image_Copy8bitRGBA(skindata, temp1, width * height, palette ? palette : palette_complete); + Image_HeightmapToNormalmap(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value); + } + skinframe->nmap = R_LoadTexture2D(loadmodel->texturepool, va("%s_nmap", basename), width, height, temp2, TEXTYPE_RGBA, textureflags | TEXF_ALPHA, NULL); + Mem_Free(temp1); + } + // use either a custom palette, or the quake palette + skinframe->base = skinframe->merged = GL_TextureForSkinLayer(skindata, width, height, va("%s_merged", basename), palette ? palette : (loadglowtexture ? palette_nofullbrights : ((textureflags & TEXF_ALPHA) ? palette_transparent : palette_complete)), textureflags); // all + if (!palette && loadglowtexture) + skinframe->glow = GL_TextureForSkinLayer(skindata, width, height, va("%s_glow", basename), palette_onlyfullbrights, textureflags); // glow + if (!palette && loadpantsandshirt) { skinframe->pants = GL_TextureForSkinLayer(skindata, width, height, va("%s_pants", basename), palette_pantsaswhite, textureflags); // pants skinframe->shirt = GL_TextureForSkinLayer(skindata, width, height, va("%s_shirt", basename), palette_shirtaswhite, textureflags); // shirt - if (skinframe->pants || skinframe->shirt) - skinframe->base = GL_TextureForSkinLayer(skindata, width, height, va("%s_nospecial", basename), palette_nocolormap, textureflags); // no pants or shirt + } + if (skinframe->pants || skinframe->shirt) + skinframe->base = GL_TextureForSkinLayer(skindata, width, height, va("%s_nospecial", basename),loadglowtexture ? palette_nocolormapnofullbrights : palette_nocolormap, textureflags); // no special colors + if (textureflags & TEXF_ALPHA) + { + // if not using a custom alphapalette, use the quake one + if (!alphapalette) + alphapalette = palette_alpha; + for (i = 0;i < width * height;i++) + if (((unsigned char *)alphapalette)[skindata[i]*4+3] < 255) + break; + if (i < width * height) + skinframe->fog = GL_TextureForSkinLayer(skindata, width, height, va("%s_fog", basename), alphapalette, textureflags); // fog mask } } + else + return false; if (!skinframe->nmap) skinframe->nmap = r_texture_blanknormalmap; return true; } -void Mod_GetTerrainVertex3fTexCoord2fFromRGBA(const qbyte *imagepixels, int imagewidth, int imageheight, int ix, int iy, float *vertex3f, float *texcoord2f, matrix4x4_t *pixelstepmatrix, matrix4x4_t *pixeltexturestepmatrix) +void Mod_GetTerrainVertex3fTexCoord2fFromRGBA(const unsigned char *imagepixels, int imagewidth, int imageheight, int ix, int iy, float *vertex3f, float *texcoord2f, matrix4x4_t *pixelstepmatrix, matrix4x4_t *pixeltexturestepmatrix) { float v[3], tc[3]; v[0] = ix; @@ -1004,7 +1048,7 @@ void Mod_GetTerrainVertex3fTexCoord2fFromRGBA(const qbyte *imagepixels, int imag texcoord2f[1] = tc[1]; } -void Mod_GetTerrainVertexFromRGBA(const qbyte *imagepixels, int imagewidth, int imageheight, int ix, int iy, float *vertex3f, float *svector3f, float *tvector3f, float *normal3f, float *texcoord2f, matrix4x4_t *pixelstepmatrix, matrix4x4_t *pixeltexturestepmatrix) +void Mod_GetTerrainVertexFromRGBA(const unsigned char *imagepixels, int imagewidth, int imageheight, int ix, int iy, float *vertex3f, float *svector3f, float *tvector3f, float *normal3f, float *texcoord2f, matrix4x4_t *pixelstepmatrix, matrix4x4_t *pixeltexturestepmatrix) { float vup[3], vdown[3], vleft[3], vright[3]; float tcup[3], tcdown[3], tcleft[3], tcright[3]; @@ -1029,7 +1073,7 @@ void Mod_GetTerrainVertexFromRGBA(const qbyte *imagepixels, int imagewidth, int VectorAdd(normal3f, nl, normal3f); } -void Mod_ConstructTerrainPatchFromRGBA(const qbyte *imagepixels, int imagewidth, int imageheight, int x1, int y1, int width, int height, int *element3i, int *neighbor3i, float *vertex3f, float *svector3f, float *tvector3f, float *normal3f, float *texcoord2f, matrix4x4_t *pixelstepmatrix, matrix4x4_t *pixeltexturestepmatrix) +void Mod_ConstructTerrainPatchFromRGBA(const unsigned char *imagepixels, int imagewidth, int imageheight, int x1, int y1, int width, int height, int *element3i, int *neighbor3i, float *vertex3f, float *svector3f, float *tvector3f, float *normal3f, float *texcoord2f, matrix4x4_t *pixelstepmatrix, matrix4x4_t *pixeltexturestepmatrix) { int x, y, ix, iy, *e; e = element3i; @@ -1080,7 +1124,7 @@ tag_torso, */ memset(tagsets, 0, sizeof(tagsets)); memset(word, 0, sizeof(word)); - for (i = 0;i < MAX_SKINS && (data = text = (char *)FS_LoadFile(va("%s_%i.skin", loadmodel->name, i), tempmempool, true));i++) + for (i = 0;i < MAX_SKINS && (data = text = (char *)FS_LoadFile(va("%s_%i.skin", loadmodel->name, i), tempmempool, true, NULL));i++) { numtags = 0;