]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - model_brush.c
added cvar_string extension at the request of Paul Timofeyev
[xonotic/darkplaces.git] / model_brush.c
index a8b6cd53e18c210dabc77c40cce573882492ecef..641c1eddbf097865fa8a3fa4dc3ec02520bdfca6 100644 (file)
@@ -416,11 +416,17 @@ loc0:
                        // if the first leaf is solid, set startsolid
                        if (t->trace->allsolid)
                                t->trace->startsolid = true;
+#ifdef COLLISIONPARANOID
+                       Con_Printf("S");
+#endif
                        return HULLCHECKSTATE_SOLID;
                }
                else
                {
                        t->trace->allsolid = false;
+#ifdef COLLISIONPARANOID
+                       Con_Printf("E");
+#endif
                        return HULLCHECKSTATE_EMPTY;
                }
        }
@@ -444,6 +450,9 @@ loc0:
        {
                if (t2 < 0)
                {
+#ifdef COLLISIONPARANOID
+                       Con_Printf("<");
+#endif
                        num = node->children[1];
                        goto loc0;
                }
@@ -453,6 +462,9 @@ loc0:
        {
                if (t2 >= 0)
                {
+#ifdef COLLISIONPARANOID
+                       Con_Printf(">");
+#endif
                        num = node->children[0];
                        goto loc0;
                }
@@ -461,6 +473,9 @@ loc0:
 
        // the line intersects, find intersection point
        // LordHavoc: this uses the original trace for maximum accuracy
+#ifdef COLLISIONPARANOID
+       Con_Printf("M");
+#endif
        if (plane->type < 3)
        {
                t1 = t->start[plane->type] - plane->dist;
@@ -506,9 +521,36 @@ loc0:
        midf = t1 / (t1 - t2);
        t->trace->fraction = bound(0.0f, midf, 1.0);
 
+#ifdef COLLISIONPARANOID
+       Con_Printf("D");
+#endif
        return HULLCHECKSTATE_DONE;
 }
 
+#ifndef COLLISIONPARANOID
+static int Mod_Q1BSP_RecursiveHullCheckPoint(RecursiveHullCheckTraceInfo_t *t, int num)
+{
+       while (num >= 0)
+               num = t->hull->clipnodes[num].children[(t->hull->planes[t->hull->clipnodes[num].planenum].type < 3 ? t->start[t->hull->planes[t->hull->clipnodes[num].planenum].type] : DotProduct(t->hull->planes[t->hull->clipnodes[num].planenum].normal, t->start)) < t->hull->planes[t->hull->clipnodes[num].planenum].dist];
+       num = Mod_Q1BSP_SuperContentsFromNativeContents(NULL, num);
+       t->trace->startsupercontents |= num;
+       if (num & SUPERCONTENTS_LIQUIDSMASK)
+               t->trace->inwater = true;
+       if (num == 0)
+               t->trace->inopen = true;
+       if (num & t->trace->hitsupercontentsmask)
+       {
+               t->trace->allsolid = t->trace->startsolid = true;
+               return HULLCHECKSTATE_SOLID;
+       }
+       else
+       {
+               t->trace->allsolid = t->trace->startsolid = false;
+               return HULLCHECKSTATE_EMPTY;
+       }
+}
+#endif
+
 static void Mod_Q1BSP_TraceBox(struct model_s *model, int frame, trace_t *trace, const vec3_t boxstartmins, const vec3_t boxstartmaxs, const vec3_t boxendmins, const vec3_t boxendmaxs, int hitsupercontentsmask)
 {
        // this function currently only supports same size start and end
@@ -526,7 +568,9 @@ static void Mod_Q1BSP_TraceBox(struct model_s *model, int frame, trace_t *trace,
                rhc.hull = &model->brushq1.hulls[0]; // 0x0x0
        else if (model->brush.ishlbsp)
        {
-               if (boxsize[0] <= 32)
+               // LordHavoc: this has to have a minor tolerance (the .1) because of
+               // minor float precision errors from the box being transformed around
+               if (boxsize[0] < 32.1)
                {
                        if (boxsize[2] < 54) // pick the nearest of 36 or 72
                                rhc.hull = &model->brushq1.hulls[3]; // 32x32x36
@@ -538,7 +582,9 @@ static void Mod_Q1BSP_TraceBox(struct model_s *model, int frame, trace_t *trace,
        }
        else
        {
-               if (boxsize[0] <= 32)
+               // LordHavoc: this has to have a minor tolerance (the .1) because of
+               // minor float precision errors from the box being transformed around
+               if (boxsize[0] < 32.1)
                        rhc.hull = &model->brushq1.hulls[1]; // 32x32x56
                else
                        rhc.hull = &model->brushq1.hulls[2]; // 64x64x88
@@ -546,7 +592,16 @@ static void Mod_Q1BSP_TraceBox(struct model_s *model, int frame, trace_t *trace,
        VectorSubtract(boxstartmins, rhc.hull->clip_mins, rhc.start);
        VectorSubtract(boxendmins, rhc.hull->clip_mins, rhc.end);
        VectorSubtract(rhc.end, rhc.start, rhc.dist);
+#ifdef COLLISIONPARANOID
+       Con_Printf("t(%f %f %f,%f %f %f,%i %f %f %f)", rhc.start[0], rhc.start[1], rhc.start[2], rhc.end[0], rhc.end[1], rhc.end[2], rhc.hull - model->brushq1.hulls, rhc.hull->clip_mins[0], rhc.hull->clip_mins[1], rhc.hull->clip_mins[2]);
        Mod_Q1BSP_RecursiveHullCheck(&rhc, rhc.hull->firstclipnode, 0, 1, rhc.start, rhc.end);
+       Con_Printf("\n");
+#else
+       if (DotProduct(rhc.dist, rhc.dist))
+               Mod_Q1BSP_RecursiveHullCheck(&rhc, rhc.hull->firstclipnode, 0, 1, rhc.start, rhc.end);
+       else
+               Mod_Q1BSP_RecursiveHullCheckPoint(&rhc, rhc.hull->firstclipnode);
+#endif
 }
 
 static int Mod_Q1BSP_LightPoint_RecursiveBSPNode(vec3_t ambientcolor, vec3_t diffusecolor, vec3_t diffusenormal, const mnode_t *node, float x, float y, float startz, float endz)
@@ -3309,6 +3364,12 @@ static void Mod_Q3BSP_LoadTextures(lump_t *l)
        q3dtexture_t *in;
        q3mtexture_t *out;
        int i, count;
+       int j, c;
+       fssearch_t *search;
+       char *f;
+       const char *text;
+       int flags;
+       char shadername[Q3PATHLENGTH];
 
        in = (void *)(mod_base + l->fileofs);
        if (l->filelen % sizeof(*in))
@@ -3319,10 +3380,6 @@ static void Mod_Q3BSP_LoadTextures(lump_t *l)
        loadmodel->brushq3.data_textures = out;
        loadmodel->brushq3.num_textures = count;
 
-       // FIXME: do a quick parse of the shader files to see if any names match
-       // up and get their surfaceparms
-
-
        for (i = 0;i < count;i++, in++, out++)
        {
                out->number = i;
@@ -3331,15 +3388,151 @@ static void Mod_Q3BSP_LoadTextures(lump_t *l)
                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, false, true, true);
-               out->renderflags = 0;
-               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->renderflags |= Q3MTEXTURERENDERFLAGS_NODRAW;
-               if (!strncmp(out->name, "textures/skies/", 15))
-                       out->renderflags |= Q3MTEXTURERENDERFLAGS_SKY;
-               if (R_TextureHasAlpha(out->skin.base))
-                       out->renderflags |= Q3MTEXTURERENDERFLAGS_TRANSPARENT;
+               out->surfaceparms = -1;
+       }
+
+       // do a quick parse of shader files to get surfaceparms
+       if ((search = FS_Search("scripts/*.shader", true, false)))
+       {
+               for (i = 0;i < search->numfilenames;i++)
+               {
+                       if ((f = FS_LoadFile(search->filenames[i], false)))
+                       {
+                               text = f;
+                               while (COM_ParseToken(&text, false))
+                               {
+                                       snprintf(shadername, sizeof(shadername), "%s", com_token);
+                                       flags = 0;
+                                       if (COM_ParseToken(&text, false) && !strcmp(com_token, "{"))
+                                       {
+                                               while (COM_ParseToken(&text, false))
+                                               {
+                                                       if (!strcmp(com_token, "}"))
+                                                               break;
+                                                       else if (!strcmp(com_token, "{"))
+                                                       {
+                                                               while (COM_ParseToken(&text, false))
+                                                               {
+                                                                       if (!strcmp(com_token, "}"))
+                                                                               break;
+                                                               }
+                                                       }
+                                                       else if (!strcmp(com_token, "surfaceparm"))
+                                                       {
+                                                               if (COM_ParseToken(&text, true) && strcmp(com_token, "\n"))
+                                                               {
+                                                                       if (!strcmp(com_token, "alphashadow"))
+                                                                               flags |= Q3SURFACEPARM_ALPHASHADOW;
+                                                                       else if (!strcmp(com_token, "areaportal"))
+                                                                               flags |= Q3SURFACEPARM_AREAPORTAL;
+                                                                       else if (!strcmp(com_token, "clusterportal"))
+                                                                               flags |= Q3SURFACEPARM_CLUSTERPORTAL;
+                                                                       else if (!strcmp(com_token, "detail"))
+                                                                               flags |= Q3SURFACEPARM_DETAIL;
+                                                                       else if (!strcmp(com_token, "donotenter"))
+                                                                               flags |= Q3SURFACEPARM_DONOTENTER;
+                                                                       else if (!strcmp(com_token, "fog"))
+                                                                               flags |= Q3SURFACEPARM_FOG;
+                                                                       else if (!strcmp(com_token, "lava"))
+                                                                               flags |= Q3SURFACEPARM_LAVA;
+                                                                       else if (!strcmp(com_token, "lightfilter"))
+                                                                               flags |= Q3SURFACEPARM_LIGHTFILTER;
+                                                                       else if (!strcmp(com_token, "metalsteps"))
+                                                                               flags |= Q3SURFACEPARM_METALSTEPS;
+                                                                       else if (!strcmp(com_token, "nodamage"))
+                                                                               flags |= Q3SURFACEPARM_NODAMAGE;
+                                                                       else if (!strcmp(com_token, "nodlight"))
+                                                                               flags |= Q3SURFACEPARM_NODLIGHT;
+                                                                       else if (!strcmp(com_token, "nodraw"))
+                                                                               flags |= Q3SURFACEPARM_NODRAW;
+                                                                       else if (!strcmp(com_token, "nodrop"))
+                                                                               flags |= Q3SURFACEPARM_NODROP;
+                                                                       else if (!strcmp(com_token, "noimpact"))
+                                                                               flags |= Q3SURFACEPARM_NOIMPACT;
+                                                                       else if (!strcmp(com_token, "nolightmap"))
+                                                                               flags |= Q3SURFACEPARM_NOLIGHTMAP;
+                                                                       else if (!strcmp(com_token, "nomarks"))
+                                                                               flags |= Q3SURFACEPARM_NOMARKS;
+                                                                       else if (!strcmp(com_token, "nomipmaps"))
+                                                                               flags |= Q3SURFACEPARM_NOMIPMAPS;
+                                                                       else if (!strcmp(com_token, "nonsolid"))
+                                                                               flags |= Q3SURFACEPARM_NONSOLID;
+                                                                       else if (!strcmp(com_token, "origin"))
+                                                                               flags |= Q3SURFACEPARM_ORIGIN;
+                                                                       else if (!strcmp(com_token, "playerclip"))
+                                                                               flags |= Q3SURFACEPARM_PLAYERCLIP;
+                                                                       else if (!strcmp(com_token, "sky"))
+                                                                               flags |= Q3SURFACEPARM_SKY;
+                                                                       else if (!strcmp(com_token, "slick"))
+                                                                               flags |= Q3SURFACEPARM_SLICK;
+                                                                       else if (!strcmp(com_token, "slime"))
+                                                                               flags |= Q3SURFACEPARM_SLIME;
+                                                                       else if (!strcmp(com_token, "structural"))
+                                                                               flags |= Q3SURFACEPARM_STRUCTURAL;
+                                                                       else if (!strcmp(com_token, "trans"))
+                                                                               flags |= Q3SURFACEPARM_TRANS;
+                                                                       else if (!strcmp(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) || strcmp(com_token, "\n"))
+                                                                       {
+                                                                               Con_Printf("%s parsing error: surfaceparm only takes one parameter.\n", search->filenames[i]);
+                                                                               goto parseerror;
+                                                                       }
+                                                               }
+                                                               else
+                                                               {
+                                                                       Con_Printf("%s parsing error: surfaceparm expects a parameter.\n", search->filenames[i]);
+                                                                       goto parseerror;
+                                                               }
+                                                       }
+                                                       else
+                                                       {
+                                                               // look for linebreak or }
+                                                               while(COM_ParseToken(&text, true) && strcmp(com_token, "\n") && strcmp(com_token, "}"));
+                                                               // break out to top level if it was }
+                                                               if (!strcmp(com_token, "}"))
+                                                                       break;
+                                                       }
+                                               }
+                                               // 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++)
+                                                       if (!strcmp(out->name, shadername))
+                                                               out->surfaceparms = flags;
+                                       }
+                                       else
+                                       {
+                                               Con_Printf("%s parsing error - expected \"{\", found \"%s\"\n", search->filenames[i], com_token);
+                                               goto parseerror;
+                                       }
+                               }
+parseerror:
+                               Mem_Free(f);
+                       }
+               }
+       }
+
+       c = 0;
+       for (j = 0, out = loadmodel->brushq3.data_textures;j < loadmodel->brushq3.num_textures;j++, out++)
+       {
+               if (out->surfaceparms == -1)
+               {
+                       c++;
+                       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;
+               }
        }
+       Con_DPrintf("%s: %i textures missing shaders\n", loadmodel->name, c);
 }
 
 static void Mod_Q3BSP_LoadPlanes(lump_t *l)
@@ -4680,7 +4873,7 @@ void Mod_Q3BSP_Load(model_t *mod, void *buffer)
                mod->radius2 = modelradius * modelradius;
 
                for (j = 0;j < mod->brushq3.data_thismodel->numfaces;j++)
-                       if (mod->brushq3.data_thismodel->firstface[j].texture->renderflags & Q3MTEXTURERENDERFLAGS_SKY)
+                       if (mod->brushq3.data_thismodel->firstface[j].texture->surfaceflags & Q3SURFACEFLAG_SKY)
                                break;
                if (j < mod->brushq3.data_thismodel->numfaces)
                        mod->DrawSky = R_Q3BSP_DrawSky;