now parses more of q3 shaders to guess at proper rendering settings for surfaces...
authorhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Sat, 16 Oct 2004 11:29:13 +0000 (11:29 +0000)
committerhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Sat, 16 Oct 2004 11:29:13 +0000 (11:29 +0000)
now assumes that a q3 texture is not transparent unless it has a shader saying it is (yes shaders are now required to enable transparency in q3bsp)
now loads the texture used in the first pass of the shader if there is no texture of the same name as the shader itself
what this all means: quake3 maps look 99% correct (other than lack of animation and various shader effects)

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

gl_rsurf.c
model_brush.c
model_shared.h

index 9e53d69..7db260b 100644 (file)
@@ -1931,7 +1931,7 @@ void R_Q3BSP_DrawFace_TransparentCallback(const void *voident, int facenumber)
        rmeshstate_t m;
        R_Mesh_Matrix(&ent->matrix);
        memset(&m, 0, sizeof(m));
-       if (ent->effects & EF_ADDITIVE)
+       if ((ent->effects & EF_ADDITIVE) || (face->texture->textureflags & Q3TEXTUREFLAG_ADDITIVE))
                GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
        else
                GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
@@ -1979,13 +1979,60 @@ void R_Q3BSP_DrawFace_TransparentCallback(const void *voident, int facenumber)
                }
                m.pointer_color = varray_color4f;
        }
-       m.pointer_vertex = face->data_vertex3f;
+       if (face->texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
+       {
+               int i, j;
+               float f, center[3], center2[3], forward[3], right[3], up[3], v[4][3];
+               matrix4x4_t matrix1, imatrix1;
+               R_Mesh_Matrix(&r_identitymatrix);
+               // a single autosprite surface can contain multiple sprites...
+               for (j = 0;j < face->num_vertices - 3;j += 4)
+               {
+                       VectorClear(center);
+                       for (i = 0;i < 4;i++)
+                               VectorAdd(center, face->data_vertex3f + (j+i) * 3, center);
+                       VectorScale(center, 0.25f, center);
+                       Matrix4x4_Transform(&ent->matrix, center, center2);
+                       // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
+                       Matrix4x4_FromVectors(&matrix1, face->data_normal3f + j*3, face->data_svector3f + j*3, face->data_tvector3f + j*3, center);
+                       Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
+                       for (i = 0;i < 4;i++)
+                               Matrix4x4_Transform(&imatrix1, face->data_vertex3f + (j+i)*3, v[i]);
+                       if (face->texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE2)
+                       {
+                               CL_SparkShower (center, vec3_origin, 1);
+                               forward[0] = r_vieworigin[0] - center2[0];
+                               forward[1] = r_vieworigin[1] - center2[1];
+                               forward[2] = 0;
+                               VectorNormalize(forward);
+                               right[0] = forward[1];
+                               right[1] = -forward[0];
+                               right[2] = 0;
+                               up[0] = 0;
+                               up[1] = 0;
+                               up[2] = 1;
+                       }
+                       else
+                       {
+                               VectorCopy(r_viewforward, forward);
+                               VectorCopy(r_viewright, right);
+                               VectorCopy(r_viewup, up);
+                       }
+                       for (i = 0;i < 4;i++)
+                               VectorMAMAMAM(1, center2, v[i][0], forward, v[i][1], right, v[i][2], up, varray_vertex3f + (i+j) * 3);
+               }
+               m.pointer_vertex = varray_vertex3f;
+       }
+       else
+               m.pointer_vertex = face->data_vertex3f;
        R_Mesh_State(&m);
-       qglDisable(GL_CULL_FACE);
+       if (face->texture->textureflags & Q3TEXTUREFLAG_TWOSIDED)
+               qglDisable(GL_CULL_FACE);
        GL_LockArrays(0, face->num_vertices);
        R_Mesh_Draw(face->num_vertices, face->num_triangles, face->data_element3i);
        GL_LockArrays(0, 0);
-       qglEnable(GL_CULL_FACE);
+       if (face->texture->textureflags & Q3TEXTUREFLAG_TWOSIDED)
+               qglEnable(GL_CULL_FACE);
 }
 
 void R_Q3BSP_DrawFaceList(entity_render_t *ent, q3mtexture_t *t, int texturenumfaces, q3msurface_t **texturefacelist)
@@ -2063,6 +2110,7 @@ void R_Q3BSP_DrawFaceList(entity_render_t *ent, q3mtexture_t *t, int texturenumf
                GL_DepthMask(true);
                GL_DepthTest(true);
                GL_BlendFunc(GL_ONE, GL_ZERO);
+               qglDisable(GL_CULL_FACE);
                memset(&m, 0, sizeof(m));
                for (texturefaceindex = 0;texturefaceindex < texturenumfaces;texturefaceindex++)
                {
@@ -2082,6 +2130,7 @@ void R_Q3BSP_DrawFaceList(entity_render_t *ent, q3mtexture_t *t, int texturenumf
                        R_Mesh_Draw(face->num_vertices, face->num_triangles, face->data_element3i);
                        GL_LockArrays(0, 0);
                }
+               qglEnable(GL_CULL_FACE);
                return;
        }
        // anything else is a typical wall, lightmap * texture + glow
@@ -2091,6 +2140,8 @@ void R_Q3BSP_DrawFaceList(entity_render_t *ent, q3mtexture_t *t, int texturenumf
                GL_DepthTest(true);
                GL_BlendFunc(GL_ONE, GL_ZERO);
                GL_Color(1, 1, 1, 1);
+               if (t->textureflags & Q3TEXTUREFLAG_TWOSIDED)
+                       qglDisable(GL_CULL_FACE);
                memset(&m, 0, sizeof(m));
                m.tex[0] = R_GetTexture(t->skin.base);
                for (texturefaceindex = 0;texturefaceindex < texturenumfaces;texturefaceindex++)
@@ -2119,8 +2170,12 @@ void R_Q3BSP_DrawFaceList(entity_render_t *ent, q3mtexture_t *t, int texturenumf
                                GL_LockArrays(0, 0);
                        }
                }
+               if (t->textureflags & Q3TEXTUREFLAG_TWOSIDED)
+                       qglEnable(GL_CULL_FACE);
                return;
        }
+       if (t->textureflags & Q3TEXTUREFLAG_TWOSIDED)
+               qglDisable(GL_CULL_FACE);
        if (r_lightmapintensity <= 0)
        {
                GL_DepthMask(true);
@@ -2252,6 +2307,8 @@ void R_Q3BSP_DrawFaceList(entity_render_t *ent, q3mtexture_t *t, int texturenumf
                        GL_LockArrays(0, 0);
                }
        }
+       if (t->textureflags & Q3TEXTUREFLAG_TWOSIDED)
+               qglEnable(GL_CULL_FACE);
 }
 
 void R_Q3BSP_DrawFaces(entity_render_t *ent, int skyfaces)
@@ -2424,16 +2481,34 @@ void R_Q3BSP_GetLightInfo(entity_render_t *ent, vec3_t relativelightorigin, floa
                                        {
                                                if (BoxesOverlap(lightmins, lightmaxs, surface->mins, surface->maxs) && !(surface->texture->surfaceparms & Q3SURFACEPARM_TRANS) && !(surface->texture->surfaceflags & (Q3SURFACEFLAG_SKY | Q3SURFACEFLAG_NODRAW)) && surface->num_triangles)
                                                {
-                                                       for (triangleindex = 0, t = surface->num_firstshadowmeshtriangle, e = model->brush.shadowmesh->element3i + t * 3;triangleindex < surface->num_triangles;triangleindex++, t++, e += 3)
+                                                       if (surface->texture->textureflags & Q3TEXTUREFLAG_TWOSIDED)
                                                        {
-                                                               v[0] = model->brush.shadowmesh->vertex3f + e[0] * 3;
-                                                               v[1] = model->brush.shadowmesh->vertex3f + e[1] * 3;
-                                                               v[2] = model->brush.shadowmesh->vertex3f + e[2] * 3;
-                                                               if (PointInfrontOfTriangle(relativelightorigin, v[0], v[1], v[2]) && lightmaxs[0] > min(v[0][0], min(v[1][0], v[2][0])) && lightmins[0] < max(v[0][0], max(v[1][0], v[2][0])) && lightmaxs[1] > min(v[0][1], min(v[1][1], v[2][1])) && lightmins[1] < max(v[0][1], max(v[1][1], v[2][1])) && lightmaxs[2] > min(v[0][2], min(v[1][2], v[2][2])) && lightmins[2] < max(v[0][2], max(v[1][2], v[2][2])))
+                                                               for (triangleindex = 0, t = surface->num_firstshadowmeshtriangle, e = model->brush.shadowmesh->element3i + t * 3;triangleindex < surface->num_triangles;triangleindex++, t++, e += 3)
                                                                {
-                                                                       SETPVSBIT(outsurfacepvs, surfaceindex);
-                                                                       outsurfacelist[outnumsurfaces++] = surfaceindex;
-                                                                       break;
+                                                                       v[0] = model->brush.shadowmesh->vertex3f + e[0] * 3;
+                                                                       v[1] = model->brush.shadowmesh->vertex3f + e[1] * 3;
+                                                                       v[2] = model->brush.shadowmesh->vertex3f + e[2] * 3;
+                                                                       if (lightmaxs[0] > min(v[0][0], min(v[1][0], v[2][0])) && lightmins[0] < max(v[0][0], max(v[1][0], v[2][0])) && lightmaxs[1] > min(v[0][1], min(v[1][1], v[2][1])) && lightmins[1] < max(v[0][1], max(v[1][1], v[2][1])) && lightmaxs[2] > min(v[0][2], min(v[1][2], v[2][2])) && lightmins[2] < max(v[0][2], max(v[1][2], v[2][2])))
+                                                                       {
+                                                                               SETPVSBIT(outsurfacepvs, surfaceindex);
+                                                                               outsurfacelist[outnumsurfaces++] = surfaceindex;
+                                                                               break;
+                                                                       }
+                                                               }
+                                                       }
+                                                       else
+                                                       {
+                                                               for (triangleindex = 0, t = surface->num_firstshadowmeshtriangle, e = model->brush.shadowmesh->element3i + t * 3;triangleindex < surface->num_triangles;triangleindex++, t++, e += 3)
+                                                               {
+                                                                       v[0] = model->brush.shadowmesh->vertex3f + e[0] * 3;
+                                                                       v[1] = model->brush.shadowmesh->vertex3f + e[1] * 3;
+                                                                       v[2] = model->brush.shadowmesh->vertex3f + e[2] * 3;
+                                                                       if (PointInfrontOfTriangle(relativelightorigin, v[0], v[1], v[2]) && lightmaxs[0] > min(v[0][0], min(v[1][0], v[2][0])) && lightmins[0] < max(v[0][0], max(v[1][0], v[2][0])) && lightmaxs[1] > min(v[0][1], min(v[1][1], v[2][1])) && lightmins[1] < max(v[0][1], max(v[1][1], v[2][1])) && lightmaxs[2] > min(v[0][2], min(v[1][2], v[2][2])) && lightmins[2] < max(v[0][2], max(v[1][2], v[2][2])))
+                                                                       {
+                                                                               SETPVSBIT(outsurfacepvs, surfaceindex);
+                                                                               outsurfacelist[outnumsurfaces++] = surfaceindex;
+                                                                               break;
+                                                                       }
                                                                }
                                                        }
                                                }
@@ -2475,7 +2550,7 @@ void R_Q3BSP_DrawShadowVolume(entity_render_t *ent, vec3_t relativelightorigin,
                {
                        surface = model->brushq3.data_faces + surfacelist[surfacelistindex];
                        // FIXME: check some manner of face->rendermode here?
-                       if (!(surface->texture->surfaceflags & Q3SURFACEFLAG_NODRAW) && !(surface->texture->surfaceparms & Q3SURFACEPARM_TRANS))
+                       if (!(surface->texture->surfaceflags & Q3SURFACEFLAG_NODRAW) && !(surface->texture->surfaceparms & (Q3SURFACEPARM_SKY | Q3SURFACEPARM_TRANS)) && !(surface->texture->textureflags & Q3TEXTUREFLAG_TWOSIDED))
                                R_Shadow_MarkVolumeFromBox(surface->num_firstshadowmeshtriangle, surface->num_triangles, model->brush.shadowmesh->vertex3f, model->brush.shadowmesh->element3i, relativelightorigin, lightmins, lightmaxs, surface->mins, surface->maxs);
                }
                R_Shadow_VolumeFromList(model->brush.shadowmesh->numverts, model->brush.shadowmesh->numtriangles, model->brush.shadowmesh->vertex3f, model->brush.shadowmesh->element3i, model->brush.shadowmesh->neighbor3i, relativelightorigin, lightradius + model->radius + r_shadow_projectdistance.value, numshadowmark, shadowmarklist);
@@ -2507,7 +2582,13 @@ void R_Q3BSP_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, vec3_t
                                Mod_ShadowMesh_AddMesh(r_shadow_mempool, r_shadow_compilingrtlight->static_meshchain_light, surface->texture->skin.base, surface->texture->skin.gloss, surface->texture->skin.nmap, surface->data_vertex3f, surface->data_svector3f, surface->data_tvector3f, surface->data_normal3f, surface->data_texcoordtexture2f, surface->num_triangles, surface->data_element3i);
                        }
                        else if (!(surface->texture->surfaceflags & Q3SURFACEFLAG_NODRAW) && surface->num_triangles)
+                       {
+                               if (surface->texture->textureflags & Q3TEXTUREFLAG_TWOSIDED)
+                                       qglDisable(GL_CULL_FACE);
                                R_Shadow_RenderLighting(surface->num_vertices, surface->num_triangles, surface->data_element3i, surface->data_vertex3f, surface->data_svector3f, surface->data_tvector3f, surface->data_normal3f, surface->data_texcoordtexture2f, relativelightorigin, relativeeyeorigin, lightcolor, matrix_modeltolight, matrix_modeltoattenuationxyz, matrix_modeltoattenuationz, surface->texture->skin.base, surface->texture->skin.nmap, surface->texture->skin.gloss, lightcubemap, LIGHTING_DIFFUSE | LIGHTING_SPECULAR);
+                               if (surface->texture->textureflags & Q3TEXTUREFLAG_TWOSIDED)
+                                       qglEnable(GL_CULL_FACE);
+                       }
                }
        }
 }
index 2cb005c..5f43235 100644 (file)
@@ -3597,9 +3597,11 @@ static void Mod_Q3BSP_LoadTextures(lump_t *l)
        fssearch_t *search;
        char *f;
        const char *text;
-       int flags;
+       int flags, flags2, numparameters, passnumber;
        char shadername[Q3PATHLENGTH];
        char sky[Q3PATHLENGTH];
+       char firstpasstexturename[Q3PATHLENGTH];
+       char parameter[4][Q3PATHLENGTH];
 
        in = (void *)(mod_base + l->fileofs);
        if (l->filelen % sizeof(*in))
@@ -3617,7 +3619,6 @@ static void Mod_Q3BSP_LoadTextures(lump_t *l)
                out->surfaceflags = LittleLong(in->surfaceflags);
                out->nativecontents = LittleLong(in->contents);
                out->supercontents = Mod_Q3BSP_SuperContentsFromNativeContents(loadmodel, out->nativecontents);
-               Mod_LoadSkinFrame(&out->skin, out->name, TEXF_MIPMAP | TEXF_ALPHA | TEXF_PRECACHE | TEXF_PICMIP, false, true, true);
                out->surfaceparms = -1;
        }
 
@@ -3633,7 +3634,10 @@ static void Mod_Q3BSP_LoadTextures(lump_t *l)
                                {
                                        strlcpy (shadername, com_token, sizeof (shadername));
                                        flags = 0;
+                                       flags2 = 0;
                                        sky[0] = 0;
+                                       passnumber = 0;
+                                       firstpasstexturename[0] = 0;
                                        if (COM_ParseToken(&text, false) && !strcasecmp(com_token, "{"))
                                        {
                                                while (COM_ParseToken(&text, false))
@@ -3646,103 +3650,152 @@ static void Mod_Q3BSP_LoadTextures(lump_t *l)
                                                                {
                                                                        if (!strcasecmp(com_token, "}"))
                                                                                break;
+                                                                       if (!strcasecmp(com_token, "\n"))
+                                                                               continue;
+                                                                       numparameters = 0;
+                                                                       for (j = 0;strcasecmp(com_token, "\n") && strcasecmp(com_token, "}");j++)
+                                                                       {
+                                                                               if (j < 4)
+                                                                               {
+                                                                                       strlcpy(parameter[j], com_token, sizeof(parameter[j]));
+                                                                                       numparameters = j + 1;
+                                                                               }
+                                                                               if (!COM_ParseToken(&text, true))
+                                                                                       break;
+                                                                       }
+                                                                       Con_Printf("%s %i: ", shadername, passnumber);
+                                                                       for (j = 0;j < numparameters;j++)
+                                                                               Con_Printf(" %s", parameter[j]);
+                                                                       Con_Print("\n");
+                                                                       if (passnumber == 0 && numparameters >= 1)
+                                                                       {
+                                                                               if (!strcasecmp(parameter[0], "blendfunc"))
+                                                                               {
+                                                                                       Con_Printf("!\n");
+                                                                                       if (numparameters == 2 && !strcasecmp(parameter[1], "add"))
+                                                                                               flags2 |= Q3TEXTUREFLAG_ADDITIVE;
+                                                                                       else if (numparameters == 3 && !strcasecmp(parameter[1], "gl_one") && !strcasecmp(parameter[2], "gl_one"))
+                                                                                               flags2 |= Q3TEXTUREFLAG_ADDITIVE;
+                                                                                       else if (numparameters == 3 && !strcasecmp(parameter[1], "gl_src_alpha") && !strcasecmp(parameter[2], "gl_one"))
+                                                                                               flags2 |= Q3TEXTUREFLAG_ADDITIVE;
+                                                                               }
+                                                                               else if (numparameters >= 2 && (!strcasecmp(parameter[0], "map") || !strcasecmp(parameter[0], "clampmap")))
+                                                                                       strlcpy(firstpasstexturename, parameter[1], sizeof(firstpasstexturename));
+                                                                               else if (numparameters >= 3 && !strcasecmp(parameter[0], "animmap"))
+                                                                                       strlcpy(firstpasstexturename, parameter[2], sizeof(firstpasstexturename));
+                                                                       }
+                                                                       // break out a level if it was }
+                                                                       if (!strcasecmp(com_token, "}"))
+                                                                               break;
                                                                }
+                                                               passnumber++;
+                                                               continue;
                                                        }
-                                                       else if (!strcasecmp(com_token, "surfaceparm"))
+                                                       numparameters = 0;
+                                                       for (j = 0;strcasecmp(com_token, "\n") && strcasecmp(com_token, "}");j++)
                                                        {
-                                                               if (COM_ParseToken(&text, true) && strcasecmp(com_token, "\n"))
+                                                               if (j < 4)
                                                                {
-                                                                       if (!strcasecmp(com_token, "alphashadow"))
-                                                                               flags |= Q3SURFACEPARM_ALPHASHADOW;
-                                                                       else if (!strcasecmp(com_token, "areaportal"))
-                                                                               flags |= Q3SURFACEPARM_AREAPORTAL;
-                                                                       else if (!strcasecmp(com_token, "clusterportal"))
-                                                                               flags |= Q3SURFACEPARM_CLUSTERPORTAL;
-                                                                       else if (!strcasecmp(com_token, "detail"))
-                                                                               flags |= Q3SURFACEPARM_DETAIL;
-                                                                       else if (!strcasecmp(com_token, "donotenter"))
-                                                                               flags |= Q3SURFACEPARM_DONOTENTER;
-                                                                       else if (!strcasecmp(com_token, "fog"))
-                                                                               flags |= Q3SURFACEPARM_FOG;
-                                                                       else if (!strcasecmp(com_token, "lava"))
-                                                                               flags |= Q3SURFACEPARM_LAVA;
-                                                                       else if (!strcasecmp(com_token, "lightfilter"))
-                                                                               flags |= Q3SURFACEPARM_LIGHTFILTER;
-                                                                       else if (!strcasecmp(com_token, "metalsteps"))
-                                                                               flags |= Q3SURFACEPARM_METALSTEPS;
-                                                                       else if (!strcasecmp(com_token, "nodamage"))
-                                                                               flags |= Q3SURFACEPARM_NODAMAGE;
-                                                                       else if (!strcasecmp(com_token, "nodlight"))
-                                                                               flags |= Q3SURFACEPARM_NODLIGHT;
-                                                                       else if (!strcasecmp(com_token, "nodraw"))
-                                                                               flags |= Q3SURFACEPARM_NODRAW;
-                                                                       else if (!strcasecmp(com_token, "nodrop"))
-                                                                               flags |= Q3SURFACEPARM_NODROP;
-                                                                       else if (!strcasecmp(com_token, "noimpact"))
-                                                                               flags |= Q3SURFACEPARM_NOIMPACT;
-                                                                       else if (!strcasecmp(com_token, "nolightmap"))
-                                                                               flags |= Q3SURFACEPARM_NOLIGHTMAP;
-                                                                       else if (!strcasecmp(com_token, "nomarks"))
-                                                                               flags |= Q3SURFACEPARM_NOMARKS;
-                                                                       else if (!strcasecmp(com_token, "nomipmaps"))
-                                                                               flags |= Q3SURFACEPARM_NOMIPMAPS;
-                                                                       else if (!strcasecmp(com_token, "nonsolid"))
-                                                                               flags |= Q3SURFACEPARM_NONSOLID;
-                                                                       else if (!strcasecmp(com_token, "origin"))
-                                                                               flags |= Q3SURFACEPARM_ORIGIN;
-                                                                       else if (!strcasecmp(com_token, "playerclip"))
-                                                                               flags |= Q3SURFACEPARM_PLAYERCLIP;
-                                                                       else if (!strcasecmp(com_token, "sky"))
-                                                                               flags |= Q3SURFACEPARM_SKY;
-                                                                       else if (!strcasecmp(com_token, "slick"))
-                                                                               flags |= Q3SURFACEPARM_SLICK;
-                                                                       else if (!strcasecmp(com_token, "slime"))
-                                                                               flags |= Q3SURFACEPARM_SLIME;
-                                                                       else if (!strcasecmp(com_token, "structural"))
-                                                                               flags |= Q3SURFACEPARM_STRUCTURAL;
-                                                                       else if (!strcasecmp(com_token, "trans"))
-                                                                               flags |= Q3SURFACEPARM_TRANS;
-                                                                       else if (!strcasecmp(com_token, "water"))
-                                                                               flags |= Q3SURFACEPARM_WATER;
-                                                                       else
-                                                                               Con_Printf("%s parsing warning: unknown surfaceparm \"%s\"\n", search->filenames[i], com_token);
-                                                                       if (!COM_ParseToken(&text, true) || strcasecmp(com_token, "\n"))
-                                                                       {
-                                                                               Con_Printf("%s parsing error: surfaceparm only takes one parameter.\n", search->filenames[i]);
-                                                                               goto parseerror;
-                                                                       }
+                                                                       strlcpy(parameter[j], com_token, sizeof(parameter[j]));
+                                                                       numparameters = j + 1;
                                                                }
+                                                               if (!COM_ParseToken(&text, true))
+                                                                       break;
+                                                       }
+                                                       if (i == 0 && !strcasecmp(com_token, "}"))
+                                                               break;
+                                                       Con_Printf("%s: ", shadername);
+                                                       for (j = 0;j < numparameters;j++)
+                                                               Con_Printf(" %s", parameter[j]);
+                                                       Con_Print("\n");
+                                                       if (numparameters < 1)
+                                                               continue;
+                                                       if (!strcasecmp(parameter[0], "surfaceparm") && numparameters >= 2)
+                                                       {
+                                                               if (!strcasecmp(parameter[1], "alphashadow"))
+                                                                       flags |= Q3SURFACEPARM_ALPHASHADOW;
+                                                               else if (!strcasecmp(parameter[1], "areaportal"))
+                                                                       flags |= Q3SURFACEPARM_AREAPORTAL;
+                                                               else if (!strcasecmp(parameter[1], "clusterportal"))
+                                                                       flags |= Q3SURFACEPARM_CLUSTERPORTAL;
+                                                               else if (!strcasecmp(parameter[1], "detail"))
+                                                                       flags |= Q3SURFACEPARM_DETAIL;
+                                                               else if (!strcasecmp(parameter[1], "donotenter"))
+                                                                       flags |= Q3SURFACEPARM_DONOTENTER;
+                                                               else if (!strcasecmp(parameter[1], "fog"))
+                                                                       flags |= Q3SURFACEPARM_FOG;
+                                                               else if (!strcasecmp(parameter[1], "lava"))
+                                                                       flags |= Q3SURFACEPARM_LAVA;
+                                                               else if (!strcasecmp(parameter[1], "lightfilter"))
+                                                                       flags |= Q3SURFACEPARM_LIGHTFILTER;
+                                                               else if (!strcasecmp(parameter[1], "metalsteps"))
+                                                                       flags |= Q3SURFACEPARM_METALSTEPS;
+                                                               else if (!strcasecmp(parameter[1], "nodamage"))
+                                                                       flags |= Q3SURFACEPARM_NODAMAGE;
+                                                               else if (!strcasecmp(parameter[1], "nodlight"))
+                                                                       flags |= Q3SURFACEPARM_NODLIGHT;
+                                                               else if (!strcasecmp(parameter[1], "nodraw"))
+                                                                       flags |= Q3SURFACEPARM_NODRAW;
+                                                               else if (!strcasecmp(parameter[1], "nodrop"))
+                                                                       flags |= Q3SURFACEPARM_NODROP;
+                                                               else if (!strcasecmp(parameter[1], "noimpact"))
+                                                                       flags |= Q3SURFACEPARM_NOIMPACT;
+                                                               else if (!strcasecmp(parameter[1], "nolightmap"))
+                                                                       flags |= Q3SURFACEPARM_NOLIGHTMAP;
+                                                               else if (!strcasecmp(parameter[1], "nomarks"))
+                                                                       flags |= Q3SURFACEPARM_NOMARKS;
+                                                               else if (!strcasecmp(parameter[1], "nomipmaps"))
+                                                                       flags |= Q3SURFACEPARM_NOMIPMAPS;
+                                                               else if (!strcasecmp(parameter[1], "nonsolid"))
+                                                                       flags |= Q3SURFACEPARM_NONSOLID;
+                                                               else if (!strcasecmp(parameter[1], "origin"))
+                                                                       flags |= Q3SURFACEPARM_ORIGIN;
+                                                               else if (!strcasecmp(parameter[1], "playerclip"))
+                                                                       flags |= Q3SURFACEPARM_PLAYERCLIP;
+                                                               else if (!strcasecmp(parameter[1], "sky"))
+                                                                       flags |= Q3SURFACEPARM_SKY;
+                                                               else if (!strcasecmp(parameter[1], "slick"))
+                                                                       flags |= Q3SURFACEPARM_SLICK;
+                                                               else if (!strcasecmp(parameter[1], "slime"))
+                                                                       flags |= Q3SURFACEPARM_SLIME;
+                                                               else if (!strcasecmp(parameter[1], "structural"))
+                                                                       flags |= Q3SURFACEPARM_STRUCTURAL;
+                                                               else if (!strcasecmp(parameter[1], "trans"))
+                                                                       flags |= Q3SURFACEPARM_TRANS;
+                                                               else if (!strcasecmp(parameter[1], "water"))
+                                                                       flags |= Q3SURFACEPARM_WATER;
                                                                else
-                                                               {
-                                                                       Con_Printf("%s parsing error: surfaceparm expects a parameter.\n", search->filenames[i]);
-                                                                       goto parseerror;
-                                                               }
+                                                                       Con_Printf("%s parsing warning: unknown surfaceparm \"%s\"\n", search->filenames[i], parameter[1]);
                                                        }
-                                                       else if (!strcasecmp(com_token, "sky"))
+                                                       else if (!strcasecmp(parameter[0], "sky") && numparameters >= 2)
+                                                               strlcpy(sky, parameter[1], sizeof(sky));
+                                                       else if (!strcasecmp(parameter[0], "skyparms") && numparameters >= 2)
                                                        {
-                                                               if (COM_ParseToken(&text, true) && strcasecmp(com_token, "\n"))
-                                                                       if (strlen(com_token) < sizeof(sky))
-                                                                               strcpy(sky, com_token);
+                                                               if (!atoi(parameter[1]) && strcasecmp(parameter[1], "-"))
+                                                                       strlcpy(sky, parameter[1], sizeof(sky));
                                                        }
-                                                       else if (!strcasecmp(com_token, "skyparms"))
+                                                       else if (!strcasecmp(parameter[0], "cull") && numparameters >= 2)
                                                        {
-                                                               if (COM_ParseToken(&text, true) && strcasecmp(com_token, "\n"))
-                                                               {
-                                                                       if (strlen(com_token) < sizeof(sky) && !atoi(com_token) && strcasecmp(com_token, "-"))
-                                                                               strcpy(sky, com_token);
-                                                                       if (COM_ParseToken(&text, true) && strcasecmp(com_token, "\n"))
-                                                                               COM_ParseToken(&text, true);
-                                                               }
+                                                               if (!strcasecmp(parameter[1], "disable") || !strcasecmp(parameter[1], "none") || !strcasecmp(parameter[1], "twosided"))
+                                                                       flags2 |= Q3TEXTUREFLAG_TWOSIDED;
                                                        }
-                                                       else
+                                                       else if (!strcasecmp(parameter[0], "nomipmaps"))
+                                                               flags2 |= Q3TEXTUREFLAG_NOMIPMAPS;
+                                                       else if (!strcasecmp(parameter[0], "nopicmip"))
+                                                               flags2 |= Q3TEXTUREFLAG_NOPICMIP;
+                                                       else if (!strcasecmp(parameter[0], "deformvertexes") && numparameters >= 2)
                                                        {
-                                                               // look for linebreak or }
-                                                               while(COM_ParseToken(&text, true) && strcasecmp(com_token, "\n") && strcasecmp(com_token, "}"));
-                                                               // break out to top level if it was }
-                                                               if (!strcasecmp(com_token, "}"))
-                                                                       break;
+                                                               if (!strcasecmp(parameter[1], "autosprite") && numparameters == 2)
+                                                                       flags2 |= Q3TEXTUREFLAG_AUTOSPRITE;
+                                                               if (!strcasecmp(parameter[1], "autosprite2") && numparameters == 2)
+                                                                       flags2 |= Q3TEXTUREFLAG_AUTOSPRITE2;
                                                        }
                                                }
+                                               // force transparent render path for a number of odd
+                                               // shader effects to avoid bogging down the normal
+                                               // render path unnecessarily
+                                               if (flags2 & (Q3TEXTUREFLAG_ADDITIVE | Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
+                                                       flags |= Q3SURFACEPARM_TRANS;
                                                // add shader to list (shadername and flags)
                                                // actually here we just poke into the texture settings
                                                for (j = 0, out = loadmodel->brushq3.data_textures;j < loadmodel->brushq3.num_textures;j++, out++)
@@ -3750,6 +3803,8 @@ static void Mod_Q3BSP_LoadTextures(lump_t *l)
                                                        if (!strcasecmp(out->name, shadername))
                                                        {
                                                                out->surfaceparms = flags;
+                                                               out->textureflags = flags2;
+                                                               strlcpy(out->firstpasstexturename, firstpasstexturename, sizeof(out->firstpasstexturename));
                                                                if ((flags & Q3SURFACEPARM_SKY) && sky[0])
                                                                {
                                                                        // quake3 seems to append a _ to the skybox name, so this must do so as well
@@ -3779,14 +3834,16 @@ parseerror:
                        Con_DPrintf("%s: No shader found for texture \"%s\"\n", loadmodel->name, out->name);
                        out->surfaceparms = 0;
                        // these are defaults
-                       if (!strcmp(out->name, "caulk") || !strcmp(out->name, "common/caulk") || !strcmp(out->name, "textures/common/caulk")
-                        || !strcmp(out->name, "nodraw") || !strcmp(out->name, "common/nodraw") || !strcmp(out->name, "textures/common/nodraw"))
-                               out->surfaceparms |= Q3SURFACEPARM_NODRAW;
                        if (!strncmp(out->name, "textures/skies/", 15))
                                out->surfaceparms |= Q3SURFACEPARM_SKY;
-                       if (R_TextureHasAlpha(out->skin.base))
-                               out->surfaceparms |= Q3SURFACEPARM_TRANS;
+                       //if (!strcmp(out->name, "caulk") || !strcmp(out->name, "common/caulk") || !strcmp(out->name, "textures/common/caulk")
+                       // || !strcmp(out->name, "nodraw") || !strcmp(out->name, "common/nodraw") || !strcmp(out->name, "textures/common/nodraw"))
+                       //      out->surfaceparms |= Q3SURFACEPARM_NODRAW;
+                       //if (R_TextureHasAlpha(out->skin.base))
+                       //      out->surfaceparms |= Q3SURFACEPARM_TRANS;
                }
+               if (!Mod_LoadSkinFrame(&out->skin, out->name, (((out->textureflags & Q3TEXTUREFLAG_NOMIPMAPS) || (out->surfaceparms & Q3SURFACEPARM_NOMIPMAPS)) ? 0 : TEXF_MIPMAP) | TEXF_ALPHA | TEXF_PRECACHE | (out->textureflags & Q3TEXTUREFLAG_NOPICMIP ? 0 : TEXF_PICMIP), false, true, true))
+                       Mod_LoadSkinFrame(&out->skin, out->firstpasstexturename, (((out->textureflags & Q3TEXTUREFLAG_NOMIPMAPS) || (out->surfaceparms & Q3SURFACEPARM_NOMIPMAPS)) ? 0 : TEXF_MIPMAP) | TEXF_ALPHA | TEXF_PRECACHE | (out->textureflags & Q3TEXTUREFLAG_NOPICMIP ? 0 : TEXF_PICMIP), false, true, true);
        }
        Con_DPrintf("%s: %i textures missing shaders\n", loadmodel->name, c);
 }
index 2c3630e..830428d 100644 (file)
@@ -327,14 +327,24 @@ model_brushq2_t;
 #define Q3SURFACEPARM_TRANS 16777216
 #define Q3SURFACEPARM_WATER 33554432
 
+// various flags from shaders
+#define Q3TEXTUREFLAG_TWOSIDED 1
+#define Q3TEXTUREFLAG_ADDITIVE 2
+#define Q3TEXTUREFLAG_NOMIPMAPS 4
+#define Q3TEXTUREFLAG_NOPICMIP 8
+#define Q3TEXTUREFLAG_AUTOSPRITE 16
+#define Q3TEXTUREFLAG_AUTOSPRITE2 32
+
 struct q3msurface_s;
 typedef struct q3mtexture_s
 {
        char name[Q3PATHLENGTH];
+       char firstpasstexturename[Q3PATHLENGTH];
        int surfaceflags;
        int nativecontents;
        int supercontents;
        int surfaceparms;
+       int textureflags;
 
        int number;
        skinframe_t skin;