]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - model_brush.c
fix bugs with bbox vs bbox traces (the collision box's planes didn't have correct...
[xonotic/darkplaces.git] / model_brush.c
index d53885e2e0af44151ea8ac31b83109c740c9ddf6..a4092e71acbf7cfc0a8891559ffa7c69ae2f1ccb 100644 (file)
@@ -44,6 +44,12 @@ cvar_t mod_q3bsp_curves_collisions = {0, "mod_q3bsp_curves_collisions", "1", "en
 cvar_t mod_q3bsp_optimizedtraceline = {0, "mod_q3bsp_optimizedtraceline", "1", "whether to use optimized traceline code for line traces (as opposed to tracebox code)"};
 cvar_t mod_q3bsp_debugtracebrush = {0, "mod_q3bsp_debugtracebrush", "0", "selects different tracebrush bsp recursion algorithms (for debugging purposes only)"};
 
+static texture_t mod_q1bsp_texture_solid;
+static texture_t mod_q1bsp_texture_sky;
+static texture_t mod_q1bsp_texture_lava;
+static texture_t mod_q1bsp_texture_slime;
+static texture_t mod_q1bsp_texture_water;
+
 void Mod_BrushInit(void)
 {
 //     Cvar_RegisterVariable(&r_subdivide_size);
@@ -63,6 +69,31 @@ void Mod_BrushInit(void)
        Cvar_RegisterVariable(&mod_q3bsp_curves_collisions);
        Cvar_RegisterVariable(&mod_q3bsp_optimizedtraceline);
        Cvar_RegisterVariable(&mod_q3bsp_debugtracebrush);
+
+       memset(&mod_q1bsp_texture_solid, 0, sizeof(mod_q1bsp_texture_solid));
+       strlcpy(mod_q1bsp_texture_solid.name, "solid" , sizeof(mod_q1bsp_texture_solid.name));
+       mod_q1bsp_texture_solid.surfaceflags = 0;
+       mod_q1bsp_texture_solid.supercontents = SUPERCONTENTS_SOLID;
+
+       mod_q1bsp_texture_sky = mod_q1bsp_texture_solid;
+       strlcpy(mod_q1bsp_texture_sky.name, "sky", sizeof(mod_q1bsp_texture_sky.name));
+       mod_q1bsp_texture_sky.surfaceflags = Q3SURFACEFLAG_SKY | Q3SURFACEFLAG_NOIMPACT | Q3SURFACEFLAG_NOMARKS | Q3SURFACEFLAG_NODLIGHT | Q3SURFACEFLAG_NOLIGHTMAP;
+       mod_q1bsp_texture_sky.supercontents = SUPERCONTENTS_SKY | SUPERCONTENTS_NODROP;
+
+       mod_q1bsp_texture_lava = mod_q1bsp_texture_solid;
+       strlcpy(mod_q1bsp_texture_lava.name, "*lava", sizeof(mod_q1bsp_texture_lava.name));
+       mod_q1bsp_texture_lava.surfaceflags = Q3SURFACEFLAG_NOMARKS;
+       mod_q1bsp_texture_lava.supercontents = SUPERCONTENTS_LAVA | SUPERCONTENTS_NODROP;
+
+       mod_q1bsp_texture_slime = mod_q1bsp_texture_solid;
+       strlcpy(mod_q1bsp_texture_slime.name, "*slime", sizeof(mod_q1bsp_texture_slime.name));
+       mod_q1bsp_texture_slime.surfaceflags = Q3SURFACEFLAG_NOMARKS;
+       mod_q1bsp_texture_slime.supercontents = SUPERCONTENTS_SLIME;
+
+       mod_q1bsp_texture_water = mod_q1bsp_texture_solid;
+       strlcpy(mod_q1bsp_texture_water.name, "*water", sizeof(mod_q1bsp_texture_water.name));
+       mod_q1bsp_texture_water.surfaceflags = Q3SURFACEFLAG_NOMARKS;
+       mod_q1bsp_texture_water.supercontents = SUPERCONTENTS_WATER;
 }
 
 static mleaf_t *Mod_Q1BSP_PointInLeaf(model_t *model, const vec3_t p)
@@ -539,9 +570,9 @@ int Mod_Q1BSP_SuperContentsFromNativeContents(model_t *model, int nativecontents
                case CONTENTS_SLIME:
                        return SUPERCONTENTS_SLIME;
                case CONTENTS_LAVA:
-                       return SUPERCONTENTS_LAVA;
+                       return SUPERCONTENTS_LAVA | SUPERCONTENTS_NODROP;
                case CONTENTS_SKY:
-                       return SUPERCONTENTS_SKY;
+                       return SUPERCONTENTS_SKY | SUPERCONTENTS_NODROP;
        }
        return 0;
 }
@@ -612,6 +643,18 @@ loc0:
                        t->trace->inwater = true;
                if (num == 0)
                        t->trace->inopen = true;
+               if (num & SUPERCONTENTS_SOLID)
+                       t->trace->hittexture = &mod_q1bsp_texture_solid;
+               else if (num & SUPERCONTENTS_SKY)
+                       t->trace->hittexture = &mod_q1bsp_texture_sky;
+               else if (num & SUPERCONTENTS_LAVA)
+                       t->trace->hittexture = &mod_q1bsp_texture_lava;
+               else if (num & SUPERCONTENTS_SLIME)
+                       t->trace->hittexture = &mod_q1bsp_texture_slime;
+               else
+                       t->trace->hittexture = &mod_q1bsp_texture_water;
+               t->trace->hitq3surfaceflags = t->trace->hittexture->surfaceflags;
+               t->trace->hitsupercontents = num;
                if (num & t->trace->hitsupercontentsmask)
                {
                        // if the first leaf is solid, set startsolid
@@ -814,9 +857,15 @@ static void Mod_Q1BSP_TraceBox(struct model_s *model, int frame, trace_t *trace,
        else
                Mod_Q1BSP_RecursiveHullCheckPoint(&rhc, rhc.hull->firstclipnode);
 #endif
+       if (trace->fraction == 1)
+       {
+               trace->hitsupercontents = 0;
+               trace->hitq3surfaceflags = 0;
+               trace->hittexture = NULL;
+       }
 }
 
-void Collision_ClipTrace_Box(trace_t *trace, const vec3_t cmins, const vec3_t cmaxs, const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end, int hitsupercontentsmask, int boxsupercontents)
+void Collision_ClipTrace_Box(trace_t *trace, const vec3_t cmins, const vec3_t cmaxs, const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end, int hitsupercontentsmask, int boxsupercontents, int boxq3surfaceflags, texture_t *boxtexture)
 {
 #if 1
        colbrushf_t cbox;
@@ -841,6 +890,12 @@ void Collision_ClipTrace_Box(trace_t *trace, const vec3_t cmins, const vec3_t cm
        cbox_planes[3].normal[0] =  0;cbox_planes[3].normal[1] = -1;cbox_planes[3].normal[2] =  0;cbox_planes[3].dist = maxs[1] - cmins[1];
        cbox_planes[4].normal[0] =  0;cbox_planes[4].normal[1] =  0;cbox_planes[4].normal[2] =  1;cbox_planes[4].dist = cmaxs[2] - mins[2];
        cbox_planes[5].normal[0] =  0;cbox_planes[5].normal[1] =  0;cbox_planes[5].normal[2] = -1;cbox_planes[5].dist = maxs[2] - cmins[2];
+       cbox_planes[0].supercontents = boxsupercontents;cbox_planes[0].q3surfaceflags = boxq3surfaceflags;cbox_planes[0].texture = boxtexture;
+       cbox_planes[1].supercontents = boxsupercontents;cbox_planes[1].q3surfaceflags = boxq3surfaceflags;cbox_planes[1].texture = boxtexture;
+       cbox_planes[2].supercontents = boxsupercontents;cbox_planes[2].q3surfaceflags = boxq3surfaceflags;cbox_planes[2].texture = boxtexture;
+       cbox_planes[3].supercontents = boxsupercontents;cbox_planes[3].q3surfaceflags = boxq3surfaceflags;cbox_planes[3].texture = boxtexture;
+       cbox_planes[4].supercontents = boxsupercontents;cbox_planes[4].q3surfaceflags = boxq3surfaceflags;cbox_planes[4].texture = boxtexture;
+       cbox_planes[5].supercontents = boxsupercontents;cbox_planes[5].q3surfaceflags = boxq3surfaceflags;cbox_planes[5].texture = boxtexture;
        memset(trace, 0, sizeof(trace_t));
        trace->hitsupercontentsmask = hitsupercontentsmask;
        trace->fraction = 1;
@@ -1195,12 +1250,14 @@ static void Mod_Q1BSP_LoadTextures(lump_t *l)
                if (i == loadmodel->num_textures - 1)
                {
                        tx->basematerialflags |= MATERIALFLAG_WATER | MATERIALFLAG_LIGHTBOTHSIDES;
-                       tx->supercontents = SUPERCONTENTS_WATER;
+                       tx->supercontents = mod_q1bsp_texture_water.supercontents;
+                       tx->surfaceflags = mod_q1bsp_texture_water.surfaceflags;
                }
                else
                {
                        tx->basematerialflags |= MATERIALFLAG_WALL;
-                       tx->supercontents = SUPERCONTENTS_SOLID;
+                       tx->supercontents = mod_q1bsp_texture_solid.supercontents;
+                       tx->surfaceflags = mod_q1bsp_texture_solid.surfaceflags;
                }
                tx->currentframe = tx;
        }
@@ -1313,28 +1370,38 @@ static void Mod_Q1BSP_LoadTextures(lump_t *l)
                tx->basematerialflags = 0;
                if (tx->name[0] == '*')
                {
-                       // turb does not block movement
-                       tx->basematerialflags |= MATERIALFLAG_WATER | MATERIALFLAG_LIGHTBOTHSIDES;
                        // LordHavoc: some turbulent textures should not be affected by wateralpha
                        if (strncmp(tx->name,"*lava",5)
                         && strncmp(tx->name,"*teleport",9)
                         && strncmp(tx->name,"*rift",5)) // Scourge of Armagon texture
                                tx->basematerialflags |= MATERIALFLAG_WATERALPHA;
                        if (!strncmp(tx->name, "*lava", 5))
-                               tx->supercontents = SUPERCONTENTS_LAVA;
+                       {
+                               tx->supercontents = mod_q1bsp_texture_lava.supercontents;
+                               tx->surfaceflags = mod_q1bsp_texture_lava.surfaceflags;
+                       }
                        else if (!strncmp(tx->name, "*slime", 6))
-                               tx->supercontents = SUPERCONTENTS_SLIME;
+                       {
+                               tx->supercontents = mod_q1bsp_texture_slime.supercontents;
+                               tx->surfaceflags = mod_q1bsp_texture_slime.surfaceflags;
+                       }
                        else
-                               tx->supercontents = SUPERCONTENTS_WATER;
+                       {
+                               tx->supercontents = mod_q1bsp_texture_water.supercontents;
+                               tx->surfaceflags = mod_q1bsp_texture_water.surfaceflags;
+                       }
+                       tx->basematerialflags |= MATERIALFLAG_WATER | MATERIALFLAG_LIGHTBOTHSIDES;
                }
                else if (tx->name[0] == 's' && tx->name[1] == 'k' && tx->name[2] == 'y')
                {
-                       tx->supercontents = SUPERCONTENTS_SKY;
+                       tx->supercontents = mod_q1bsp_texture_sky.supercontents;
+                       tx->surfaceflags = mod_q1bsp_texture_sky.surfaceflags;
                        tx->basematerialflags |= MATERIALFLAG_SKY;
                }
                else
                {
-                       tx->supercontents = SUPERCONTENTS_SOLID;
+                       tx->supercontents = mod_q1bsp_texture_solid.supercontents;
+                       tx->surfaceflags = mod_q1bsp_texture_solid.surfaceflags;
                        tx->basematerialflags |= MATERIALFLAG_WALL;
                }
                if (tx->skin.fog)
@@ -2288,6 +2355,8 @@ static void Mod_Q1BSP_LoadClipnodes(lump_t *l, hullinfo_t *hullinfo)
                out->planenum = LittleLong(in->planenum);
                out->children[0] = LittleShort(in->children[0]);
                out->children[1] = LittleShort(in->children[1]);
+               if (out->planenum < 0 || out->planenum >= loadmodel->brush.num_planes)
+                       Host_Error("Corrupt clipping hull(out of range planenum)");
                if (out->children[0] >= count || out->children[1] >= count)
                        Host_Error("Corrupt clipping hull(out of range child)");
        }
@@ -3335,7 +3404,7 @@ void Mod_Q1BSP_Load(model_t *mod, void *buffer, void *bufferend)
 
        //Mod_Q1BSP_ProcessLightList();
 
-       if (developer.integer)
+       if (developer.integer >= 10)
                Con_Printf("Some stats for q1bsp model \"%s\": %i faces, %i nodes, %i leafs, %i visleafs, %i visleafportals\n", loadmodel->name, loadmodel->num_surfaces, loadmodel->brush.num_nodes, loadmodel->brush.num_leafs, mod->brush.num_pvsclusters, loadmodel->brush.num_portals);
 }
 
@@ -3897,7 +3966,7 @@ static void Mod_Q3BSP_LoadTextures(lump_t *l)
                                                                                if (!COM_ParseToken(&text, true))
                                                                                        break;
                                                                        }
-                                                                       if (developer.integer >= 2)
+                                                                       if (developer.integer >= 100)
                                                                        {
                                                                                Con_Printf("%s %i: ", shadername, passnumber);
                                                                                for (j = 0;j < numparameters;j++)
@@ -3942,7 +4011,7 @@ static void Mod_Q3BSP_LoadTextures(lump_t *l)
                                                        }
                                                        if (i == 0 && !strcasecmp(com_token, "}"))
                                                                break;
-                                                       if (developer.integer >= 2)
+                                                       if (developer.integer >= 100)
                                                        {
                                                                Con_Printf("%s: ", shadername);
                                                                for (j = 0;j < numparameters;j++)
@@ -4180,7 +4249,7 @@ static void Mod_Q3BSP_LoadBrushes(lump_t *l)
        q3dbrush_t *in;
        q3mbrush_t *out;
        int i, j, n, c, count, maxplanes;
-       mplane_t *planes;
+       colplanef_t *planes;
 
        in = (q3dbrush_t *)(mod_base + l->fileofs);
        if (l->filelen % sizeof(*in))
@@ -4213,15 +4282,18 @@ static void Mod_Q3BSP_LoadBrushes(lump_t *l)
                        maxplanes = out->numbrushsides;
                        if (planes)
                                Mem_Free(planes);
-                       planes = (mplane_t *)Mem_Alloc(tempmempool, sizeof(mplane_t) * maxplanes);
+                       planes = (colplanef_t *)Mem_Alloc(tempmempool, sizeof(colplanef_t) * maxplanes);
                }
                for (j = 0;j < out->numbrushsides;j++)
                {
                        VectorCopy(out->firstbrushside[j].plane->normal, planes[j].normal);
                        planes[j].dist = out->firstbrushside[j].plane->dist;
+                       planes[j].supercontents = out->firstbrushside[j].texture->supercontents;
+                       planes[j].q3surfaceflags = out->firstbrushside[j].texture->surfaceflags;
+                       planes[j].texture = out->firstbrushside[j].texture;
                }
                // make the colbrush from the planes
-               out->colbrushf = Collision_NewBrushFromPlanes(loadmodel->mempool, out->numbrushsides, planes, out->texture->supercontents);
+               out->colbrushf = Collision_NewBrushFromPlanes(loadmodel->mempool, out->numbrushsides, planes);
        }
        if (planes)
                Mem_Free(planes);
@@ -4434,7 +4506,7 @@ static void Mod_Q3BSP_LoadFaces(lump_t *l)
                        n = LittleLong(in->effectindex);
                        if (n < -1 || n >= loadmodel->brushq3.num_effects)
                        {
-                               if (developer.integer >= 2)
+                               if (developer.integer >= 100)
                                        Con_Printf("Mod_Q3BSP_LoadFaces: face #%i (texture \"%s\"): invalid effectindex %i (%i effects)\n", i, out->texture->name, n, loadmodel->brushq3.num_effects);
                                n = -1;
                        }
@@ -4521,7 +4593,7 @@ static void Mod_Q3BSP_LoadFaces(lump_t *l)
                                numtriangles = (finalwidth - 1) * (finalheight - 1) * 2;
                                break;
                        case Q3FACETYPE_FLARE:
-                               if (developer.integer >= 2)
+                               if (developer.integer >= 100)
                                        Con_Printf("Mod_Q3BSP_LoadFaces: face #%i (texture \"%s\"): Q3FACETYPE_FLARE not supported (yet)\n", i, out->texture->name);
                                // don't render it
                                continue;
@@ -4610,7 +4682,7 @@ static void Mod_Q3BSP_LoadFaces(lump_t *l)
                                Q3PatchTesselateFloat(4, sizeof(float[4]), (out->groupmesh->data_lightmapcolor4f + 4 * out->num_firstvertex), patchsize[0], patchsize[1], sizeof(float[4]), originalcolor4f, xtess, ytess);
                                Q3PatchTriangleElements((out->groupmesh->data_element3i + 3 * out->num_firsttriangle), finalwidth, finalheight, out->num_firstvertex);
                                out->num_triangles = Mod_RemoveDegenerateTriangles(out->num_triangles, (out->groupmesh->data_element3i + 3 * out->num_firsttriangle), (out->groupmesh->data_element3i + 3 * out->num_firsttriangle), out->groupmesh->data_vertex3f);
-                               if (developer.integer >= 2)
+                               if (developer.integer >= 100)
                                {
                                        if (out->num_triangles < finaltriangles)
                                                Con_Printf("Mod_Q3BSP_LoadFaces: %ix%i curve subdivided to %i vertices / %i triangles, %i degenerate triangles removed (leaving %i)\n", patchsize[0], patchsize[1], out->num_vertices, finaltriangles, finaltriangles - out->num_triangles, out->num_triangles);
@@ -4653,7 +4725,7 @@ static void Mod_Q3BSP_LoadFaces(lump_t *l)
                                oldnumtriangles = out->num_triangles;
                                oldnumtriangles2 = out->num_collisiontriangles;
                                out->num_collisiontriangles = Mod_RemoveDegenerateTriangles(out->num_collisiontriangles, out->data_collisionelement3i, out->data_collisionelement3i, out->data_collisionvertex3f);
-                               if (developer.integer)
+                               if (developer.integer >= 100)
                                        Con_Printf("Mod_Q3BSP_LoadFaces: %ix%i curve became %i:%i vertices / %i:%i triangles (%i:%i degenerate)\n", patchsize[0], patchsize[1], out->num_vertices, out->num_collisionvertices, oldnumtriangles, oldnumtriangles2, oldnumtriangles - out->num_triangles, oldnumtriangles2 - out->num_collisiontriangles);
                                break;
                        default:
@@ -5139,7 +5211,7 @@ static void Mod_Q3BSP_TraceLine_RecursiveBSPNode(trace_t *trace, model_t *model,
                        if (surface->num_collisiontriangles && surface->collisionmarkframe != markframe && BoxesOverlap(nodesegmentmins, nodesegmentmaxs, surface->mins, surface->maxs))
                        {
                                surface->collisionmarkframe = markframe;
-                               Collision_TraceLineTriangleMeshFloat(trace, linestart, lineend, surface->num_collisiontriangles, surface->data_collisionelement3i, surface->data_collisionvertex3f, surface->texture->supercontents, segmentmins, segmentmaxs);
+                               Collision_TraceLineTriangleMeshFloat(trace, linestart, lineend, surface->num_collisiontriangles, surface->data_collisionelement3i, surface->data_collisionvertex3f, surface->texture->supercontents, surface->texture->surfaceflags, surface->texture, segmentmins, segmentmaxs);
                        }
                }
        }
@@ -5214,7 +5286,7 @@ static void Mod_Q3BSP_TraceBrush_RecursiveBSPNode(trace_t *trace, model_t *model
                        if (surface->num_collisiontriangles && surface->collisionmarkframe != markframe && BoxesOverlap(nodesegmentmins, nodesegmentmaxs, surface->mins, surface->maxs))
                        {
                                surface->collisionmarkframe = markframe;
-                               Collision_TraceBrushTriangleMeshFloat(trace, thisbrush_start, thisbrush_end, surface->num_collisiontriangles, surface->data_collisionelement3i, surface->data_collisionvertex3f, surface->texture->supercontents, segmentmins, segmentmaxs);
+                               Collision_TraceBrushTriangleMeshFloat(trace, thisbrush_start, thisbrush_end, surface->num_collisiontriangles, surface->data_collisionelement3i, surface->data_collisionvertex3f, surface->texture->supercontents, surface->texture->surfaceflags, surface->texture, segmentmins, segmentmaxs);
                        }
                }
        }
@@ -5262,7 +5334,7 @@ static void Mod_Q3BSP_TraceBox(model_t *model, int frame, trace_t *trace, const
                                if (mod_q3bsp_curves_collisions.integer)
                                        for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
                                                if (surface->num_collisiontriangles)
-                                                       Collision_TraceLineTriangleMeshFloat(trace, start, end, surface->num_collisiontriangles, surface->data_collisionelement3i, surface->data_collisionvertex3f, surface->texture->supercontents, segmentmins, segmentmaxs);
+                                                       Collision_TraceLineTriangleMeshFloat(trace, start, end, surface->num_collisiontriangles, surface->data_collisionelement3i, surface->data_collisionvertex3f, surface->texture->supercontents, surface->texture->surfaceflags, surface->texture, segmentmins, segmentmaxs);
                        }
                        else
                                Mod_Q3BSP_TraceLine_RecursiveBSPNode(trace, model, model->brush.data_nodes, start, end, 0, 1, start, end, ++markframe, segmentmins, segmentmaxs);
@@ -5283,8 +5355,8 @@ static void Mod_Q3BSP_TraceBox(model_t *model, int frame, trace_t *trace, const
                VectorAdd(start, boxmaxs, boxstartmaxs);
                VectorAdd(end, boxmins, boxendmins);
                VectorAdd(end, boxmaxs, boxendmaxs);
-               thisbrush_start = Collision_BrushForBox(&identitymatrix, boxstartmins, boxstartmaxs);
-               thisbrush_end = Collision_BrushForBox(&identitymatrix, boxendmins, boxendmaxs);
+               thisbrush_start = Collision_BrushForBox(&identitymatrix, boxstartmins, boxstartmaxs, 0, 0, NULL);
+               thisbrush_end = Collision_BrushForBox(&identitymatrix, boxendmins, boxendmaxs, 0, 0, NULL);
                if (model->brush.submodel)
                {
                        for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
@@ -5293,7 +5365,7 @@ static void Mod_Q3BSP_TraceBox(model_t *model, int frame, trace_t *trace, const
                        if (mod_q3bsp_curves_collisions.integer)
                                for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
                                        if (surface->num_collisiontriangles)
-                                               Collision_TraceBrushTriangleMeshFloat(trace, thisbrush_start, thisbrush_end, surface->num_collisiontriangles, surface->data_collisionelement3i, surface->data_collisionvertex3f, surface->texture->supercontents, segmentmins, segmentmaxs);
+                                               Collision_TraceBrushTriangleMeshFloat(trace, thisbrush_start, thisbrush_end, surface->num_collisiontriangles, surface->data_collisionelement3i, surface->data_collisionvertex3f, surface->texture->supercontents, surface->texture->surfaceflags, surface->texture, segmentmins, segmentmaxs);
                }
                else
                        Mod_Q3BSP_TraceBrush_RecursiveBSPNode(trace, model, model->brush.data_nodes, thisbrush_start, thisbrush_end, ++markframe, segmentmins, segmentmaxs);