X-Git-Url: http://git.xonotic.org/?a=blobdiff_plain;f=model_brush.c;h=a5c0c1ce30a5db57f7a4c3f6e432cf7113d67784;hb=6200e1894c002b5aceb94c89f1c9bd9fa0e51020;hp=fc63c983900a4dc92a7f38fd4a7a845ff490a693;hpb=efe66e1a99b2ad1b6aaa2a5c131237b9cb7b4ee4;p=xonotic%2Fdarkplaces.git diff --git a/model_brush.c b/model_brush.c index fc63c983..a5c0c1ce 100644 --- a/model_brush.c +++ b/model_brush.c @@ -27,6 +27,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. //cvar_t r_subdivide_size = {CVAR_SAVE, "r_subdivide_size", "128", "how large water polygons should be (smaller values produce more polygons which give better warping effects)"}; +cvar_t mod_bsp_portalize = {0, "mod_bsp_portalize", "1", "enables portal generation from BSP tree (may take several seconds per map), used by r_drawportals, r_useportalculling, r_shadow_realtime_world_compileportalculling, sv_cullentities_portal"}; cvar_t r_novis = {0, "r_novis", "0", "draws whole level, see also sv_cullentities_pvs 0"}; cvar_t r_nosurftextures = {0, "r_nosurftextures", "0", "pretends there was no texture lump found in the q1bsp/hlbsp loading (useful for debugging this rare case)"}; cvar_t r_subdivisions_tolerance = {0, "r_subdivisions_tolerance", "4", "maximum error tolerance on curve subdivision for rendering purposes (in other words, the curves will be given as many polygons as necessary to represent curves at this quality)"}; @@ -46,6 +47,8 @@ cvar_t mod_q3bsp_lightmapmergepower = {CVAR_SAVE, "mod_q3bsp_lightmapmergepower" cvar_t mod_q3bsp_nolightmaps = {CVAR_SAVE, "mod_q3bsp_nolightmaps", "0", "do not load lightmaps in Q3BSP maps (to save video RAM, but be warned: it looks ugly)"}; cvar_t mod_q3bsp_tracelineofsight_brushes = {0, "mod_q3bsp_tracelineofsight_brushes", "0", "enables culling of entities behind detail brushes, curves, etc"}; cvar_t mod_q3shader_default_offsetmapping = {CVAR_SAVE, "mod_q3shader_default_offsetmapping", "1", "use offsetmapping by default on all surfaces"}; +cvar_t mod_q3shader_default_polygonfactor = {0, "mod_q3shader_default_polygonfactor", "0", "biases depth values of 'polygonoffset' shaders to prevent z-fighting artifacts"}; +cvar_t mod_q3shader_default_polygonoffset = {0, "mod_q3shader_default_polygonoffset", "-2", "biases depth values of 'polygonoffset' shaders to prevent z-fighting artifacts"}; cvar_t mod_q1bsp_polygoncollisions = {0, "mod_q1bsp_polygoncollisions", "0", "disables use of precomputed cliphulls and instead collides with polygons (uses Bounding Interval Hierarchy optimizations)"}; cvar_t mod_collision_bih = {0, "mod_collision_bih", "1", "enables use of generated Bounding Interval Hierarchy tree instead of compiled bsp tree in collision code"}; @@ -60,6 +63,7 @@ static texture_t mod_q1bsp_texture_water; void Mod_BrushInit(void) { // Cvar_RegisterVariable(&r_subdivide_size); + Cvar_RegisterVariable(&mod_bsp_portalize); Cvar_RegisterVariable(&r_novis); Cvar_RegisterVariable(&r_nosurftextures); Cvar_RegisterVariable(&r_subdivisions_tolerance); @@ -79,6 +83,8 @@ void Mod_BrushInit(void) Cvar_RegisterVariable(&mod_q3bsp_nolightmaps); Cvar_RegisterVariable(&mod_q3bsp_tracelineofsight_brushes); Cvar_RegisterVariable(&mod_q3shader_default_offsetmapping); + Cvar_RegisterVariable(&mod_q3shader_default_polygonfactor); + Cvar_RegisterVariable(&mod_q3shader_default_polygonoffset); Cvar_RegisterVariable(&mod_q1bsp_polygoncollisions); Cvar_RegisterVariable(&mod_collision_bih); Cvar_RegisterVariable(&mod_recalculatenodeboxes); @@ -1287,6 +1293,188 @@ void Mod_Q1BSP_LightPoint(dp_model_t *model, const vec3_t p, vec3_t ambientcolor Mod_Q1BSP_LightPoint_RecursiveBSPNode(model, ambientcolor, diffusecolor, diffusenormal, model->brush.data_nodes + model->brushq1.hulls[0].firstclipnode, p[0], p[1], p[2] + 0.125, p[2] - 65536); } +static const texture_t *Mod_Q1BSP_TraceLineAgainstSurfacesFindTextureOnNode(RecursiveHullCheckTraceInfo_t *t, const dp_model_t *model, const mnode_t *node, double mid[3]) +{ + int i; + int j; + int k; + const msurface_t *surface; + float normal[3]; + float v0[3]; + float v1[3]; + float edgedir[3]; + float edgenormal[3]; + float p[4]; + float midf; + float t1; + float t2; + VectorCopy(mid, p); + p[3] = 1; + surface = model->data_surfaces + node->firstsurface; + for (i = 0;i < node->numsurfaces;i++, surface++) + { + // skip surfaces whose bounding box does not include the point +// if (!BoxesOverlap(mid, mid, surface->mins, surface->maxs)) +// continue; + // skip faces with contents we don't care about + if (!(t->trace->hitsupercontentsmask & surface->texture->supercontents)) + continue; + // get the surface normal - since it is flat we know any vertex normal will suffice + VectorCopy(model->surfmesh.data_normal3f + 3 * surface->num_firstvertex, normal); + // skip backfaces + if (DotProduct(t->dist, normal) > 0) + continue; + // iterate edges and see if the point is outside one of them + for (j = 0, k = surface->num_vertices - 1;j < surface->num_vertices;k = j, j++) + { + VectorCopy(model->surfmesh.data_vertex3f + 3 * (surface->num_firstvertex + k), v0); + VectorCopy(model->surfmesh.data_vertex3f + 3 * (surface->num_firstvertex + j), v1); + VectorSubtract(v0, v1, edgedir); + CrossProduct(edgedir, normal, edgenormal); + if (DotProduct(edgenormal, p) > DotProduct(edgenormal, v0)) + break; + } + // if the point is outside one of the edges, it is not within the surface + if (j < surface->num_vertices) + continue; + + // we hit a surface, this is the impact point... + VectorCopy(normal, t->trace->plane.normal); + t->trace->plane.dist = DotProduct(normal, p); + + // calculate the true fraction + t1 = DotProduct(t->start, t->trace->plane.normal) - t->trace->plane.dist; + t2 = DotProduct(t->end, t->trace->plane.normal) - t->trace->plane.dist; + midf = t1 / (t1 - t2); + t->trace->realfraction = midf; + + // calculate the return fraction which is nudged off the surface a bit + midf = (t1 - DIST_EPSILON) / (t1 - t2); + t->trace->fraction = bound(0, midf, 1); + + if (collision_prefernudgedfraction.integer) + t->trace->realfraction = t->trace->fraction; + + t->trace->hittexture = surface->texture->currentframe; + t->trace->hitq3surfaceflags = t->trace->hittexture->surfaceflags; + t->trace->hitsupercontents = t->trace->hittexture->supercontents; + return surface->texture->currentframe; + } + return NULL; +} + +static int Mod_Q1BSP_TraceLineAgainstSurfacesRecursiveBSPNode(RecursiveHullCheckTraceInfo_t *t, const dp_model_t *model, const mnode_t *node, const double p1[3], const double p2[3]) +{ + const mplane_t *plane; + double t1, t2; + int side; + double midf, mid[3]; + const mleaf_t *leaf; + + while (node->plane) + { + plane = node->plane; + if (plane->type < 3) + { + t1 = p1[plane->type] - plane->dist; + t2 = p2[plane->type] - plane->dist; + } + else + { + t1 = DotProduct (plane->normal, p1) - plane->dist; + t2 = DotProduct (plane->normal, p2) - plane->dist; + } + if (t1 < 0) + { + if (t2 < 0) + { + node = node->children[1]; + continue; + } + side = 1; + } + else + { + if (t2 >= 0) + { + node = node->children[0]; + continue; + } + side = 0; + } + + // the line intersects, find intersection point + // LordHavoc: this uses the original trace for maximum accuracy + if (plane->type < 3) + { + t1 = t->start[plane->type] - plane->dist; + t2 = t->end[plane->type] - plane->dist; + } + else + { + t1 = DotProduct (plane->normal, t->start) - plane->dist; + t2 = DotProduct (plane->normal, t->end) - plane->dist; + } + + midf = t1 / (t1 - t2); + VectorMA(t->start, midf, t->dist, mid); + + // recurse both sides, front side first, return if we hit a surface + if (Mod_Q1BSP_TraceLineAgainstSurfacesRecursiveBSPNode(t, model, node->children[side], p1, mid) == HULLCHECKSTATE_DONE) + return HULLCHECKSTATE_DONE; + + // test each surface on the node + Mod_Q1BSP_TraceLineAgainstSurfacesFindTextureOnNode(t, model, node, mid); + if (t->trace->hittexture) + return HULLCHECKSTATE_DONE; + + // recurse back side + return Mod_Q1BSP_TraceLineAgainstSurfacesRecursiveBSPNode(t, model, node->children[side ^ 1], mid, p2); + } + leaf = (const mleaf_t *)node; + side = Mod_Q1BSP_SuperContentsFromNativeContents(NULL, leaf->contents); + if (!t->trace->startfound) + { + t->trace->startfound = true; + t->trace->startsupercontents |= side; + } + if (side & SUPERCONTENTS_LIQUIDSMASK) + t->trace->inwater = true; + if (side == 0) + t->trace->inopen = true; + if (side & t->trace->hitsupercontentsmask) + { + // if the first leaf is solid, set startsolid + if (t->trace->allsolid) + t->trace->startsolid = true; + return HULLCHECKSTATE_SOLID; + } + else + { + t->trace->allsolid = false; + return HULLCHECKSTATE_EMPTY; + } +} + +static void Mod_Q1BSP_TraceLineAgainstSurfaces(struct model_s *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, const vec3_t start, const vec3_t end, int hitsupercontentsmask) +{ + RecursiveHullCheckTraceInfo_t rhc; + + memset(&rhc, 0, sizeof(rhc)); + memset(trace, 0, sizeof(trace_t)); + rhc.trace = trace; + rhc.trace->hitsupercontentsmask = hitsupercontentsmask; + rhc.trace->fraction = 1; + rhc.trace->realfraction = 1; + rhc.trace->allsolid = true; + rhc.hull = &model->brushq1.hulls[0]; // 0x0x0 + VectorCopy(start, rhc.start); + VectorCopy(end, rhc.end); + VectorSubtract(rhc.end, rhc.start, rhc.dist); + Mod_Q1BSP_TraceLineAgainstSurfacesRecursiveBSPNode(&rhc, model, model->brush.data_nodes + rhc.hull->firstclipnode, rhc.start, rhc.end); + VectorMA(rhc.start, rhc.trace->fraction, rhc.dist, rhc.trace->endpos); +} + static void Mod_Q1BSP_DecompressVis(const unsigned char *in, const unsigned char *inend, unsigned char *out, unsigned char *outend) { int c; @@ -2339,8 +2527,8 @@ static void Mod_Q1BSP_LoadFaces(lump_t *l) } // compile additional data about the surface geometry - Mod_BuildNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, loadmodel->surfmesh.data_vertex3f, (loadmodel->surfmesh.data_element3i + 3 * surface->num_firsttriangle), loadmodel->surfmesh.data_normal3f, true); - Mod_BuildTextureVectorsFromNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_texcoordtexture2f, loadmodel->surfmesh.data_normal3f, (loadmodel->surfmesh.data_element3i + 3 * surface->num_firsttriangle), loadmodel->surfmesh.data_svector3f, loadmodel->surfmesh.data_tvector3f, true); + Mod_BuildNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, loadmodel->surfmesh.data_vertex3f, (loadmodel->surfmesh.data_element3i + 3 * surface->num_firsttriangle), loadmodel->surfmesh.data_normal3f, r_smoothnormals_areaweighting.integer != 0); + Mod_BuildTextureVectorsFromNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_texcoordtexture2f, loadmodel->surfmesh.data_normal3f, (loadmodel->surfmesh.data_element3i + 3 * surface->num_firsttriangle), loadmodel->surfmesh.data_svector3f, loadmodel->surfmesh.data_tvector3f, r_smoothnormals_areaweighting.integer != 0); BoxFromPoints(surface->mins, surface->maxs, surface->num_vertices, (loadmodel->surfmesh.data_vertex3f + 3 * surface->num_firstvertex)); // generate surface extents information @@ -2559,6 +2747,8 @@ static void Mod_Q1BSP_LoadNodes(lump_t *l) if (l->filelen % sizeof(*in)) Host_Error("Mod_Q1BSP_LoadNodes: funny lump size in %s",loadmodel->name); count = l->filelen / sizeof(*in); + if (count == 0) + Host_Error("Mod_Q1BSP_LoadNodes: missing BSP tree in %s",loadmodel->name); out = (mnode_t *)Mem_Alloc(loadmodel->mempool, count*sizeof(*out)); loadmodel->brush.data_nodes = out; @@ -3434,13 +3624,15 @@ static int Mod_Q1BSP_CreateShadowMesh(dp_model_t *mod) for (j = 0, surface = mod->data_surfaces;j < mod->num_surfaces;j++, surface++) if (surface->num_triangles > 0) Mod_ShadowMesh_AddMesh(mod->mempool, mod->brush.shadowmesh, NULL, NULL, NULL, mod->surfmesh.data_vertex3f, NULL, NULL, NULL, NULL, surface->num_triangles, (mod->surfmesh.data_element3i + 3 * surface->num_firsttriangle)); - mod->brush.shadowmesh = Mod_ShadowMesh_Finish(mod->mempool, mod->brush.shadowmesh, false, true, false); - if (mod->brush.shadowmesh) + mod->brush.shadowmesh = Mod_ShadowMesh_Finish(mod->mempool, mod->brush.shadowmesh, false, r_enableshadowvolumes.integer != 0, false); + if (mod->brush.shadowmesh && mod->brush.shadowmesh->neighbor3i) Mod_BuildTriangleNeighbors(mod->brush.shadowmesh->neighbor3i, mod->brush.shadowmesh->element3i, mod->brush.shadowmesh->numtriangles); return numshadowmeshtriangles; } +void Mod_CollisionBIH_TraceLineAgainstSurfaces(dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, const vec3_t start, const vec3_t end, int hitsupercontentsmask); + void Mod_Q1BSP_Load(dp_model_t *mod, void *buffer, void *bufferend) { int i, j, k; @@ -3498,9 +3690,10 @@ void Mod_Q1BSP_Load(dp_model_t *mod, void *buffer, void *bufferend) mod->soundfromcenter = true; mod->TraceBox = Mod_Q1BSP_TraceBox; - mod->TraceLine = Mod_Q1BSP_TraceLine; + mod->TraceLine = Mod_Q1BSP_TraceLineAgainstSurfaces; // LordHavoc: use the surface-hitting version of TraceLine in all cases mod->TracePoint = Mod_Q1BSP_TracePoint; mod->PointSuperContents = Mod_Q1BSP_PointSuperContents; + mod->TraceLineAgainstSurfaces = Mod_Q1BSP_TraceLineAgainstSurfaces; mod->brush.TraceLineOfSight = Mod_Q1BSP_TraceLineOfSight; mod->brush.SuperContentsFromNativeContents = Mod_Q1BSP_SuperContentsFromNativeContents; mod->brush.NativeContentsFromSuperContents = Mod_Q1BSP_NativeContentsFromSuperContents; @@ -3569,7 +3762,8 @@ void Mod_Q1BSP_Load(dp_model_t *mod, void *buffer, void *bufferend) mod->brushq1.num_compressedpvs = 0; Mod_Q1BSP_MakeHull0(); - Mod_Q1BSP_MakePortals(); + if (mod_bsp_portalize.integer) + Mod_Q1BSP_MakePortals(); mod->numframes = 2; // regular and alternate animation mod->numskins = 1; @@ -3751,16 +3945,18 @@ void Mod_Q1BSP_Load(dp_model_t *mod, void *buffer, void *bufferend) } //mod->brushq1.num_visleafs = bm->visleafs; + // build a Bounding Interval Hierarchy for culling triangles in light rendering + Mod_MakeCollisionBIH(mod, true, &mod->render_bih); + if (mod_q1bsp_polygoncollisions.integer) { - Mod_MakeCollisionBIH(mod, true, &mod->collision_bih); + mod->collision_bih = mod->render_bih; // point traces and contents checks still use the bsp tree mod->TraceLine = Mod_CollisionBIH_TraceLine; mod->TraceBox = Mod_CollisionBIH_TraceBox; mod->TraceBrush = Mod_CollisionBIH_TraceBrush; + mod->TraceLineAgainstSurfaces = Mod_CollisionBIH_TraceLineAgainstSurfaces; } - else - Mod_MakeCollisionBIH(mod, true, &mod->render_bih); // generate VBOs and other shared data before cloning submodels if (i == 0) @@ -5315,13 +5511,20 @@ static void Mod_Q3BSP_LoadFaces(lump_t *l) if(out->num_vertices && out->num_triangles) continue; if(out->num_vertices == 0) - Con_Printf("Mod_Q3BSP_LoadFaces: surface %d has no vertices, ignoring\n", i); - if(out->num_triangles == 0) - Con_Printf("Mod_Q3BSP_LoadFaces: surface %d has no triangles, ignoring\n", i); + { + Con_Printf("Mod_Q3BSP_LoadFaces: surface %d (texture %s) has no vertices, ignoring\n", i, out->texture ? out->texture->name : "(none)"); + if(out->num_triangles == 0) + Con_Printf("Mod_Q3BSP_LoadFaces: surface %d (texture %s) has no triangles, ignoring\n", i, out->texture ? out->texture->name : "(none)"); + } + else if(out->num_triangles == 0) + Con_Printf("Mod_Q3BSP_LoadFaces: surface %d (texture %s, near %f %f %f) has no triangles, ignoring\n", i, out->texture ? out->texture->name : "(none)", + (loadmodel->surfmesh.data_vertex3f + 3 * out->num_firstvertex)[0 * 3 + 0], + (loadmodel->surfmesh.data_vertex3f + 3 * out->num_firstvertex)[1 * 3 + 0], + (loadmodel->surfmesh.data_vertex3f + 3 * out->num_firstvertex)[2 * 3 + 0]); } // for per pixel lighting - Mod_BuildTextureVectorsFromNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_texcoordtexture2f, loadmodel->surfmesh.data_normal3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_svector3f, loadmodel->surfmesh.data_tvector3f, true); + Mod_BuildTextureVectorsFromNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_texcoordtexture2f, loadmodel->surfmesh.data_normal3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_svector3f, loadmodel->surfmesh.data_tvector3f, r_smoothnormals_areaweighting.integer != 0); // generate ushort elements array if possible if (loadmodel->surfmesh.data_element3s) @@ -5484,6 +5687,8 @@ static void Mod_Q3BSP_LoadNodes(lump_t *l) if (l->filelen % sizeof(*in)) Host_Error("Mod_Q3BSP_LoadNodes: funny lump size in %s",loadmodel->name); count = l->filelen / sizeof(*in); + if (count == 0) + Host_Error("Mod_Q3BSP_LoadNodes: missing BSP tree in %s",loadmodel->name); out = (mnode_t *)Mem_Alloc(loadmodel->mempool, count * sizeof(*out)); loadmodel->brush.data_nodes = out; @@ -5609,11 +5814,26 @@ static void Mod_Q3BSP_LoadPVS(lump_t *l) static void Mod_Q3BSP_LightPoint(dp_model_t *model, const vec3_t p, vec3_t ambientcolor, vec3_t diffusecolor, vec3_t diffusenormal) { int i, j, k, index[3]; - float transformed[3], blend1, blend2, blend, stylescale; + float transformed[3], blend1, blend2, blend, stylescale = 1; q3dlightgrid_t *a, *s; // scale lighting by lightstyle[0] so that darkmode in dpmod works properly - stylescale = r_refdef.scene.rtlightstylevalue[0]; + switch(vid.renderpath) + { + case RENDERPATH_GL20: + case RENDERPATH_D3D9: + case RENDERPATH_D3D10: + case RENDERPATH_D3D11: + case RENDERPATH_SOFT: + case RENDERPATH_GLES2: + // LordHavoc: FIXME: is this true? + stylescale = 1; // added while render + break; + case RENDERPATH_GL11: + case RENDERPATH_GL13: + stylescale = r_refdef.scene.rtlightstylevalue[0]; + break; + } if (!model->brushq3.num_lightgrid) { @@ -5755,9 +5975,38 @@ static void Mod_CollisionBIH_TracePoint_RecursiveBIHNode(trace_t *trace, dp_mode const bih_node_t *node; const colbrushf_t *brush; int axis; - while (nodenum >= 0) + for(;;) { node = model->collision_bih.nodes + nodenum; +#if 1 + if (!BoxesOverlap(point, point, node->mins, node->maxs)) + return; +#endif + if (node->type == BIH_UNORDERED) + { + for (axis = 0;axis < BIH_MAXUNORDEREDCHILDREN && node->children[axis] >= 0;axis++) + { + leaf = model->collision_bih.leafs + node->children[axis]; +#if 1 + if (!BoxesOverlap(point, point, leaf->mins, leaf->maxs)) + continue; +#endif + switch(leaf->type) + { + case BIH_BRUSH: + brush = model->brush.data_brushes[leaf->itemindex].colbrushf; + Collision_TracePointBrushFloat(trace, point, brush); + break; + case BIH_COLLISIONTRIANGLE: + // collision triangle - skipped because they have no volume + break; + case BIH_RENDERTRIANGLE: + // render triangle - skipped because they have no volume + break; + } + } + return; + } axis = node->type - BIH_SPLITX; if (point[axis] <= node->backmax) { @@ -5770,25 +6019,9 @@ static void Mod_CollisionBIH_TracePoint_RecursiveBIHNode(trace_t *trace, dp_mode else // no overlap with either child? just return return; } - if (!model->collision_bih.leafs) - return; - leaf = model->collision_bih.leafs + (-1-nodenum); - switch(leaf->type) - { - case BIH_BRUSH: - brush = model->brush.data_brushes[leaf->itemindex].colbrushf; - Collision_TracePointBrushFloat(trace, point, brush); - break; - case BIH_COLLISIONTRIANGLE: - // collision triangle - skipped because they have no volume - break; - case BIH_RENDERTRIANGLE: - // render triangle - skipped because they have no volume - break; - } } -static void Mod_CollisionBIH_TraceLine_RecursiveBIHNode(trace_t *trace, dp_model_t *model, int nodenum, const vec3_t start, const vec3_t end, const vec3_t linestart, const vec3_t lineend) +static void Mod_CollisionBIH_TraceLine_RecursiveBIHNode(trace_t *trace, dp_model_t *model, bih_t *bih, int nodenum, const vec3_t start, const vec3_t end, const vec3_t linestart, const vec3_t lineend) { const bih_leaf_t *leaf; const bih_node_t *node; @@ -5815,19 +6048,50 @@ static void Mod_CollisionBIH_TraceLine_RecursiveBIHNode(trace_t *trace, dp_model segmentmaxs[0] = max(start[0], end[0]); segmentmaxs[1] = max(start[1], end[1]); segmentmaxs[2] = max(start[2], end[2]); - while (nodenum >= 0) + for (;;) { - node = model->collision_bih.nodes + nodenum; -#if 0 + node = bih->nodes + nodenum; +#if 1 if (!BoxesOverlap(segmentmins, segmentmaxs, node->mins, node->maxs)) return; #endif + if (node->type == BIH_UNORDERED) + { + for (axis = 0;axis < BIH_MAXUNORDEREDCHILDREN && node->children[axis] >= 0;axis++) + { + leaf = model->collision_bih.leafs + node->children[axis]; +#if 1 + if (!BoxesOverlap(segmentmins, segmentmaxs, leaf->mins, leaf->maxs)) + continue; +#endif + switch(leaf->type) + { + case BIH_BRUSH: + brush = model->brush.data_brushes[leaf->itemindex].colbrushf; + Collision_TraceLineBrushFloat(trace, linestart, lineend, brush, brush); + break; + case BIH_COLLISIONTRIANGLE: + if (!mod_q3bsp_curves_collisions.integer) + continue; + e = model->brush.data_collisionelement3i + 3*leaf->itemindex; + texture = model->data_textures + leaf->textureindex; + Collision_TraceLineTriangleFloat(trace, linestart, lineend, model->brush.data_collisionvertex3f + e[0] * 3, model->brush.data_collisionvertex3f + e[1] * 3, model->brush.data_collisionvertex3f + e[2] * 3, texture->supercontents, texture->surfaceflags, texture); + break; + case BIH_RENDERTRIANGLE: + e = model->surfmesh.data_element3i + 3*leaf->itemindex; + texture = model->data_textures + leaf->textureindex; + Collision_TraceLineTriangleFloat(trace, linestart, lineend, model->surfmesh.data_vertex3f + e[0] * 3, model->surfmesh.data_vertex3f + e[1] * 3, model->surfmesh.data_vertex3f + e[2] * 3, texture->supercontents, texture->surfaceflags, texture); + break; + } + } + return; + } axis = node->type - BIH_SPLITX; #if 0 if (segmentmins[axis] <= node->backmax) { if (segmentmaxs[axis] >= node->frontmin) - Mod_CollisionBIH_TraceLine_RecursiveBIHNode(trace, model, node->front, start, end, linestart, lineend); + Mod_CollisionBIH_TraceLine_RecursiveBIHNode(trace, model, bih, node->front, start, end, linestart, lineend); nodenum = node->back; } else if (segmentmaxs[axis] >= node->frontmin) @@ -5852,7 +6116,7 @@ static void Mod_CollisionBIH_TraceLine_RecursiveBIHNode(trace_t *trace, dp_model if (sideflags & 12) { if ((sideflags & 3) != 3) - Mod_CollisionBIH_TraceLine_RecursiveBIHNode(trace, model, node->front, start, end, linestart, lineend); + Mod_CollisionBIH_TraceLine_RecursiveBIHNode(trace, model, bih, node->front, start, end, linestart, lineend); nodenum = node->back; } else if ((sideflags & 3) != 3) @@ -5899,7 +6163,7 @@ static void Mod_CollisionBIH_TraceLine_RecursiveBIHNode(trace_t *trace, dp_model return; // line falls in gap between children case 4: // start end start END - Mod_CollisionBIH_TraceLine_RecursiveBIHNode(trace, model, node->front, start, end, linestart, lineend); + Mod_CollisionBIH_TraceLine_RecursiveBIHNode(trace, model, bih, node->front, start, end, linestart, lineend); #ifdef BIHLINECLIP backfrac = backdist1 / (backdist1 - backdist2); VectorLerp(start, backfrac, end, newend); end = newend; @@ -5917,7 +6181,7 @@ static void Mod_CollisionBIH_TraceLine_RecursiveBIHNode(trace_t *trace, dp_model #ifdef BIHLINECLIP frontfrac = frontdist1 / (frontdist1 - frontdist2); VectorLerp(start, frontfrac, end, clipped); - Mod_CollisionBIH_TraceLine_RecursiveBIHNode(trace, model, node->front, clipped, end, linestart, lineend); + Mod_CollisionBIH_TraceLine_RecursiveBIHNode(trace, model, bih, node->front, clipped, end, linestart, lineend); backfrac = backdist1 / (backdist1 - backdist2); VectorLerp(start, backfrac, end, newend); end = newend; segmentmins[0] = min(start[0], end[0]); @@ -5927,7 +6191,7 @@ static void Mod_CollisionBIH_TraceLine_RecursiveBIHNode(trace_t *trace, dp_model segmentmaxs[1] = max(start[1], end[1]); segmentmaxs[2] = max(start[2], end[2]); #else - Mod_CollisionBIH_TraceLine_RecursiveBIHNode(trace, model, node->front, start, end, linestart, lineend); + Mod_CollisionBIH_TraceLine_RecursiveBIHNode(trace, model, bih, node->front, start, end, linestart, lineend); #endif nodenum = node->back; break; @@ -5936,7 +6200,7 @@ static void Mod_CollisionBIH_TraceLine_RecursiveBIHNode(trace_t *trace, dp_model #ifdef BIHLINECLIP frontfrac = frontdist1 / (frontdist1 - frontdist2); VectorLerp(start, frontfrac, end, clipped); - Mod_CollisionBIH_TraceLine_RecursiveBIHNode(trace, model, node->front, start, clipped, linestart, lineend); + Mod_CollisionBIH_TraceLine_RecursiveBIHNode(trace, model, bih, node->front, start, clipped, linestart, lineend); backfrac = backdist1 / (backdist1 - backdist2); VectorLerp(start, backfrac, end, newend); end = newend; segmentmins[0] = min(start[0], end[0]); @@ -5946,7 +6210,7 @@ static void Mod_CollisionBIH_TraceLine_RecursiveBIHNode(trace_t *trace, dp_model segmentmaxs[1] = max(start[1], end[1]); segmentmaxs[2] = max(start[2], end[2]); #else - Mod_CollisionBIH_TraceLine_RecursiveBIHNode(trace, model, node->front, start, end, linestart, lineend); + Mod_CollisionBIH_TraceLine_RecursiveBIHNode(trace, model, bih, node->front, start, end, linestart, lineend); #endif nodenum = node->back; break; @@ -5966,7 +6230,7 @@ static void Mod_CollisionBIH_TraceLine_RecursiveBIHNode(trace_t *trace, dp_model break; case 8: // start end START end - Mod_CollisionBIH_TraceLine_RecursiveBIHNode(trace, model, node->front, start, end, linestart, lineend); + Mod_CollisionBIH_TraceLine_RecursiveBIHNode(trace, model, bih, node->front, start, end, linestart, lineend); #ifdef BIHLINECLIP backfrac = backdist1 / (backdist1 - backdist2); VectorLerp(start, backfrac, end, newstart); start = newstart; @@ -5984,7 +6248,7 @@ static void Mod_CollisionBIH_TraceLine_RecursiveBIHNode(trace_t *trace, dp_model #ifdef BIHLINECLIP frontfrac = frontdist1 / (frontdist1 - frontdist2); VectorLerp(start, frontfrac, end, clipped); - Mod_CollisionBIH_TraceLine_RecursiveBIHNode(trace, model, node->front, clipped, end, linestart, lineend); + Mod_CollisionBIH_TraceLine_RecursiveBIHNode(trace, model, bih, node->front, clipped, end, linestart, lineend); backfrac = backdist1 / (backdist1 - backdist2); VectorLerp(start, backfrac, end, newstart); start = newstart; segmentmins[0] = min(start[0], end[0]); @@ -5994,7 +6258,7 @@ static void Mod_CollisionBIH_TraceLine_RecursiveBIHNode(trace_t *trace, dp_model segmentmaxs[1] = max(start[1], end[1]); segmentmaxs[2] = max(start[2], end[2]); #else - Mod_CollisionBIH_TraceLine_RecursiveBIHNode(trace, model, node->front, start, end, linestart, lineend); + Mod_CollisionBIH_TraceLine_RecursiveBIHNode(trace, model, bih, node->front, start, end, linestart, lineend); #endif nodenum = node->back; break; @@ -6003,7 +6267,7 @@ static void Mod_CollisionBIH_TraceLine_RecursiveBIHNode(trace_t *trace, dp_model #ifdef BIHLINECLIP frontfrac = frontdist1 / (frontdist1 - frontdist2); VectorLerp(start, frontfrac, end, clipped); - Mod_CollisionBIH_TraceLine_RecursiveBIHNode(trace, model, node->front, start, clipped, linestart, lineend); + Mod_CollisionBIH_TraceLine_RecursiveBIHNode(trace, model, bih, node->front, start, clipped, linestart, lineend); backfrac = backdist1 / (backdist1 - backdist2); VectorLerp(start, backfrac, end, newstart); start = newstart; segmentmins[0] = min(start[0], end[0]); @@ -6013,7 +6277,7 @@ static void Mod_CollisionBIH_TraceLine_RecursiveBIHNode(trace_t *trace, dp_model segmentmaxs[1] = max(start[1], end[1]); segmentmaxs[2] = max(start[2], end[2]); #else - Mod_CollisionBIH_TraceLine_RecursiveBIHNode(trace, model, node->front, start, end, linestart, lineend); + Mod_CollisionBIH_TraceLine_RecursiveBIHNode(trace, model, bih, node->front, start, end, linestart, lineend); #endif nodenum = node->back; break; @@ -6033,7 +6297,7 @@ static void Mod_CollisionBIH_TraceLine_RecursiveBIHNode(trace_t *trace, dp_model break; case 12: // start end start end - Mod_CollisionBIH_TraceLine_RecursiveBIHNode(trace, model, node->front, start, end, linestart, lineend); + Mod_CollisionBIH_TraceLine_RecursiveBIHNode(trace, model, bih, node->front, start, end, linestart, lineend); nodenum = node->back; break; case 13: @@ -6041,9 +6305,9 @@ static void Mod_CollisionBIH_TraceLine_RecursiveBIHNode(trace_t *trace, dp_model #ifdef BIHLINECLIP frontfrac = frontdist1 / (frontdist1 - frontdist2); VectorLerp(start, frontfrac, end, clipped); - Mod_CollisionBIH_TraceLine_RecursiveBIHNode(trace, model, node->front, clipped, end, linestart, lineend); + Mod_CollisionBIH_TraceLine_RecursiveBIHNode(trace, model, bih, node->front, clipped, end, linestart, lineend); #else - Mod_CollisionBIH_TraceLine_RecursiveBIHNode(trace, model, node->front, start, end, linestart, lineend); + Mod_CollisionBIH_TraceLine_RecursiveBIHNode(trace, model, bih, node->front, start, end, linestart, lineend); #endif nodenum = node->back; break; @@ -6052,9 +6316,9 @@ static void Mod_CollisionBIH_TraceLine_RecursiveBIHNode(trace_t *trace, dp_model #ifdef BIHLINECLIP frontfrac = frontdist1 / (frontdist1 - frontdist2); VectorLerp(start, frontfrac, end, clipped); - Mod_CollisionBIH_TraceLine_RecursiveBIHNode(trace, model, node->front, start, clipped, linestart, lineend); + Mod_CollisionBIH_TraceLine_RecursiveBIHNode(trace, model, bih, node->front, start, clipped, linestart, lineend); #else - Mod_CollisionBIH_TraceLine_RecursiveBIHNode(trace, model, node->front, start, end, linestart, lineend); + Mod_CollisionBIH_TraceLine_RecursiveBIHNode(trace, model, bih, node->front, start, end, linestart, lineend); #endif nodenum = node->back; break; @@ -6066,32 +6330,6 @@ static void Mod_CollisionBIH_TraceLine_RecursiveBIHNode(trace_t *trace, dp_model #endif #endif } - if (!model->collision_bih.leafs) - return; - leaf = model->collision_bih.leafs + (-1-nodenum); -#if 1 - if (!BoxesOverlap(segmentmins, segmentmaxs, leaf->mins, leaf->maxs)) - return; -#endif - switch(leaf->type) - { - case BIH_BRUSH: - brush = model->brush.data_brushes[leaf->itemindex].colbrushf; - Collision_TraceLineBrushFloat(trace, linestart, lineend, brush, brush); - break; - case BIH_COLLISIONTRIANGLE: - if (!mod_q3bsp_curves_collisions.integer) - return; - e = model->brush.data_collisionelement3i + 3*leaf->itemindex; - texture = model->data_textures + leaf->textureindex; - Collision_TraceLineTriangleFloat(trace, linestart, lineend, model->brush.data_collisionvertex3f + e[0] * 3, model->brush.data_collisionvertex3f + e[1] * 3, model->brush.data_collisionvertex3f + e[2] * 3, texture->supercontents, texture->surfaceflags, texture); - break; - case BIH_RENDERTRIANGLE: - e = model->surfmesh.data_element3i + 3*leaf->itemindex; - texture = model->data_textures + leaf->textureindex; - Collision_TraceLineTriangleFloat(trace, linestart, lineend, model->surfmesh.data_vertex3f + e[0] * 3, model->surfmesh.data_vertex3f + e[1] * 3, model->surfmesh.data_vertex3f + e[2] * 3, texture->supercontents, texture->surfaceflags, texture); - break; - } } static void Mod_CollisionBIH_TraceBrush_RecursiveBIHNode(trace_t *trace, dp_model_t *model, int nodenum, const colbrushf_t *thisbrush_start, const colbrushf_t *thisbrush_end, const vec3_t segmentmins, const vec3_t segmentmaxs) @@ -6102,9 +6340,40 @@ static void Mod_CollisionBIH_TraceBrush_RecursiveBIHNode(trace_t *trace, dp_mode const int *e; const texture_t *texture; int axis; - while (nodenum >= 0) + for(;;) { node = model->collision_bih.nodes + nodenum; + if (node->type == BIH_UNORDERED) + { + for (axis = 0;axis < BIH_MAXUNORDEREDCHILDREN && node->children[axis] >= 0;axis++) + { + leaf = model->collision_bih.leafs + node->children[axis]; +#if 1 + if (!BoxesOverlap(segmentmins, segmentmaxs, leaf->mins, leaf->maxs)) + continue; +#endif + switch(leaf->type) + { + case BIH_BRUSH: + brush = model->brush.data_brushes[leaf->itemindex].colbrushf; + Collision_TraceBrushBrushFloat(trace, thisbrush_start, thisbrush_end, brush, brush); + break; + case BIH_COLLISIONTRIANGLE: + if (!mod_q3bsp_curves_collisions.integer) + continue; + e = model->brush.data_collisionelement3i + 3*leaf->itemindex; + texture = model->data_textures + leaf->textureindex; + Collision_TraceBrushTriangleFloat(trace, thisbrush_start, thisbrush_end, model->brush.data_collisionvertex3f + e[0] * 3, model->brush.data_collisionvertex3f + e[1] * 3, model->brush.data_collisionvertex3f + e[2] * 3, texture->supercontents, texture->surfaceflags, texture); + break; + case BIH_RENDERTRIANGLE: + e = model->surfmesh.data_element3i + 3*leaf->itemindex; + texture = model->data_textures + leaf->textureindex; + Collision_TraceBrushTriangleFloat(trace, thisbrush_start, thisbrush_end, model->surfmesh.data_vertex3f + e[0] * 3, model->surfmesh.data_vertex3f + e[1] * 3, model->surfmesh.data_vertex3f + e[2] * 3, texture->supercontents, texture->surfaceflags, texture); + break; + } + } + return; + } axis = node->type - BIH_SPLITX; #if 1 if (!BoxesOverlap(segmentmins, segmentmaxs, node->mins, node->maxs)) @@ -6126,32 +6395,6 @@ static void Mod_CollisionBIH_TraceBrush_RecursiveBIHNode(trace_t *trace, dp_mode else return; // trace falls between children } - if (!model->collision_bih.leafs) - return; - leaf = model->collision_bih.leafs + (-1-nodenum); -#if 1 - if (!BoxesOverlap(segmentmins, segmentmaxs, leaf->mins, leaf->maxs)) - return; -#endif - switch(leaf->type) - { - case BIH_BRUSH: - brush = model->brush.data_brushes[leaf->itemindex].colbrushf; - Collision_TraceBrushBrushFloat(trace, thisbrush_start, thisbrush_end, brush, brush); - break; - case BIH_COLLISIONTRIANGLE: - if (!mod_q3bsp_curves_collisions.integer) - return; - e = model->brush.data_collisionelement3i + 3*leaf->itemindex; - texture = model->data_textures + leaf->textureindex; - Collision_TraceBrushTriangleFloat(trace, thisbrush_start, thisbrush_end, model->brush.data_collisionvertex3f + e[0] * 3, model->brush.data_collisionvertex3f + e[1] * 3, model->brush.data_collisionvertex3f + e[2] * 3, texture->supercontents, texture->surfaceflags, texture); - break; - case BIH_RENDERTRIANGLE: - e = model->surfmesh.data_element3i + 3*leaf->itemindex; - texture = model->data_textures + leaf->textureindex; - Collision_TraceBrushTriangleFloat(trace, thisbrush_start, thisbrush_end, model->surfmesh.data_vertex3f + e[0] * 3, model->surfmesh.data_vertex3f + e[1] * 3, model->surfmesh.data_vertex3f + e[2] * 3, texture->supercontents, texture->surfaceflags, texture); - break; - } } void Mod_CollisionBIH_TracePoint(dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, const vec3_t start, int hitsupercontentsmask) @@ -6175,7 +6418,7 @@ void Mod_CollisionBIH_TraceLine(dp_model_t *model, const frameblend_t *frameblen trace->fraction = 1; trace->realfraction = 1; trace->hitsupercontentsmask = hitsupercontentsmask; - Mod_CollisionBIH_TraceLine_RecursiveBIHNode(trace, model, model->collision_bih.rootnode, start, end, start, end); + Mod_CollisionBIH_TraceLine_RecursiveBIHNode(trace, model, &model->collision_bih, model->collision_bih.rootnode, start, end, start, end); } void Mod_CollisionBIH_TraceBox(dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, const vec3_t start, const vec3_t boxmins, const vec3_t boxmaxs, const vec3_t end, int hitsupercontentsmask) @@ -6550,7 +6793,7 @@ static void Mod_Q3BSP_TraceLine(dp_model_t *model, const frameblend_t *frameblen segmentmaxs[1] = max(start[1], end[1]) + 1; segmentmaxs[2] = max(start[2], end[2]) + 1; if (mod_collision_bih.integer) - Mod_CollisionBIH_TraceLine_RecursiveBIHNode(trace, model, model->collision_bih.rootnode, start, end, start, end); + Mod_CollisionBIH_TraceLine_RecursiveBIHNode(trace, model, &model->collision_bih, model->collision_bih.rootnode, start, end, start, end); else if (model->brush.submodel) { for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++) @@ -6700,6 +6943,16 @@ static int Mod_Q3BSP_PointSuperContents(struct model_s *model, int frame, const return supercontents; } +void Mod_CollisionBIH_TraceLineAgainstSurfaces(dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, const vec3_t start, const vec3_t end, int hitsupercontentsmask) +{ + memset(trace, 0, sizeof(*trace)); + trace->fraction = 1; + trace->realfraction = 1; + trace->hitsupercontentsmask = hitsupercontentsmask; + Mod_CollisionBIH_TraceLine_RecursiveBIHNode(trace, model, &model->render_bih, model->render_bih.rootnode, start, end, start, end); +} + + bih_t *Mod_MakeCollisionBIH(dp_model_t *model, qboolean userendersurfaces, bih_t *out) { int j; @@ -6814,7 +7067,7 @@ bih_t *Mod_MakeCollisionBIH(dp_model_t *model, qboolean userendersurfaces, bih_t } // allocate buffers for the produced and temporary data - bihmaxnodes = bihnumleafs - 1; + bihmaxnodes = bihnumleafs + 1; bihnodes = (bih_node_t *)Mem_Alloc(loadmodel->mempool, sizeof(bih_node_t) * bihmaxnodes); temp_leafsort = (int *)Mem_Alloc(loadmodel->mempool, sizeof(int) * bihnumleafs * 2); temp_leafsortscratch = temp_leafsort + bihnumleafs; @@ -6934,6 +7187,7 @@ void Mod_Q3BSP_Load(dp_model_t *mod, void *buffer, void *bufferend) mod->TraceLine = Mod_Q3BSP_TraceLine; mod->TracePoint = Mod_Q3BSP_TracePoint; mod->PointSuperContents = Mod_Q3BSP_PointSuperContents; + mod->TraceLineAgainstSurfaces = Mod_CollisionBIH_TraceLine; mod->brush.TraceLineOfSight = Mod_Q3BSP_TraceLineOfSight; mod->brush.SuperContentsFromNativeContents = Mod_Q3BSP_SuperContentsFromNativeContents; mod->brush.NativeContentsFromSuperContents = Mod_Q3BSP_NativeContentsFromSuperContents; @@ -7025,7 +7279,8 @@ void Mod_Q3BSP_Load(dp_model_t *mod, void *buffer, void *bufferend) loadmodel->brush.numsubmodels = loadmodel->brushq3.num_models; // the MakePortals code works fine on the q3bsp data as well - Mod_Q1BSP_MakePortals(); + if (mod_bsp_portalize.integer) + Mod_Q1BSP_MakePortals(); // FIXME: shader alpha should replace r_wateralpha support in q3bsp loadmodel->brush.supportwateralpha = true; @@ -7231,6 +7486,7 @@ void Mod_OBJ_Load(dp_model_t *mod, void *buffer, void *bufferend) loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush; loadmodel->TraceLine = Mod_CollisionBIH_TraceLine; loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh; + loadmodel->TraceLineAgainstSurfaces = Mod_CollisionBIH_TraceLine; loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh; loadmodel->brush.TraceLineOfSight = NULL; loadmodel->brush.SuperContentsFromNativeContents = NULL; @@ -7560,13 +7816,14 @@ void Mod_OBJ_Load(dp_model_t *mod, void *buffer, void *bufferend) // allocate storage for final mesh data loadmodel->num_textures = numtextures * loadmodel->numskins; loadmodel->num_texturesperskin = numtextures; - data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(int) + loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t) + numtriangles * sizeof(int[3]) + (numvertices <= 65536 ? numtriangles * sizeof(unsigned short[3]) : 0) + numvertices * sizeof(float[14]) + loadmodel->brush.numsubmodels * sizeof(dp_model_t *)); + data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(int) + loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t) + numtriangles * sizeof(int[3]) + (numvertices <= 65536 ? numtriangles * sizeof(unsigned short[3]) : 0) + (r_enableshadowvolumes.integer ? numtriangles * sizeof(int[3]) : 0) + numvertices * sizeof(float[14]) + loadmodel->brush.numsubmodels * sizeof(dp_model_t *)); loadmodel->brush.submodels = (dp_model_t **)data;data += loadmodel->brush.numsubmodels * sizeof(dp_model_t *); loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int); loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t); loadmodel->surfmesh.num_vertices = numvertices; loadmodel->surfmesh.num_triangles = numtriangles; - loadmodel->surfmesh.data_neighbor3i = (int *)data;data += numtriangles * sizeof(int[3]); + if (r_enableshadowvolumes.integer) + loadmodel->surfmesh.data_neighbor3i = (int *)data;data += numtriangles * sizeof(int[3]); loadmodel->surfmesh.data_vertex3f = (float *)data;data += numvertices * sizeof(float[3]); loadmodel->surfmesh.data_svector3f = (float *)data;data += numvertices * sizeof(float[3]); loadmodel->surfmesh.data_tvector3f = (float *)data;data += numvertices * sizeof(float[3]); @@ -7610,9 +7867,10 @@ void Mod_OBJ_Load(dp_model_t *mod, void *buffer, void *bufferend) Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__); // generate normals if the file did not have them if (!VectorLength2(loadmodel->surfmesh.data_normal3f)) - Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, true); - Mod_BuildTextureVectorsFromNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_texcoordtexture2f, loadmodel->surfmesh.data_normal3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_svector3f, loadmodel->surfmesh.data_tvector3f, true); - Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles); + Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, r_smoothnormals_areaweighting.integer != 0); + Mod_BuildTextureVectorsFromNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_texcoordtexture2f, loadmodel->surfmesh.data_normal3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_svector3f, loadmodel->surfmesh.data_tvector3f, r_smoothnormals_areaweighting.integer != 0); + if (loadmodel->surfmesh.data_neighbor3i) + Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles); // if this is a worldmodel and has no BSP tree, create a fake one for the purpose loadmodel->brush.num_visleafs = 1; @@ -8219,6 +8477,7 @@ void Mod_OBJ_Load(dp_model_t *mod, void *buffer, void *bufferend) loadmodel->TraceLine = Mod_OBJ_TraceLine; loadmodel->TracePoint = Mod_OBJ_TracePoint; loadmodel->PointSuperContents = Mod_OBJ_PointSuperContents; + loadmodel->TraceLineAgainstSurfaces = Mod_OBJ_TraceLineAgainstSurfaces; loadmodel->brush.TraceLineOfSight = Mod_OBJ_TraceLineOfSight; loadmodel->brush.SuperContentsFromNativeContents = Mod_OBJ_SuperContentsFromNativeContents; loadmodel->brush.NativeContentsFromSuperContents = Mod_OBJ_NativeContentsFromSuperContents; @@ -8512,14 +8771,15 @@ void Mod_OBJ_Load(dp_model_t *mod, void *buffer, void *bufferend) loadmodel->num_surfaces = 1; loadmodel->nummodelsurfaces = loadmodel->num_surfaces; - data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->numframes * sizeof(animscene_t) + loadmodel->numframes * sizeof(float[6]) + loadmodel->surfmesh.num_triangles * sizeof(int[3]) + loadmodel->surfmesh.num_triangles * sizeof(int[3])); + data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->numframes * sizeof(animscene_t) + loadmodel->numframes * sizeof(float[6]) + loadmodel->surfmesh.num_triangles * sizeof(int[3]) + (r_enableshadowvolume.integer ? loadmodel->surfmesh.num_triangles * sizeof(int[3]) : 0)); loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t); loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int); loadmodel->sortedmodelsurfaces[0] = 0; loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t); loadmodel->surfmesh.data_morphmd2framesize6f = (float *)data;data += loadmodel->numframes * sizeof(float[6]); loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]); - loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]); + if (r_enableshadowvolumes.integer) + loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]); loadmodel->synctype = ST_RAND; @@ -8661,7 +8921,8 @@ void Mod_OBJ_Load(dp_model_t *mod, void *buffer, void *bufferend) Mem_Free(vertremap); Mod_MakeSortedSurfaces(loadmodel); - Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles); + if (loadmodel->surfmesh.data_neighbor3i) + Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles); Mod_Alias_CalculateBoundingBox(); Mod_Alias_MorphMesh_CompileFrames();