unified model skinframe loaders used for mdl, md2, md3, and bsp textures (both extern...
authorhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Sun, 22 Dec 2002 22:56:09 +0000 (22:56 +0000)
committerhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Sun, 22 Dec 2002 22:56:09 +0000 (22:56 +0000)
imageskin_t and image_loadskin/image_freeskin functions added to image.[ch] for use by the unified skinframe loaders
added palette_nocolormap
split r_shadow_bumpscale cvar into r_shadow_bumpscale_bumpmap (for _bump textures) and r_shadow_bumpscale_basetexture (self explanatory)
now loads _norm normalmap textures (tenebrae compatibility)
_nmap normalmap texture support removed (it was broken in the previous release and I don't need to bog down the texture loader with even more unnecessary names)
r_shadow_lightattenuationpower added (default 2, to leave it looking identical to previous versions, this controls the falloff curve of light)
renamed detailtextures array to mod_shared_detailtextures and moved it and related code to model_shared.[ch]
removed progs/missile.mdl shadow casting check (in r_shadow_realtime mode) I had forgotten to remove before committing last time

git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@2682 d7cf8633-e32d-0410-b094-e92efae38249

13 files changed:
gl_rmain.c
gl_rsurf.c
image.c
image.h
model_alias.c
model_brush.c
model_brush.h
model_shared.c
model_shared.h
palette.c
palette.h
r_shadow.c
r_shadow.h

index bedc8b8..902a06d 100644 (file)
@@ -915,7 +915,7 @@ void R_ShadowVolumeLighting (int visiblevolumes)
                        for (i = 0;i < r_refdef.numentities;i++)
                        {
                                ent = r_refdef.entities[i];
-                               if (ent->model && !strcmp(ent->model->name, "progs/missile.mdl"))
+                               if (ent->model)
                                        R_TestAndDrawShadowVolume(ent, wl->origin, cullradius, lightradius, wl->mins, wl->maxs, clipmins, clipmaxs);
                        }
                }
index 0c0c77a..61ea4d0 100644 (file)
@@ -817,7 +817,7 @@ static void RSurfShader_Water_Callback(const void *calldata1, int calldata2)
                m.blendfunc1 = GL_ONE;
                m.blendfunc2 = GL_ZERO;
        }
-       m.tex[0] = R_GetTexture(texture->texture);
+       m.tex[0] = R_GetTexture(texture->skin.base);
        colorscale = r_colorscale;
        if (gl_combine.integer)
        {
@@ -856,7 +856,7 @@ static void RSurfShader_Water_Callback(const void *calldata1, int calldata2)
                memset(&m, 0, sizeof(m));
                m.blendfunc1 = GL_SRC_ALPHA;
                m.blendfunc2 = GL_ONE;
-               m.tex[0] = R_GetTexture(texture->fogtexture);
+               m.tex[0] = R_GetTexture(texture->skin.fog);
                R_Mesh_State(&m);
                for (mesh = surf->mesh;mesh;mesh = mesh->chain)
                {
@@ -915,7 +915,7 @@ static void RSurfShader_Wall_Pass_BaseVertex(const entity_render_t *ent, const m
                m.blendfunc1 = GL_ONE;
                m.blendfunc2 = GL_ZERO;
        }
-       m.tex[0] = R_GetTexture(texture->texture);
+       m.tex[0] = R_GetTexture(texture->skin.base);
        colorscale = r_colorscale;
        if (gl_combine.integer)
        {
@@ -952,7 +952,7 @@ static void RSurfShader_Wall_Pass_Glow(const entity_render_t *ent, const msurfac
        memset(&m, 0, sizeof(m));
        m.blendfunc1 = GL_SRC_ALPHA;
        m.blendfunc2 = GL_ONE;
-       m.tex[0] = R_GetTexture(texture->glowtexture);
+       m.tex[0] = R_GetTexture(texture->skin.glow);
        R_Mesh_State(&m);
        GL_UseColorArray();
        for (mesh = surf->mesh;mesh;mesh = mesh->chain)
@@ -974,7 +974,7 @@ static void RSurfShader_Wall_Pass_Fog(const entity_render_t *ent, const msurface
        memset(&m, 0, sizeof(m));
        m.blendfunc1 = GL_SRC_ALPHA;
        m.blendfunc2 = GL_ONE;
-       m.tex[0] = R_GetTexture(texture->fogtexture);
+       m.tex[0] = R_GetTexture(texture->skin.fog);
        R_Mesh_State(&m);
        GL_UseColorArray();
        for (mesh = surf->mesh;mesh;mesh = mesh->chain)
@@ -998,9 +998,9 @@ static void RSurfShader_OpaqueWall_Pass_BaseTripleTexCombine(const entity_render
        memset(&m, 0, sizeof(m));
        m.blendfunc1 = GL_ONE;
        m.blendfunc2 = GL_ZERO;
-       m.tex[0] = R_GetTexture(texture->texture);
+       m.tex[0] = R_GetTexture(texture->skin.base);
        m.tex[1] = R_GetTexture((**surfchain).lightmaptexture);
-       m.tex[2] = R_GetTexture(texture->detailtexture);
+       m.tex[2] = R_GetTexture(texture->skin.detail);
        m.texrgbscale[0] = 1;
        m.texrgbscale[1] = 4;
        m.texrgbscale[2] = 2;
@@ -1039,7 +1039,7 @@ static void RSurfShader_OpaqueWall_Pass_BaseDoubleTex(const entity_render_t *ent
        memset(&m, 0, sizeof(m));
        m.blendfunc1 = GL_ONE;
        m.blendfunc2 = GL_ZERO;
-       m.tex[0] = R_GetTexture(texture->texture);
+       m.tex[0] = R_GetTexture(texture->skin.base);
        m.tex[1] = R_GetTexture((**surfchain).lightmaptexture);
        if (gl_combine.integer)
                m.texrgbscale[1] = 4;
@@ -1075,7 +1075,7 @@ static void RSurfShader_OpaqueWall_Pass_BaseTexture(const entity_render_t *ent,
        memset(&m, 0, sizeof(m));
        m.blendfunc1 = GL_ONE;
        m.blendfunc2 = GL_ZERO;
-       m.tex[0] = R_GetTexture(texture->texture);
+       m.tex[0] = R_GetTexture(texture->skin.base);
        R_Mesh_State(&m);
        GL_Color(1, 1, 1, 1);
        while((surf = *surfchain++) != NULL)
@@ -1138,7 +1138,7 @@ static void RSurfShader_OpaqueWall_Pass_Light(const entity_render_t *ent, const
        memset(&m, 0, sizeof(m));
        m.blendfunc1 = GL_SRC_ALPHA;
        m.blendfunc2 = GL_ONE;
-       m.tex[0] = R_GetTexture(texture->texture);
+       m.tex[0] = R_GetTexture(texture->skin.base);
        colorscale = r_colorscale;
        if (gl_combine.integer)
        {
@@ -1205,7 +1205,7 @@ static void RSurfShader_OpaqueWall_Pass_BaseDetail(const entity_render_t *ent, c
        memset(&m, 0, sizeof(m));
        m.blendfunc1 = GL_DST_COLOR;
        m.blendfunc2 = GL_SRC_COLOR;
-       m.tex[0] = R_GetTexture(texture->detailtexture);
+       m.tex[0] = R_GetTexture(texture->skin.detail);
        R_Mesh_State(&m);
        GL_Color(1, 1, 1, 1);
        while((surf = *surfchain++) != NULL)
@@ -1231,7 +1231,7 @@ static void RSurfShader_OpaqueWall_Pass_Glow(const entity_render_t *ent, const t
        memset(&m, 0, sizeof(m));
        m.blendfunc1 = GL_SRC_ALPHA;
        m.blendfunc2 = GL_ONE;
-       m.tex[0] = R_GetTexture(texture->glowtexture);
+       m.tex[0] = R_GetTexture(texture->skin.glow);
        R_Mesh_State(&m);
        GL_Color(r_colorscale, r_colorscale, r_colorscale, 1);
        while((surf = *surfchain++) != NULL)
@@ -1257,7 +1257,7 @@ static void RSurfShader_OpaqueWall_Pass_OpaqueGlow(const entity_render_t *ent, c
        memset(&m, 0, sizeof(m));
        m.blendfunc1 = GL_SRC_ALPHA;
        m.blendfunc2 = GL_ZERO;
-       m.tex[0] = R_GetTexture(texture->glowtexture);
+       m.tex[0] = R_GetTexture(texture->skin.glow);
        R_Mesh_State(&m);
        if (m.tex[0])
                GL_Color(r_colorscale, r_colorscale, r_colorscale, 1);
@@ -1296,13 +1296,13 @@ static void RSurfShader_Wall_Vertex_Callback(const void *calldata1, int calldata
                currentalpha *= r_wateralpha.value;
        if (ent->effects & EF_ADDITIVE)
                rendertype = SURFRENDER_ADD;
-       else if (currentalpha < 1 || texture->fogtexture != NULL)
+       else if (currentalpha < 1 || texture->skin.fog != NULL)
                rendertype = SURFRENDER_ALPHA;
        else
                rendertype = SURFRENDER_OPAQUE;
 
        RSurfShader_Wall_Pass_BaseVertex(ent, surf, texture, rendertype, currentalpha);
-       if (texture->glowtexture)
+       if (texture->skin.glow)
                RSurfShader_Wall_Pass_Glow(ent, surf, texture, rendertype, currentalpha);
        if (fogenabled)
                RSurfShader_Wall_Pass_Fog(ent, surf, texture, rendertype, currentalpha);
@@ -1338,7 +1338,7 @@ static void RSurfShader_Wall_Lightmap(const entity_render_t *ent, const texture_
                for (chain = surfchain;(surf = *chain) != NULL;chain++)
                        if (surf->visframe == r_framecount)
                                RSurfShader_Wall_Pass_BaseVertex(ent, surf, texture, texture->rendertype, texture->currentalpha);
-               if (texture->glowtexture)
+               if (texture->skin.glow)
                        for (chain = surfchain;(surf = *chain) != NULL;chain++)
                                if (surf->visframe == r_framecount)
                                        RSurfShader_Wall_Pass_Glow(ent, surf, texture, texture->rendertype, texture->currentalpha);
@@ -1370,7 +1370,7 @@ static void RSurfShader_Wall_Lightmap(const entity_render_t *ent, const texture_
                }
                if (!r_dlightmap.integer && !(ent->effects & EF_FULLBRIGHT))
                        RSurfShader_OpaqueWall_Pass_Light(ent, texture, surfchain);
-               if (texture->glowtexture)
+               if (texture->skin.glow)
                        RSurfShader_OpaqueWall_Pass_Glow(ent, texture, surfchain);
                if (fogenabled)
                        RSurfShader_OpaqueWall_Pass_Fog(ent, texture, surfchain);
@@ -1407,7 +1407,7 @@ void R_UpdateTextureInfo(entity_render_t *ent)
                        t->currentalpha *= r_wateralpha.value;
                if (ent->effects & EF_ADDITIVE)
                        t->rendertype = SURFRENDER_ADD;
-               else if (t->currentalpha < 1 || t->fogtexture != NULL)
+               else if (t->currentalpha < 1 || t->skin.fog != NULL)
                        t->rendertype = SURFRENDER_ALPHA;
                else
                        t->rendertype = SURFRENDER_OPAQUE;
@@ -1846,8 +1846,8 @@ void R_Model_Brush_DrawLightForSurfaceList(entity_render_t *ent, vec3_t relative
                                {
                                        R_Mesh_ResizeCheck(mesh->numverts);
                                        memcpy(varray_vertex, mesh->verts, mesh->numverts * sizeof(float[4]));
-                                       R_Shadow_DiffuseLighting(mesh->numverts, mesh->numtriangles, mesh->index, mesh->svectors, mesh->tvectors, mesh->normals, mesh->str, relativelightorigin, lightradius, lightcolor, t->texture, t->nmaptexture, NULL);
-                                       R_Shadow_SpecularLighting(mesh->numverts, mesh->numtriangles, mesh->index, mesh->svectors, mesh->tvectors, mesh->normals, mesh->str, relativelightorigin, relativeeyeorigin, lightradius, lightcolor, t->glosstexture, t->nmaptexture, NULL);
+                                       R_Shadow_DiffuseLighting(mesh->numverts, mesh->numtriangles, mesh->index, mesh->svectors, mesh->tvectors, mesh->normals, mesh->str, relativelightorigin, lightradius, lightcolor, t->skin.base, t->skin.nmap, NULL);
+                                       R_Shadow_SpecularLighting(mesh->numverts, mesh->numtriangles, mesh->index, mesh->svectors, mesh->tvectors, mesh->normals, mesh->str, relativelightorigin, relativeeyeorigin, lightradius, lightcolor, t->skin.gloss, t->skin.nmap, NULL);
                                }
                        }
                }
@@ -1891,8 +1891,8 @@ void R_Model_Brush_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, v
                                                        {
                                                                R_Mesh_ResizeCheck(mesh->numverts);
                                                                memcpy(varray_vertex, mesh->verts, mesh->numverts * sizeof(float[4]));
-                                                               R_Shadow_DiffuseLighting(mesh->numverts, mesh->numtriangles, mesh->index, mesh->svectors, mesh->tvectors, mesh->normals, mesh->str, relativelightorigin, lightradius, lightcolor, t->texture, t->nmaptexture, NULL);
-                                                               R_Shadow_SpecularLighting(mesh->numverts, mesh->numtriangles, mesh->index, mesh->svectors, mesh->tvectors, mesh->normals, mesh->str, relativelightorigin, relativeeyeorigin, lightradius, lightcolor, t->glosstexture, t->nmaptexture, NULL);
+                                                               R_Shadow_DiffuseLighting(mesh->numverts, mesh->numtriangles, mesh->index, mesh->svectors, mesh->tvectors, mesh->normals, mesh->str, relativelightorigin, lightradius, lightcolor, t->skin.base, t->skin.nmap, NULL);
+                                                               R_Shadow_SpecularLighting(mesh->numverts, mesh->numtriangles, mesh->index, mesh->svectors, mesh->tvectors, mesh->normals, mesh->str, relativelightorigin, relativeeyeorigin, lightradius, lightcolor, t->skin.gloss, t->skin.nmap, NULL);
                                                        }
                                                }
                                        }
@@ -1924,8 +1924,8 @@ void R_Model_Brush_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, v
                                                        {
                                                                R_Mesh_ResizeCheck(mesh->numverts);
                                                                memcpy(varray_vertex, mesh->verts, mesh->numverts * sizeof(float[4]));
-                                                               R_Shadow_DiffuseLighting(mesh->numverts, mesh->numtriangles, mesh->index, mesh->svectors, mesh->tvectors, mesh->normals, mesh->str, relativelightorigin, lightradius, lightcolor, t->texture, t->nmaptexture, NULL);
-                                                               R_Shadow_SpecularLighting(mesh->numverts, mesh->numtriangles, mesh->index, mesh->svectors, mesh->tvectors, mesh->normals, mesh->str, relativelightorigin, relativeeyeorigin, lightradius, lightcolor, t->glosstexture, t->nmaptexture, NULL);
+                                                               R_Shadow_DiffuseLighting(mesh->numverts, mesh->numtriangles, mesh->index, mesh->svectors, mesh->tvectors, mesh->normals, mesh->str, relativelightorigin, lightradius, lightcolor, t->skin.base, t->skin.nmap, NULL);
+                                                               R_Shadow_SpecularLighting(mesh->numverts, mesh->numtriangles, mesh->index, mesh->svectors, mesh->tvectors, mesh->normals, mesh->str, relativelightorigin, relativeeyeorigin, lightradius, lightcolor, t->skin.gloss, t->skin.nmap, NULL);
                                                        }
                                                }
                                        }
diff --git a/image.c b/image.c
index 8bb3d4d..c26befb 100644 (file)
--- a/image.c
+++ b/image.c
@@ -2,6 +2,7 @@
 #include "quakedef.h"
 #include "image.h"
 #include "jpeg.h"
+#include "r_shadow.h"
 
 int            image_width;
 int            image_height;
@@ -1347,7 +1348,6 @@ void Image_MipReduce(const qbyte *in, qbyte *out, int *width, int *height, int *
        }
 }
 
-extern cvar_t r_shadow_bumpscale;
 void Image_HeightmapToNormalmap(const unsigned char *inpixels, unsigned char *outpixels, int width, int height, int clamp, float bumpscale)
 {
        int x, y;
@@ -1356,7 +1356,7 @@ void Image_HeightmapToNormalmap(const unsigned char *inpixels, unsigned char *ou
        float iwidth, iheight, ibumpscale, n[3];
        iwidth = 1.0f / width;
        iheight = 1.0f / height;
-       ibumpscale = (255.0f * 3.0f) / (bumpscale * r_shadow_bumpscale.value);
+       ibumpscale = (255.0f * 3.0f) / bumpscale;
        out = outpixels;
        for (y = 0;y < height;y++)
        {
@@ -1404,3 +1404,113 @@ void Image_HeightmapToNormalmap(const unsigned char *inpixels, unsigned char *ou
                }
        }
 }
+
+int image_loadskin(imageskin_t *s, char *name)
+{
+       int j;
+       qbyte *bumppixels;
+       int bumppixels_width, bumppixels_height;
+       memset(s, 0, sizeof(*s));
+       s->basepixels = loadimagepixels(name, false, 0, 0);
+       if (s->basepixels == NULL)
+               return false;
+
+       bumppixels = NULL;bumppixels_width = 0;bumppixels_height = 0;
+       for (j = 3;j < s->basepixels_width * s->basepixels_height * 4;j += 4)
+               if (s->basepixels[j] < 255)
+                       break;
+       if (j < s->basepixels_width * s->basepixels_height * 4)
+       {
+               s->maskpixels = Mem_Alloc(loadmodel->mempool, s->basepixels_width * s->basepixels_height * 4);
+               s->maskpixels_width = s->basepixels_width;
+               s->maskpixels_height = s->basepixels_height;
+               memcpy(s->maskpixels, s->basepixels, s->maskpixels_width * s->maskpixels_height * 4);
+               for (j = 0;j < s->basepixels_width * s->basepixels_height * 4;j += 4)
+               {
+                       s->maskpixels[j+0] = 255;
+                       s->maskpixels[j+1] = 255;
+                       s->maskpixels[j+2] = 255;
+               }
+       }
+
+       // _luma is supported for tenebrae compatibility
+       // (I think it's a very stupid name, but oh well)
+       if ((s->glowpixels = loadimagepixels(va("%s_glow", name), false, 0, 0)) != NULL
+        || (s->glowpixels = loadimagepixels(va("%s_luma", name), false, 0, 0)) != NULL)
+       {
+               s->glowpixels_width = image_width;
+               s->glowpixels_height = image_height;
+       }
+       // _norm is the name used by tenebrae
+       // (I don't like the name much)
+       if ((s->nmappixels = loadimagepixels(va("%s_norm", name), false, 0, 0)) != NULL)
+       {
+               s->nmappixels_width = image_width;
+               s->nmappixels_height = image_height;
+       }
+       else if ((bumppixels = loadimagepixels(va("%s_bump", name), false, 0, 0)) != NULL)
+       {
+               bumppixels_width = image_width;
+               bumppixels_height = image_height;
+       }
+       if ((s->glosspixels = loadimagepixels(va("%s_gloss", name), false, 0, 0)) != NULL)
+       {
+               s->glosspixels_width = image_width;
+               s->glosspixels_height = image_height;
+       }
+       if ((s->pantspixels = loadimagepixels(va("%s_pants", name), false, 0, 0)) != NULL)
+       {
+               s->pantspixels_width = image_width;
+               s->pantspixels_height = image_height;
+       }
+       if ((s->shirtpixels = loadimagepixels(va("%s_shirt", name), false, 0, 0)) != NULL)
+       {
+               s->shirtpixels_width = image_width;
+               s->shirtpixels_height = image_height;
+       }
+
+       if (s->nmappixels == NULL)
+       {
+               if (bumppixels != NULL)
+               {
+                       if (r_shadow_bumpscale_bumpmap.value > 0)
+                       {
+                               s->nmappixels = Mem_Alloc(loadmodel->mempool, bumppixels_width * bumppixels_height * 4);
+                               s->nmappixels_width = bumppixels_width;
+                               s->nmappixels_height = bumppixels_height;
+                               Image_HeightmapToNormalmap(bumppixels, s->nmappixels, s->nmappixels_width, s->nmappixels_height, false, r_shadow_bumpscale_bumpmap.value);
+                       }
+               }
+               else
+               {
+                       if (r_shadow_bumpscale_basetexture.value > 0)
+                       {
+                               s->nmappixels = Mem_Alloc(loadmodel->mempool, s->basepixels_width * s->basepixels_height * 4);
+                               s->nmappixels_width = s->basepixels_width;
+                               s->nmappixels_height = s->basepixels_height;
+                               Image_HeightmapToNormalmap(s->basepixels, s->nmappixels, s->nmappixels_width, s->nmappixels_height, false, r_shadow_bumpscale_basetexture.value);
+                       }
+               }
+       }
+       if (bumppixels != NULL)
+               Mem_Free(bumppixels);
+       return true;
+}
+
+void image_freeskin(imageskin_t *s)
+{
+       if (s->basepixels)
+               Mem_Free(s->basepixels);
+       if (s->nmappixels)
+               Mem_Free(s->nmappixels);
+       if (s->glowpixels)
+               Mem_Free(s->glowpixels);
+       if (s->glosspixels)
+               Mem_Free(s->glosspixels);
+       if (s->pantspixels)
+               Mem_Free(s->pantspixels);
+       if (s->shirtpixels)
+               Mem_Free(s->shirtpixels);
+       memset(s, 0, sizeof(*s));
+}
+
diff --git a/image.h b/image.h
index 2d26d29..c2edabd 100644 (file)
--- a/image.h
+++ b/image.h
@@ -53,5 +53,20 @@ qbyte *LoadLMPAs8Bit (const qbyte *f, int matchwidth, int matchheight);
 
 void Image_HeightmapToNormalmap(const unsigned char *inpixels, unsigned char *outpixels, int width, int height, int clamp, float bumpscale);
 
+typedef struct imageskin_s
+{
+       qbyte *basepixels;int basepixels_width;int basepixels_height;
+       qbyte *nmappixels;int nmappixels_width;int nmappixels_height;
+       qbyte *glowpixels;int glowpixels_width;int glowpixels_height;
+       qbyte *glosspixels;int glosspixels_width;int glosspixels_height;
+       qbyte *pantspixels;int pantspixels_width;int pantspixels_height;
+       qbyte *shirtpixels;int shirtpixels_width;int shirtpixels_height;
+       qbyte *maskpixels;int maskpixels_width;int maskpixels_height;
+}
+imageskin_t;
+
+int image_loadskin(imageskin_t *s, char *name);
+void image_freeskin(imageskin_t *s);
+
 #endif
 
index 53a1395..4912638 100644 (file)
@@ -20,6 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
 #include "quakedef.h"
 #include "image.h"
+#include "r_shadow.h"
 
 static cvar_t r_mipskins = {CVAR_SAVE, "r_mipskins", "0"};
 
@@ -177,72 +178,6 @@ static void Mod_MDL_LoadFrames (qbyte* datapointer, int inverts, int outverts, v
        Mem_Free(vertexbuffer);
 }
 
-static rtexture_t *GL_TextureForSkinLayer(const qbyte *in, int width, int height, const char *name, const unsigned int *palette, int precache)
-{
-       int i;
-       for (i = 0;i < width*height;i++)
-               if (((qbyte *)&palette[in[i]])[3] > 0)
-                       return R_LoadTexture2D (loadmodel->texturepool, name, width, height, in, TEXTYPE_PALETTE, (r_mipskins.integer ? TEXF_MIPMAP : 0) | (precache ? TEXF_PRECACHE : 0), palette);
-       return NULL;
-}
-
-static int Mod_LoadExternalSkin (char *basename, skinframe_t *skinframe, int precache)
-{
-       skinframe->nmap   = loadtextureimage(loadmodel->texturepool, va("%s_nmap" , basename), 0, 0, false, (precache ? TEXF_PRECACHE : 0) | (r_mipskins.integer ? TEXF_MIPMAP : 0));
-       if (skinframe->nmap == NULL)
-               skinframe->nmap   = loadtextureimagebumpasnmap(loadmodel->texturepool, va("%s_bump" , basename), 0, 0, false, (precache ? TEXF_PRECACHE : 0) | (r_mipskins.integer ? TEXF_MIPMAP : 0), 1);
-       if (skinframe->nmap != NULL)
-       {
-               skinframe->base   = loadtextureimagewithmask(loadmodel->texturepool, va("%s_normal", basename), 0, 0, false, TEXF_ALPHA | (precache ? TEXF_PRECACHE : 0) | (r_mipskins.integer ? TEXF_MIPMAP : 0));
-               if (skinframe->base == NULL)
-                       skinframe->base   = loadtextureimagewithmask(loadmodel->texturepool, basename, 0, 0, false, TEXF_ALPHA | (precache ? TEXF_PRECACHE : 0) | (r_mipskins.integer ? TEXF_MIPMAP : 0));
-               skinframe->fog    = image_masktex;
-       }
-       else
-       {
-               skinframe->base   = loadtextureimagewithmaskandnmap(loadmodel->texturepool, va("%s_normal", basename), 0, 0, false, TEXF_ALPHA | (precache ? TEXF_PRECACHE : 0) | (r_mipskins.integer ? TEXF_MIPMAP : 0), 1);
-               if (skinframe->base == NULL)
-                       skinframe->base   = loadtextureimagewithmaskandnmap(loadmodel->texturepool, basename, 0, 0, false, TEXF_ALPHA | (precache ? TEXF_PRECACHE : 0) | (r_mipskins.integer ? TEXF_MIPMAP : 0), 1);
-               skinframe->fog    = image_masktex;
-               skinframe->nmap   = image_nmaptex;
-       }
-       skinframe->gloss  = loadtextureimage(loadmodel->texturepool, va("%s_gloss" , basename), 0, 0, false, TEXF_ALPHA | (precache ? TEXF_PRECACHE : 0) | (r_mipskins.integer ? TEXF_MIPMAP : 0));
-       skinframe->pants  = loadtextureimage(loadmodel->texturepool, va("%s_pants" , basename), 0, 0, false, TEXF_ALPHA | (precache ? TEXF_PRECACHE : 0) | (r_mipskins.integer ? TEXF_MIPMAP : 0));
-       skinframe->shirt  = loadtextureimage(loadmodel->texturepool, va("%s_shirt" , basename), 0, 0, false, TEXF_ALPHA | (precache ? TEXF_PRECACHE : 0) | (r_mipskins.integer ? TEXF_MIPMAP : 0));
-       skinframe->glow   = loadtextureimage(loadmodel->texturepool, va("%s_glow"  , basename), 0, 0, false, TEXF_ALPHA | (precache ? TEXF_PRECACHE : 0) | (r_mipskins.integer ? TEXF_MIPMAP : 0));
-       if (skinframe->glow == NULL)
-               skinframe->glow = loadtextureimage(loadmodel->texturepool, va("%s_luma"  , basename), 0, 0, false, TEXF_ALPHA | (precache ? TEXF_PRECACHE : 0) | (r_mipskins.integer ? TEXF_MIPMAP : 0));
-       skinframe->merged = skinframe->base;
-       return skinframe->base != NULL || skinframe->pants != NULL || skinframe->shirt != NULL || skinframe->glow != NULL;
-}
-
-static int Mod_LoadInternalSkin (char *basename, qbyte *skindata, int width, int height, skinframe_t *skinframe, int precache)
-{
-       qbyte *temp1, *temp2;
-       if (!skindata)
-               return false;
-       temp1 = 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, 1);
-       skinframe->nmap   = R_LoadTexture2D(loadmodel->texturepool, va("%s_nmap", basename), width, height, temp2, TEXTYPE_RGBA, (r_mipskins.integer ? TEXF_MIPMAP : 0) | (precache ? TEXF_PRECACHE : 0), NULL);
-       Mem_Free(temp1);
-       skinframe->gloss  = NULL;
-       skinframe->pants  = GL_TextureForSkinLayer(skindata, width, height, va("%s_pants", basename), palette_pantsaswhite, false); // pants
-       skinframe->shirt  = GL_TextureForSkinLayer(skindata, width, height, va("%s_shirt", basename), palette_shirtaswhite, false); // shirt
-       skinframe->glow   = GL_TextureForSkinLayer(skindata, width, height, va("%s_glow", basename), palette_onlyfullbrights, precache); // glow
-       if (skinframe->pants || skinframe->shirt)
-       {
-               skinframe->base   = GL_TextureForSkinLayer(skindata, width, height, va("%s_normal", basename), palette_nocolormapnofullbrights, false); // normal (no special colors)
-               skinframe->merged = GL_TextureForSkinLayer(skindata, width, height, va("%s_body", basename), palette_nofullbrights, precache); // body (normal + pants + shirt, but not glow)
-       }
-       else
-               skinframe->base   = GL_TextureForSkinLayer(skindata, width, height, va("%s_base", basename), palette_nofullbrights, precache); // no special colors
-       // quake model skins don't have alpha
-       skinframe->fog = NULL;
-       return true;
-}
-
 void Mod_BuildAliasSkinFromSkinFrame(aliasskin_t *skin, skinframe_t *skinframe)
 {
        aliaslayer_t *layer;
@@ -528,8 +463,8 @@ void Mod_LoadQ1AliasModel (model_t *mod, void *buffer)
                                sprintf (name, "%s_%i_%i", loadmodel->name, i, j);
                        else
                                sprintf (name, "%s_%i", loadmodel->name, i);
-                       if (!Mod_LoadExternalSkin(name, loadmodel->skinframes + totalskins, i == 0))
-                               Mod_LoadInternalSkin(name, (qbyte *)datapointer, skinwidth, skinheight, loadmodel->skinframes + totalskins, i == 0);
+                       if (!Mod_LoadSkinFrame(loadmodel->skinframes + totalskins, name, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA, true, false, true))
+                               Mod_LoadSkinFrame_Internal(loadmodel->skinframes + totalskins, name, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA, true, false, true, (qbyte *)datapointer, skinwidth, skinheight);
                        datapointer += skinwidth * skinheight;
                        totalskins++;
                }
@@ -539,7 +474,7 @@ void Mod_LoadQ1AliasModel (model_t *mod, void *buffer)
        for (;;)
        {
                sprintf (name, "%s_%i", loadmodel->name, loadmodel->numskins);
-               if (Mod_LoadExternalSkin(name, &tempskinframe, loadmodel->numskins == 0))
+               if (Mod_LoadSkinFrame (&tempskinframe, name, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA, true, false, true))
                {
                        // expand the arrays to make room
                        tempskinscenes = loadmodel->skinscenes;
@@ -725,7 +660,7 @@ void Mod_LoadQ2AliasModel (model_t *mod, void *buffer)
                        loadmodel->skinscenes[i].framecount = 1;
                        loadmodel->skinscenes[i].loop = true;
                        loadmodel->skinscenes[i].framerate = 10;
-                       Mod_LoadExternalSkin (inskin, loadmodel->skinframes + i, true);
+                       Mod_LoadSkinFrame (loadmodel->skinframes + i, inskin, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PRECACHE, true, false, true);
                        inskin += MD2MAX_SKINNAME;
                }
        }
@@ -934,7 +869,7 @@ void Mod_LoadQ3AliasModel(model_t *mod, void *buffer)
 
                memset(&tempskinframe, 0, sizeof(tempskinframe));
                if (LittleLong(pinmesh->num_shaders) >= 1 && ((md3shader_t *)((qbyte *) pinmesh + pinmesh->lump_shaders))->name[0])
-                       Mod_LoadExternalSkin (((md3shader_t *)((qbyte *) pinmesh + pinmesh->lump_shaders))->name, &tempskinframe, true);
+                       Mod_LoadSkinFrame (&tempskinframe, ((md3shader_t *)((qbyte *) pinmesh + pinmesh->lump_shaders))->name, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PRECACHE, true, false, true);
                Mod_ValidateElements(mesh->data_elements, mesh->num_triangles, mesh->num_vertices, __FILE__, __LINE__);
                Mod_BuildTriangleNeighbors(mesh->data_neighbors, mesh->data_elements, mesh->num_triangles);
                Mod_BuildAliasSkinFromSkinFrame(mesh->data_skins, &tempskinframe);
@@ -1040,12 +975,6 @@ void Mod_LoadZymoticModel(model_t *mod, void *buffer)
                loadmodel->skinscenes[0].loop = true;
                loadmodel->skinscenes[0].framerate = 10;
                loadmodel->skinframes = (void *)(loadmodel->skinscenes + 1);
-               loadmodel->skinframes->base = NULL;
-               loadmodel->skinframes->fog = NULL;
-               loadmodel->skinframes->pants = NULL;
-               loadmodel->skinframes->shirt = NULL;
-               loadmodel->skinframes->glow = NULL;
-               loadmodel->skinframes->merged = NULL;
                loadmodel->numskins = 1;
        }
 
index 4959d8c..6e7c54f 100644 (file)
@@ -20,6 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
 #include "quakedef.h"
 #include "image.h"
+#include "r_shadow.h"
 
 // note: model_shared.c sets up r_notexture, and r_surf_notexture
 
@@ -33,10 +34,6 @@ cvar_t r_lightmaprgba = {0, "r_lightmaprgba", "1"};
 cvar_t r_nosurftextures = {0, "r_nosurftextures", "0"};
 cvar_t r_sortsurfaces = {0, "r_sortsurfaces", "0"};
 
-#define NUM_DETAILTEXTURES 1
-static rtexture_t *detailtextures[NUM_DETAILTEXTURES];
-static rtexturepool_t *detailtexturepool;
-
 /*
 ===============
 Mod_BrushInit
@@ -54,55 +51,6 @@ void Mod_BrushInit (void)
        memset(mod_novis, 0xff, sizeof(mod_novis));
 }
 
-void Mod_BrushStartup (void)
-{
-       int i, x, y, light;
-       float vc[3], vx[3], vy[3], vn[3], lightdir[3];
-#define DETAILRESOLUTION 256
-       qbyte data[DETAILRESOLUTION][DETAILRESOLUTION][4], noise[DETAILRESOLUTION][DETAILRESOLUTION];
-       detailtexturepool = R_AllocTexturePool();
-       lightdir[0] = 0.5;
-       lightdir[1] = 1;
-       lightdir[2] = -0.25;
-       VectorNormalize(lightdir);
-       for (i = 0;i < NUM_DETAILTEXTURES;i++)
-       {
-               fractalnoise(&noise[0][0], DETAILRESOLUTION, DETAILRESOLUTION >> 4);
-               for (y = 0;y < DETAILRESOLUTION;y++)
-               {
-                       for (x = 0;x < DETAILRESOLUTION;x++)
-                       {
-                               vc[0] = x;
-                               vc[1] = y;
-                               vc[2] = noise[y][x] * (1.0f / 32.0f);
-                               vx[0] = x + 1;
-                               vx[1] = y;
-                               vx[2] = noise[y][(x + 1) % DETAILRESOLUTION] * (1.0f / 32.0f);
-                               vy[0] = x;
-                               vy[1] = y + 1;
-                               vy[2] = noise[(y + 1) % DETAILRESOLUTION][x] * (1.0f / 32.0f);
-                               VectorSubtract(vx, vc, vx);
-                               VectorSubtract(vy, vc, vy);
-                               CrossProduct(vx, vy, vn);
-                               VectorNormalize(vn);
-                               light = 128 - DotProduct(vn, lightdir) * 128;
-                               light = bound(0, light, 255);
-                               data[y][x][0] = data[y][x][1] = data[y][x][2] = light;
-                               data[y][x][3] = 255;
-                       }
-               }
-               detailtextures[i] = R_LoadTexture2D(detailtexturepool, va("detailtexture%i", i), DETAILRESOLUTION, DETAILRESOLUTION, &data[0][0][0], TEXTYPE_RGBA, TEXF_MIPMAP | TEXF_PRECACHE, NULL);
-       }
-}
-
-void Mod_BrushShutdown (void)
-{
-       int i;
-       for (i = 0;i < NUM_DETAILTEXTURES;i++)
-               R_FreeTexture(detailtextures[i]);
-       R_FreeTexturePool(&detailtexturepool);
-}
-
 /*
 ===============
 Mod_PointInLeaf
@@ -214,11 +162,6 @@ static void Mod_LoadTextures (lump_t *l)
        dmiptexlump_t *m;
        qbyte *data, *mtdata;
        char name[256];
-       qbyte *basepixels, *bumppixels, *nmappixels, *glosspixels, *glowpixels, *maskpixels;
-       int basepixels_width, basepixels_height, bumppixels_width, bumppixels_height;
-       int nmappixels_width, nmappixels_height, glosspixels_width, glosspixels_height;
-       int glowpixels_width, glowpixels_height, maskpixels_width, maskpixels_height;
-       rtexture_t *detailtexture;
 
        loadmodel->textures = NULL;
 
@@ -237,9 +180,10 @@ static void Mod_LoadTextures (lump_t *l)
        for (i = 0, tx = loadmodel->textures;i < loadmodel->numtextures;i++, tx++)
        {
                tx->number = i;
+               strcpy(tx->name, "NO TEXTURE FOUND");
                tx->width = 16;
                tx->height = 16;
-               tx->texture = r_notexture;
+               tx->skin.base = r_notexture;
                tx->shader = &Cshader_wall_lightmap;
                if (i == loadmodel->numtextures - 1)
                {
@@ -298,14 +242,6 @@ static void Mod_LoadTextures (lump_t *l)
                        Con_Printf("warning: unnamed texture in %s, renaming to %s\n", loadmodel->name, tx->name);
                }
 
-               basepixels = NULL;basepixels_width = 0;basepixels_height = 0;
-               bumppixels = NULL;bumppixels_width = 0;bumppixels_height = 0;
-               nmappixels = NULL;nmappixels_width = 0;nmappixels_height = 0;
-               glosspixels = NULL;glosspixels_width = 0;glosspixels_height = 0;
-               glowpixels = NULL;glowpixels_width = 0;glowpixels_height = 0;
-               maskpixels = NULL;maskpixels_width = 0;maskpixels_height = 0;
-               detailtexture = NULL;
-
                // LordHavoc: HL sky textures are entirely different than quake
                if (!loadmodel->ishlbsp && !strncmp(tx->name, "sky", 3) && mtwidth == 256 && mtheight == 128)
                {
@@ -333,159 +269,38 @@ static void Mod_LoadTextures (lump_t *l)
                }
                else
                {
-                       if ((basepixels = loadimagepixels(tx->name, false, 0, 0)) != NULL)
-                       {
-                               basepixels_width = image_width;
-                               basepixels_height = image_height;
-                       }
-                       // _luma is supported for tenebrae compatibility
-                       // (I think it's a very stupid name, but oh well)
-                       if ((glowpixels = loadimagepixels(va("%s_glow", tx->name), false, 0, 0)) != NULL
-                        || (glowpixels = loadimagepixels(va("%s_luma", tx->name), false, 0, 0)) != NULL)
-                       {
-                               glowpixels_width = image_width;
-                               glowpixels_height = image_height;
-                       }
-                       if ((bumppixels = loadimagepixels(va("%s_bump", tx->name), false, 0, 0)) != NULL)
-                       {
-                               bumppixels_width = image_width;
-                               bumppixels_height = image_height;
-                       }
-                       if ((glosspixels = loadimagepixels(va("%s_gloss", tx->name), false, 0, 0)) != NULL)
-                       {
-                               glosspixels_width = image_width;
-                               glosspixels_height = image_height;
-                       }
-                       if (!basepixels)
+                       if (!Mod_LoadSkinFrame(&tx->skin, tx->name, TEXF_MIPMAP | TEXF_ALPHA | TEXF_PRECACHE, false, true, true))
                        {
+                               // did not find external texture, load it from the bsp or wad3
                                if (loadmodel->ishlbsp)
                                {
                                        // internal texture overrides wad
-                                       if (mtdata && (basepixels = W_ConvertWAD3Texture(dmiptex)) != NULL)
-                                       {
-                                               basepixels_width = image_width;
-                                               basepixels_height = image_height;
-                                       }
-                                       else if ((basepixels = W_GetTexture(tx->name)) != NULL)
-                                       {
-                                               // get the size from the wad texture
-                                               tx->width = basepixels_width = image_width;
-                                               tx->height = basepixels_height = image_height;
-                                       }
-                               }
-                               else
-                               {
-                                       if (mtdata) // texture included
+                                       qbyte *pixels, *freepixels;
+                                       pixels = freepixels = NULL;
+                                       if (mtdata)
+                                               pixels = W_ConvertWAD3Texture(dmiptex);
+                                       if (pixels == NULL)
+                                               pixels = freepixels = W_GetTexture(tx->name);
+                                       if (pixels != NULL)
                                        {
-                                               if (r_fullbrights.integer && tx->name[0] != '*')
-                                               {
-                                                       basepixels_width = tx->width;
-                                                       basepixels_height = tx->height;
-                                                       basepixels = Mem_Alloc(loadmodel->mempool, basepixels_width * basepixels_height * 4);
-                                                       Image_Copy8bitRGBA(mtdata, basepixels, basepixels_width * basepixels_height, palette_nofullbrights);
-                                                       if (!glowpixels)
-                                                       {
-                                                               for (j = 0;j < (int)(tx->width*tx->height);j++)
-                                                                       if (((qbyte *)&palette_onlyfullbrights[mtdata[j]])[3] > 0) // fullbright
-                                                                               break;
-                                                               if (j < (int)(tx->width * tx->height))
-                                                               {
-                                                                       glowpixels_width = tx->width;
-                                                                       glowpixels_height = tx->height;
-                                                                       glowpixels = Mem_Alloc(loadmodel->mempool, glowpixels_width * glowpixels_height * 4);
-                                                                       Image_Copy8bitRGBA(mtdata, glowpixels, glowpixels_width * glowpixels_height, palette_onlyfullbrights);
-                                                               }
-                                                       }
-                                               }
-                                               else
-                                               {
-                                                       basepixels_width = tx->width;
-                                                       basepixels_height = tx->height;
-                                                       basepixels = Mem_Alloc(loadmodel->mempool, basepixels_width * basepixels_height * 4);
-                                                       Image_Copy8bitRGBA(mtdata, basepixels, tx->width * tx->height, palette_complete);
-                                               }
+                                               tx->width = image_width;
+                                               tx->height = image_height;
+                                               tx->skin.base = tx->skin.merged = R_LoadTexture2D(loadmodel->texturepool, tx->name, image_width, image_height, pixels, TEXTYPE_RGBA, TEXF_MIPMAP | TEXF_ALPHA | TEXF_PRECACHE, NULL);
                                        }
+                                       if (freepixels)
+                                               Mem_Free(freepixels);
                                }
+                               else if (mtdata) // texture included
+                                       Mod_LoadSkinFrame_Internal(&tx->skin, tx->name, TEXF_MIPMAP | TEXF_ALPHA | TEXF_PRECACHE, false, true, tx->name[0] != '*' && r_fullbrights.integer, mtdata, tx->width, tx->height);
                        }
                }
-
-               if (basepixels)
-               {
-                       for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
-                               if (basepixels[j] < 255)
-                                       break;
-                       if (j < basepixels_width * basepixels_height * 4)
-                       {
-                               maskpixels = Mem_Alloc(loadmodel->mempool, basepixels_width * basepixels_height * 4);
-                               maskpixels_width = basepixels_width;
-                               maskpixels_height = basepixels_height;
-                               for (j = 0;j < basepixels_width * basepixels_height * 4;j += 4)
-                               {
-                                       maskpixels[j+0] = 255;
-                                       maskpixels[j+1] = 255;
-                                       maskpixels[j+2] = 255;
-                                       maskpixels[j+3] = basepixels[j+3];
-                               }
-                       }
-
-                       if (!bumppixels)
-                       {
-                               bumppixels = Mem_Alloc(loadmodel->mempool, basepixels_width * basepixels_height * 4);
-                               bumppixels_width = basepixels_width;
-                               bumppixels_height = basepixels_height;
-                               memcpy(bumppixels, basepixels, bumppixels_width * bumppixels_height * 4);
-                       }
-
-                       if (!nmappixels && bumppixels)
-                       {
-                               nmappixels = Mem_Alloc(loadmodel->mempool, bumppixels_width * bumppixels_height * 4);
-                               nmappixels_width = bumppixels_width;
-                               nmappixels_height = bumppixels_height;
-                               Image_HeightmapToNormalmap(bumppixels, nmappixels, nmappixels_width, nmappixels_height, false, 1);
-                       }
-               }
-
-               if (!detailtexture)
-                       detailtexture = detailtextures[i % NUM_DETAILTEXTURES];
-
-               if (basepixels)
-               {
-                       tx->texture = R_LoadTexture2D (loadmodel->texturepool, tx->name, basepixels_width, basepixels_height, basepixels, TEXTYPE_RGBA, TEXF_MIPMAP | TEXF_ALPHA | TEXF_PRECACHE, NULL);
-                       if (nmappixels)
-                               tx->nmaptexture = R_LoadTexture2D (loadmodel->texturepool, va("%s_nmap", tx->name), basepixels_width, basepixels_height, nmappixels, TEXTYPE_RGBA, TEXF_MIPMAP | TEXF_ALPHA | TEXF_PRECACHE, NULL);
-                       if (glosspixels)
-                               tx->glosstexture = R_LoadTexture2D (loadmodel->texturepool, va("%s_gloss", tx->name), glosspixels_width, glosspixels_height, glosspixels, TEXTYPE_RGBA, TEXF_MIPMAP | TEXF_ALPHA | TEXF_PRECACHE, NULL);
-                       if (glowpixels)
-                               tx->glowtexture = R_LoadTexture2D (loadmodel->texturepool, va("%s_glow", tx->name), glowpixels_width, glowpixels_height, glowpixels, TEXTYPE_RGBA, TEXF_MIPMAP | TEXF_ALPHA | TEXF_PRECACHE, NULL);
-                       if (maskpixels)
-                               tx->fogtexture = R_LoadTexture2D (loadmodel->texturepool, va("%s_mask", tx->name), maskpixels_width, maskpixels_height, maskpixels, TEXTYPE_RGBA, TEXF_MIPMAP | TEXF_ALPHA | TEXF_PRECACHE, NULL);
-                       tx->detailtexture = detailtexture;
-               }
-               else
+               if (tx->skin.base == NULL)
                {
                        // no texture found
                        tx->width = 16;
                        tx->height = 16;
-                       tx->texture = r_notexture;
-                       tx->nmaptexture = NULL;
-                       tx->glosstexture = NULL;
-                       tx->glowtexture = NULL;
-                       tx->fogtexture = NULL;
-                       tx->detailtexture = NULL;
-               }
-
-               if (basepixels)
-                       Mem_Free(basepixels);
-               if (bumppixels)
-                       Mem_Free(bumppixels);
-               if (nmappixels)
-                       Mem_Free(nmappixels);
-               if (glosspixels)
-                       Mem_Free(glosspixels);
-               if (glowpixels)
-                       Mem_Free(glowpixels);
-               if (maskpixels)
-                       Mem_Free(maskpixels);
+                       tx->skin.base = r_notexture;
+               }
 
                if (tx->name[0] == '*')
                {
@@ -507,7 +322,7 @@ static void Mod_LoadTextures (lump_t *l)
                else
                {
                        tx->flags |= SURF_LIGHTMAP;
-                       if (!tx->fogtexture)
+                       if (!tx->skin.fog)
                                tx->flags |= SURF_SHADOWCAST | SURF_SHADOWLIGHT;
                        tx->shader = &Cshader_wall_lightmap;
                }
index 7596a39..4dfa594 100644 (file)
@@ -106,18 +106,8 @@ typedef struct texture_s
        // type of rendering (SURFRENDER_ value)
        int rendertype;
 
-       // base texture without fullbrights, never NULL
-       rtexture_t *texture;
-       // fullbrights texture, NULL if no fullbrights used
-       rtexture_t *glowtexture;
-       // alpha texture (used for fogging), NULL if opaque
-       rtexture_t *fogtexture;
-       // detail texture (usually not used if transparent)
-       rtexture_t *detailtexture;
-       // normalmap for bumpmap shading
-       rtexture_t *nmaptexture;
-       // color filtering for glossy surfaces
-       rtexture_t *glosstexture;
+       // loaded the same as model skins
+       skinframe_t skin;
 
        // shader to use for this texture
        Cshader_t *shader;
index c269469..5bec6c2 100644 (file)
@@ -23,6 +23,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 // on the same machine.
 
 #include "quakedef.h"
+#include "image.h"
+#include "r_shadow.h"
 
 model_t *loadmodel;
 
@@ -30,8 +32,49 @@ model_t *loadmodel;
 #define        MAX_MOD_KNOWN   2048
 static model_t mod_known[MAX_MOD_KNOWN];
 
+rtexturepool_t *mod_shared_texturepool;
 rtexture_t *r_notexture;
-rtexturepool_t *r_notexturepool;
+rtexture_t *mod_shared_detailtextures[NUM_DETAILTEXTURES];
+
+void Mod_BuildDetailTextures (void)
+{
+       int i, x, y, light;
+       float vc[3], vx[3], vy[3], vn[3], lightdir[3];
+#define DETAILRESOLUTION 256
+       qbyte data[DETAILRESOLUTION][DETAILRESOLUTION][4], noise[DETAILRESOLUTION][DETAILRESOLUTION];
+       lightdir[0] = 0.5;
+       lightdir[1] = 1;
+       lightdir[2] = -0.25;
+       VectorNormalize(lightdir);
+       for (i = 0;i < NUM_DETAILTEXTURES;i++)
+       {
+               fractalnoise(&noise[0][0], DETAILRESOLUTION, DETAILRESOLUTION >> 4);
+               for (y = 0;y < DETAILRESOLUTION;y++)
+               {
+                       for (x = 0;x < DETAILRESOLUTION;x++)
+                       {
+                               vc[0] = x;
+                               vc[1] = y;
+                               vc[2] = noise[y][x] * (1.0f / 32.0f);
+                               vx[0] = x + 1;
+                               vx[1] = y;
+                               vx[2] = noise[y][(x + 1) % DETAILRESOLUTION] * (1.0f / 32.0f);
+                               vy[0] = x;
+                               vy[1] = y + 1;
+                               vy[2] = noise[(y + 1) % DETAILRESOLUTION][x] * (1.0f / 32.0f);
+                               VectorSubtract(vx, vc, vx);
+                               VectorSubtract(vy, vc, vy);
+                               CrossProduct(vx, vy, vn);
+                               VectorNormalize(vn);
+                               light = 128 - DotProduct(vn, lightdir) * 128;
+                               light = bound(0, light, 255);
+                               data[y][x][0] = data[y][x][1] = data[y][x][2] = light;
+                               data[y][x][3] = 255;
+                       }
+               }
+               mod_shared_detailtextures[i] = R_LoadTexture2D(mod_shared_texturepool, va("detailtexture%i", i), DETAILRESOLUTION, DETAILRESOLUTION, &data[0][0][0], TEXTYPE_RGBA, TEXF_MIPMAP | TEXF_PRECACHE, NULL);
+       }
+}
 
 texture_t r_surf_notexture;
 
@@ -62,13 +105,9 @@ void Mod_SetupNoTexture(void)
                }
        }
 
-       r_notexturepool = R_AllocTexturePool();
-       r_notexture = R_LoadTexture2D(r_notexturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_RGBA, TEXF_MIPMAP, NULL);
+       r_notexture = R_LoadTexture2D(mod_shared_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_RGBA, TEXF_MIPMAP, NULL);
 }
 
-extern void Mod_BrushStartup (void);
-extern void Mod_BrushShutdown (void);
-
 static void mod_start(void)
 {
        int i;
@@ -77,8 +116,9 @@ static void mod_start(void)
                        Mod_UnloadModel(&mod_known[i]);
        Mod_LoadModels();
 
+       mod_shared_texturepool = R_AllocTexturePool();
        Mod_SetupNoTexture();
-       Mod_BrushStartup();
+       Mod_BuildDetailTextures();
 }
 
 static void mod_shutdown(void)
@@ -88,8 +128,7 @@ static void mod_shutdown(void)
                if (mod_known[i].name[0])
                        Mod_UnloadModel(&mod_known[i]);
 
-       R_FreeTexturePool(&r_notexturepool);
-       Mod_BrushShutdown();
+       R_FreeTexturePool(&mod_shared_texturepool);
 }
 
 static void mod_newmap(void)
@@ -731,3 +770,84 @@ void Mod_ShadowMesh_Free(shadowmesh_t *mesh)
                Mem_Free(mesh);
        }
 }
+
+static rtexture_t *GL_TextureForSkinLayer(const qbyte *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)
+                       return R_LoadTexture2D (loadmodel->texturepool, name, width, height, in, TEXTYPE_PALETTE, textureflags, palette);
+       return NULL;
+}
+
+static int detailtexturecycle = 0;
+int Mod_LoadSkinFrame (skinframe_t *skinframe, char *basename, int textureflags, int loadpantsandshirt, int usedetailtexture, int loadglowtexture)
+{
+       imageskin_t s;
+       memset(skinframe, 0, sizeof(*skinframe));
+       if (!image_loadskin(&s, basename))
+               return false;
+       if (usedetailtexture)
+               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);
+       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)
+               skinframe->glow = R_LoadTexture2D (loadmodel->texturepool, va("%s_glow", basename), s.glowpixels_width, s.glowpixels_height, s.glowpixels, TEXTYPE_RGBA, textureflags, NULL);
+       if (s.maskpixels != NULL)
+               skinframe->fog = R_LoadTexture2D (loadmodel->texturepool, va("%s_mask", basename), s.maskpixels_width, s.maskpixels_height, s.maskpixels, TEXTYPE_RGBA, textureflags, NULL);
+       if (loadpantsandshirt)
+       {
+               if (s.pantspixels != NULL)
+                       skinframe->pants = R_LoadTexture2D (loadmodel->texturepool, va("%s_pants", basename), s.pantspixels_width, s.pantspixels_height, s.pantspixels, TEXTYPE_RGBA, textureflags, NULL);
+               if (s.shirtpixels != NULL)
+                       skinframe->shirt = R_LoadTexture2D (loadmodel->texturepool, va("%s_shirt", basename), s.shirtpixels_width, s.shirtpixels_height, s.shirtpixels, TEXTYPE_RGBA, textureflags, NULL);
+       }
+       image_freeskin(&s);
+       return true;
+}
+
+int Mod_LoadSkinFrame_Internal (skinframe_t *skinframe, char *basename, int textureflags, int loadpantsandshirt, int usedetailtexture, int loadglowtexture, qbyte *skindata, int width, int height)
+{
+       qbyte *temp1, *temp2;
+       memset(skinframe, 0, sizeof(*skinframe));
+       if (!skindata)
+               return false;
+       if (usedetailtexture)
+               skinframe->detail = mod_shared_detailtextures[(detailtexturecycle++) % NUM_DETAILTEXTURES];
+       if (r_shadow_bumpscale_basetexture.value > 0)
+       {
+               temp1 = 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)
+       {
+               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)
+               {
+                       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
+               }
+       }
+       else
+       {
+               skinframe->base = skinframe->merged = GL_TextureForSkinLayer(skindata, width, height, va("%s_merged", basename), palette_complete, textureflags); // all but fullbrights
+               if (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
+               }
+       }
+       return true;
+}
index 3740fc5..0c6578d 100644 (file)
@@ -47,14 +47,15 @@ animscene_t;
 
 typedef struct skinframe_s
 {
-       rtexture_t *base; // original texture minus pants/shirt/glow
+       rtexture_t *base; // original texture without pants/shirt/glow
        rtexture_t *pants; // pants only (in greyscale)
        rtexture_t *shirt; // shirt only (in greyscale)
-       rtexture_t *glow; // glow only
-       rtexture_t *merged; // original texture minus glow
-       rtexture_t *fog; // white texture with alpha of the base texture, NULL if not transparent
+       rtexture_t *glow; // glow only (fullbrights)
+       rtexture_t *merged; // original texture without glow
+       rtexture_t *fog; // alpha of the base texture (if not opaque)
        rtexture_t *nmap; // normalmap (bumpmap for dot3)
        rtexture_t *gloss; // glossmap (for dot3)
+       rtexture_t *detail; // detail texture (silly bumps for non-dot3)
 }
 skinframe_t;
 
@@ -274,8 +275,10 @@ model_t;
 
 // this can be used for anything without a valid texture
 extern rtexture_t *r_notexture;
+#define NUM_DETAILTEXTURES 1
+extern rtexture_t *mod_shared_detailtextures[NUM_DETAILTEXTURES];
 // every texture must be in a pool...
-extern rtexturepool_t *r_notexturepool;
+extern rtexturepool_t *mod_shared_texturepool;
 
 // model loading
 extern model_t *loadmodel;
@@ -317,5 +320,8 @@ shadowmesh_t *Mod_ShadowMesh_Finish(mempool_t *mempool, shadowmesh_t *firstmesh)
 void Mod_ShadowMesh_CalcBBox(shadowmesh_t *firstmesh, vec3_t mins, vec3_t maxs, vec3_t center, float *radius);
 void Mod_ShadowMesh_Free(shadowmesh_t *mesh);
 
+int Mod_LoadSkinFrame (skinframe_t *skinframe, char *basename, int textureflags, int loadpantsandshirt, int usedetailtexture, int loadglowtexture);
+int Mod_LoadSkinFrame_Internal (skinframe_t *skinframe, char *basename, int textureflags, int loadpantsandshirt, int usedetailtexture, int loadglowtexture, qbyte *skindata, int width, int height);
+
 #endif // __MODEL__
 
index 1978eef..e6bf563 100644 (file)
--- a/palette.c
+++ b/palette.c
@@ -5,6 +5,7 @@ unsigned int palette_complete[256];
 unsigned int palette_nofullbrights[256];
 unsigned int palette_onlyfullbrights[256];
 unsigned int palette_nocolormapnofullbrights[256];
+unsigned int palette_nocolormap[256];
 unsigned int palette_pantsaswhite[256];
 unsigned int palette_shirtaswhite[256];
 unsigned int palette_alpha[256];
@@ -77,6 +78,14 @@ void Palette_Setup8to24(void)
                palette_nocolormapnofullbrights[i] = palette_complete[0];
        palette_nocolormapnofullbrights[255] = 0;
 
+       for (i = 0;i < 256;i++)
+               palette_nocolormap[i] = palette_complete[i];
+       for (i = pants_start;i < pants_end;i++)
+               palette_nocolormap[i] = palette_complete[0];
+       for (i = shirt_start;i < shirt_end;i++)
+               palette_nocolormap[i] = palette_complete[0];
+       palette_nocolormap[255] = 0;
+
        for (i = 0;i < 256;i++)
                palette_pantsaswhite[i] = palette_complete[0];
        for (i = pants_start;i < pants_end;i++)
index e1dcfda..a0e97a9 100644 (file)
--- a/palette.h
+++ b/palette.h
@@ -12,6 +12,7 @@ extern unsigned int palette_complete[256];
 extern unsigned int palette_nofullbrights[256];
 extern unsigned int palette_onlyfullbrights[256];
 extern unsigned int palette_nocolormapnofullbrights[256];
+extern unsigned int palette_nocolormap[256];
 extern unsigned int palette_pantsaswhite[256];
 extern unsigned int palette_shirtaswhite[256];
 extern unsigned int palette_alpha[256];
index fdbfc47..f8a0e3d 100644 (file)
@@ -29,13 +29,15 @@ rtexture_t *r_shadow_blankbumptexture;
 rtexture_t *r_shadow_blankglosstexture;
 rtexture_t *r_shadow_blankwhitetexture;
 
+cvar_t r_shadow_lightattenuationpower = {0, "r_shadow_lightattenuationpower", "2"};
 cvar_t r_shadow_lightattenuationscale = {0, "r_shadow_lightattenuationscale", "2"};
 cvar_t r_shadow_lightintensityscale = {0, "r_shadow_lightintensityscale", "1"};
 cvar_t r_shadow_realtime = {0, "r_shadow_realtime", "0"};
 cvar_t r_shadow_gloss = {0, "r_shadow_gloss", "1"};
 cvar_t r_shadow_debuglight = {0, "r_shadow_debuglight", "-1"};
 cvar_t r_shadow_scissor = {0, "r_shadow_scissor", "1"};
-cvar_t r_shadow_bumpscale = {0, "r_shadow_bumpscale", "4"};
+cvar_t r_shadow_bumpscale_bumpmap = {0, "r_shadow_bumpscale_bumpmap", "4"};
+cvar_t r_shadow_bumpscale_basetexture = {0, "r_shadow_bumpscale_basetexture", "4"};
 cvar_t r_shadow_shadownudge = {0, "r_shadow_shadownudge", "1"};
 
 void R_Shadow_ClearWorldLights(void);
@@ -87,13 +89,15 @@ void r_shadow_newmap(void)
 
 void R_Shadow_Init(void)
 {
+       Cvar_RegisterVariable(&r_shadow_lightattenuationpower);
        Cvar_RegisterVariable(&r_shadow_lightattenuationscale);
        Cvar_RegisterVariable(&r_shadow_lightintensityscale);
        Cvar_RegisterVariable(&r_shadow_realtime);
        Cvar_RegisterVariable(&r_shadow_gloss);
        Cvar_RegisterVariable(&r_shadow_debuglight);
        Cvar_RegisterVariable(&r_shadow_scissor);
-       Cvar_RegisterVariable(&r_shadow_bumpscale);
+       Cvar_RegisterVariable(&r_shadow_bumpscale_bumpmap);
+       Cvar_RegisterVariable(&r_shadow_bumpscale_basetexture);
        Cvar_RegisterVariable(&r_shadow_shadownudge);
        R_Shadow_EditLights_Init();
        R_RegisterModule("R_Shadow", r_shadow_start, r_shadow_shutdown, r_shadow_newmap);
@@ -345,7 +349,7 @@ void R_Shadow_RenderShadowMeshVolume(shadowmesh_t *firstmesh)
        }
 }
 
-float r_shadow_atten1;
+float r_shadow_attenpower, r_shadow_attenscale;
 static void R_Shadow_MakeTextures(void)
 {
        int x, y, d, side;
@@ -353,7 +357,8 @@ static void R_Shadow_MakeTextures(void)
        qbyte *data;
        R_FreeTexturePool(&r_shadow_texturepool);
        r_shadow_texturepool = R_AllocTexturePool();
-       r_shadow_atten1 = r_shadow_lightattenuationscale.value;
+       r_shadow_attenpower = r_shadow_lightattenuationpower.value;
+       r_shadow_attenscale = r_shadow_lightattenuationscale.value;
        data = Mem_Alloc(tempmempool, 6*128*128*4);
        data[0] = 128;
        data[1] = 128;
@@ -429,8 +434,8 @@ static void R_Shadow_MakeTextures(void)
                        v[2] = 0;
                        intensity = 1.0f - sqrt(DotProduct(v, v));
                        if (intensity > 0)
-                               intensity *= intensity;
-                       intensity = bound(0, intensity * r_shadow_atten1 * 256.0f, 255.0f);
+                               intensity = pow(intensity, r_shadow_attenpower);
+                       intensity = bound(0, intensity * r_shadow_attenscale * 256.0f, 255.0f);
                        d = bound(0, intensity, 255);
                        data[((0*128+y)*128+x)*4+0] = d;
                        data[((0*128+y)*128+x)*4+1] = d;
@@ -448,7 +453,8 @@ void R_Shadow_Stage_Begin(void)
 
        //cl.worldmodel->numlights = min(cl.worldmodel->numlights, 1);
        if (!r_shadow_attenuation2dtexture
-        || r_shadow_lightattenuationscale.value != r_shadow_atten1)
+        || r_shadow_lightattenuationpower.value != r_shadow_attenpower
+        || r_shadow_lightattenuationscale.value != r_shadow_attenscale)
                R_Shadow_MakeTextures();
        if (r_shadow_reloadlights && cl.worldmodel)
        {
index 8b97e42..96480aa 100644 (file)
@@ -7,6 +7,8 @@ extern cvar_t r_shadow_lightintensityscale;
 extern cvar_t r_shadow_realtime;
 extern cvar_t r_shadow_gloss;
 extern cvar_t r_shadow_debuglight;
+extern cvar_t r_shadow_bumpscale_bumpmap;
+extern cvar_t r_shadow_bumpscale_basetexture;
 
 void R_Shadow_Init(void);
 void R_Shadow_Volume(int numverts, int numtris, int *elements, int *neighbors, vec3_t relativelightorigin, float lightradius, float projectdistance);