From 09f884dd87cbb5b3da9e261d8c0841cdb9365c5b Mon Sep 17 00:00:00 2001 From: divverent Date: Tue, 29 Jun 2010 06:34:05 +0000 Subject: [PATCH] speed up decal creation in newdecalsystem by using BIH for finding the affected triangles git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@10254 d7cf8633-e32d-0410-b094-e92efae38249 --- bih.c | 16 ++-- bih.h | 2 +- gl_rmain.c | 206 ++++++++++++++++++++++++++++++------------------- model_alias.c | 14 ++-- model_brush.c | 26 ++++--- model_shared.h | 3 +- 6 files changed, 162 insertions(+), 105 deletions(-) diff --git a/bih.c b/bih.c index 58cc0715..d5044bff 100644 --- a/bih.c +++ b/bih.c @@ -142,7 +142,7 @@ int BIH_Build(bih_t *bih, int numleafs, bih_leaf_t *leafs, int maxnodes, bih_nod return bih->error; } -static void BIH_GetTriangleListForBox_Node(const bih_t *bih, int nodenum, int maxtriangles, int *trianglelist, int *numtrianglespointer, const float *mins, const float *maxs) +static void BIH_GetTriangleListForBox_Node(const bih_t *bih, int nodenum, int maxtriangles, int *trianglelist_idx, int *trianglelist_surf, int *numtrianglespointer, const float *mins, const float *maxs) { int axis; bih_node_t *node; @@ -154,7 +154,7 @@ static void BIH_GetTriangleListForBox_Node(const bih_t *bih, int nodenum, int ma if (mins[axis] < node->backmax) { if (maxs[axis] > node->frontmin) - BIH_GetTriangleListForBox_Node(bih, node->front, maxtriangles, trianglelist, numtrianglespointer, mins, maxs); + BIH_GetTriangleListForBox_Node(bih, node->front, maxtriangles, trianglelist_idx, trianglelist_surf, numtrianglespointer, mins, maxs); nodenum = node->back; continue; } @@ -175,17 +175,23 @@ static void BIH_GetTriangleListForBox_Node(const bih_t *bih, int nodenum, int ma { case BIH_RENDERTRIANGLE: if (*numtrianglespointer >= maxtriangles) + { + ++*numtrianglespointer; // so the caller can detect overflow return; - trianglelist[(*numtrianglespointer)++] = leaf->itemindex; + } + if(trianglelist_surf) + trianglelist_surf[*numtrianglespointer] = leaf->surfaceindex; + trianglelist_idx[*numtrianglespointer] = leaf->itemindex; + ++*numtrianglespointer; break; default: break; } } -int BIH_GetTriangleListForBox(const bih_t *bih, int maxtriangles, int *trianglelist, const float *mins, const float *maxs) +int BIH_GetTriangleListForBox(const bih_t *bih, int maxtriangles, int *trianglelist_idx, int *trianglelist_surf, const float *mins, const float *maxs) { int numtriangles = 0; - BIH_GetTriangleListForBox_Node(bih, 0, maxtriangles, trianglelist, &numtriangles, mins, maxs); + BIH_GetTriangleListForBox_Node(bih, 0, maxtriangles, trianglelist_idx, trianglelist_surf, &numtriangles, mins, maxs); return numtriangles; } diff --git a/bih.h b/bih.h index 8b796669..90ec71db 100644 --- a/bih.h +++ b/bih.h @@ -81,6 +81,6 @@ bih_t; int BIH_Build(bih_t *bih, int numleafs, bih_leaf_t *leafs, int maxnodes, bih_node_t *nodes, int *temp_leafsort, int *temp_leafsortscratch); -int BIH_GetTriangleListForBox(const bih_t *bih, int maxtriangles, int *trianglelist, const float *mins, const float *maxs); +int BIH_GetTriangleListForBox(const bih_t *bih, int maxtriangles, int *trianglelist_idx, int *trianglelist_surf, const float *mins, const float *maxs); #endif diff --git a/gl_rmain.c b/gl_rmain.c index 4071854a..0234fdfb 100644 --- a/gl_rmain.c +++ b/gl_rmain.c @@ -12226,13 +12226,92 @@ static void R_DecalSystem_SpawnTriangle(decalsystem_t *decalsystem, const float extern cvar_t cl_decals_bias; extern cvar_t cl_decals_models; extern cvar_t cl_decals_newsystem_intensitymultiplier; +// baseparms, parms, temps +static void R_DecalSystem_SplatTriangle(decalsystem_t *decalsystem, float r, float g, float b, float a, float s1, float t1, float s2, float t2, int decalsequence, qboolean dynamic, float (*planes)[4], matrix4x4_t *projection, int triangleindex, int surfaceindex) +{ + int cornerindex; + int index; + float v[9][3]; + const float *vertex3f; + int numpoints; + float points[2][9][3]; + float temp[3]; + float tc[9][2]; + float f; + float c[9][4]; + const int *e; + + e = rsurface.modelelement3i + 3*triangleindex; + + vertex3f = rsurface.modelvertex3f; + + for (cornerindex = 0;cornerindex < 3;cornerindex++) + { + index = 3*e[cornerindex]; + VectorCopy(vertex3f + index, v[cornerindex]); + } + // cull backfaces + //TriangleNormal(v[0], v[1], v[2], normal); + //if (DotProduct(normal, localnormal) < 0.0f) + // continue; + // clip by each of the box planes formed from the projection matrix + // if anything survives, we emit the decal + numpoints = PolygonF_Clip(3 , v[0] , planes[0][0], planes[0][1], planes[0][2], planes[0][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), points[1][0]); + if (numpoints < 3) + return; + numpoints = PolygonF_Clip(numpoints, points[1][0], planes[1][0], planes[1][1], planes[1][2], planes[1][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), points[0][0]); + if (numpoints < 3) + return; + numpoints = PolygonF_Clip(numpoints, points[0][0], planes[2][0], planes[2][1], planes[2][2], planes[2][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), points[1][0]); + if (numpoints < 3) + return; + numpoints = PolygonF_Clip(numpoints, points[1][0], planes[3][0], planes[3][1], planes[3][2], planes[3][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), points[0][0]); + if (numpoints < 3) + return; + numpoints = PolygonF_Clip(numpoints, points[0][0], planes[4][0], planes[4][1], planes[4][2], planes[4][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), points[1][0]); + if (numpoints < 3) + return; + numpoints = PolygonF_Clip(numpoints, points[1][0], planes[5][0], planes[5][1], planes[5][2], planes[5][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), v[0]); + if (numpoints < 3) + return; + // some part of the triangle survived, so we have to accept it... + if (dynamic) + { + // dynamic always uses the original triangle + numpoints = 3; + for (cornerindex = 0;cornerindex < 3;cornerindex++) + { + index = 3*e[cornerindex]; + VectorCopy(vertex3f + index, v[cornerindex]); + } + } + for (cornerindex = 0;cornerindex < numpoints;cornerindex++) + { + // convert vertex positions to texcoords + Matrix4x4_Transform(projection, v[cornerindex], temp); + tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1; + tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1; + // calculate distance fade from the projection origin + f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value; + f = bound(0.0f, f, 1.0f); + c[cornerindex][0] = r * f; + c[cornerindex][1] = g * f; + c[cornerindex][2] = b * f; + c[cornerindex][3] = 1.0f; + //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]); + } + if (dynamic) + R_DecalSystem_SpawnTriangle(decalsystem, v[0], v[1], v[2], tc[0], tc[1], tc[2], c[0], c[1], c[2], triangleindex, surfaceindex, decalsequence); + else + for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++) + R_DecalSystem_SpawnTriangle(decalsystem, v[0], v[cornerindex+1], v[cornerindex+2], tc[0], tc[cornerindex+1], tc[cornerindex+2], c[0], c[cornerindex+1], c[cornerindex+2], -1, surfaceindex, decalsequence); +} static void R_DecalSystem_SplatEntity(entity_render_t *ent, const vec3_t worldorigin, const vec3_t worldnormal, float r, float g, float b, float a, float s1, float t1, float s2, float t2, float worldsize, int decalsequence) { matrix4x4_t projection; decalsystem_t *decalsystem; qboolean dynamic; dp_model_t *model; - const float *vertex3f; const msurface_t *surface; const msurface_t *surfaces; const int *surfacelist; @@ -12242,24 +12321,18 @@ static void R_DecalSystem_SplatEntity(entity_render_t *ent, const vec3_t worldor int surfacelistindex; int surfaceindex; int triangleindex; - int cornerindex; - int index; - int numpoints; - const int *e; float localorigin[3]; float localnormal[3]; float localmins[3]; float localmaxs[3]; float localsize; - float v[9][3]; - float tc[9][2]; - float c[9][4]; //float normal[3]; float planes[6][4]; - float f; - float points[2][9][3]; float angles[3]; - float temp[3]; + bih_t *bih; + int bih_triangles_count; + int bih_triangles[256]; + int bih_surfaces[256]; decalsystem = &ent->decalsystem; model = ent->model; @@ -12338,86 +12411,57 @@ static void R_DecalSystem_SplatEntity(entity_render_t *ent, const vec3_t worldor #endif dynamic = model->surfmesh.isanimated; - vertex3f = rsurface.modelvertex3f; numsurfacelist = model->nummodelsurfaces; surfacelist = model->sortedmodelsurfaces; surfaces = model->data_surfaces; - for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++) + + bih = NULL; + bih_triangles_count = -1; + if(!dynamic) { - surfaceindex = surfacelist[surfacelistindex]; - surface = surfaces + surfaceindex; - // check cull box first because it rejects more than any other check - if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs)) - continue; - // skip transparent surfaces - texture = surface->texture; - if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION)) - continue; - if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS) - continue; - numtriangles = surface->num_triangles; - for (triangleindex = 0, e = rsurface.modelelement3i + 3*surface->num_firsttriangle;triangleindex < numtriangles;triangleindex++, e += 3) + if(model->render_bih.numleafs) + bih = &model->render_bih; + else if(model->collision_bih.numleafs) + bih = &model->collision_bih; + } + if(bih) + bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs); + if(bih_triangles_count == 0) + return; + if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway + return; + if(bih_triangles_count > 0) + { + for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex) { - for (cornerindex = 0;cornerindex < 3;cornerindex++) - { - index = 3*e[cornerindex]; - VectorCopy(vertex3f + index, v[cornerindex]); - } - // cull backfaces - //TriangleNormal(v[0], v[1], v[2], normal); - //if (DotProduct(normal, localnormal) < 0.0f) - // continue; - // clip by each of the box planes formed from the projection matrix - // if anything survives, we emit the decal - numpoints = PolygonF_Clip(3 , v[0] , planes[0][0], planes[0][1], planes[0][2], planes[0][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), points[1][0]); - if (numpoints < 3) - continue; - numpoints = PolygonF_Clip(numpoints, points[1][0], planes[1][0], planes[1][1], planes[1][2], planes[1][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), points[0][0]); - if (numpoints < 3) + surfaceindex = bih_surfaces[triangleindex]; + surface = surfaces + surfaceindex; + texture = surface->texture; + if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION)) continue; - numpoints = PolygonF_Clip(numpoints, points[0][0], planes[2][0], planes[2][1], planes[2][2], planes[2][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), points[1][0]); - if (numpoints < 3) + if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS) continue; - numpoints = PolygonF_Clip(numpoints, points[1][0], planes[3][0], planes[3][1], planes[3][2], planes[3][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), points[0][0]); - if (numpoints < 3) + R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex); + } + } + else + { + for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++) + { + surfaceindex = surfacelist[surfacelistindex]; + surface = surfaces + surfaceindex; + // check cull box first because it rejects more than any other check + if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs)) continue; - numpoints = PolygonF_Clip(numpoints, points[0][0], planes[4][0], planes[4][1], planes[4][2], planes[4][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), points[1][0]); - if (numpoints < 3) + // skip transparent surfaces + texture = surface->texture; + if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION)) continue; - numpoints = PolygonF_Clip(numpoints, points[1][0], planes[5][0], planes[5][1], planes[5][2], planes[5][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), v[0]); - if (numpoints < 3) + if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS) continue; - // some part of the triangle survived, so we have to accept it... - if (dynamic) - { - // dynamic always uses the original triangle - numpoints = 3; - for (cornerindex = 0;cornerindex < 3;cornerindex++) - { - index = 3*e[cornerindex]; - VectorCopy(vertex3f + index, v[cornerindex]); - } - } - for (cornerindex = 0;cornerindex < numpoints;cornerindex++) - { - // convert vertex positions to texcoords - Matrix4x4_Transform(&projection, v[cornerindex], temp); - tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1; - tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1; - // calculate distance fade from the projection origin - f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value; - f = bound(0.0f, f, 1.0f); - c[cornerindex][0] = r * f; - c[cornerindex][1] = g * f; - c[cornerindex][2] = b * f; - c[cornerindex][3] = 1.0f; - //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]); - } - if (dynamic) - R_DecalSystem_SpawnTriangle(decalsystem, v[0], v[1], v[2], tc[0], tc[1], tc[2], c[0], c[1], c[2], triangleindex+surface->num_firsttriangle, surfaceindex, decalsequence); - else - for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++) - R_DecalSystem_SpawnTriangle(decalsystem, v[0], v[cornerindex+1], v[cornerindex+2], tc[0], tc[cornerindex+1], tc[cornerindex+2], c[0], c[cornerindex+1], c[cornerindex+2], -1, surfaceindex, decalsequence); + numtriangles = surface->num_triangles; + for (triangleindex = 0; triangleindex < numtriangles; triangleindex++) + R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex); } } } diff --git a/model_alias.c b/model_alias.c index df49c9e6..9cf5e50c 100644 --- a/model_alias.c +++ b/model_alias.c @@ -1323,7 +1323,7 @@ void Mod_IDP0_Load(dp_model_t *mod, void *buffer, void *bufferend) if (!loadmodel->surfmesh.isanimated) { - Mod_MakeCollisionBIH(loadmodel, true); + Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih); loadmodel->TraceBox = Mod_CollisionBIH_TraceBox; loadmodel->TraceLine = Mod_CollisionBIH_TraceLine; loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh; @@ -1580,7 +1580,7 @@ void Mod_IDP2_Load(dp_model_t *mod, void *buffer, void *bufferend) if (!loadmodel->surfmesh.isanimated) { - Mod_MakeCollisionBIH(loadmodel, true); + Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih); loadmodel->TraceBox = Mod_CollisionBIH_TraceBox; loadmodel->TraceLine = Mod_CollisionBIH_TraceLine; loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh; @@ -1760,7 +1760,7 @@ void Mod_IDP3_Load(dp_model_t *mod, void *buffer, void *bufferend) if (!loadmodel->surfmesh.isanimated) { - Mod_MakeCollisionBIH(loadmodel, true); + Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih); loadmodel->TraceBox = Mod_CollisionBIH_TraceBox; loadmodel->TraceLine = Mod_CollisionBIH_TraceLine; loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh; @@ -2132,7 +2132,7 @@ void Mod_ZYMOTICMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend) if (!loadmodel->surfmesh.isanimated) { - Mod_MakeCollisionBIH(loadmodel, true); + Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih); loadmodel->TraceBox = Mod_CollisionBIH_TraceBox; loadmodel->TraceLine = Mod_CollisionBIH_TraceLine; loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh; @@ -2482,7 +2482,7 @@ void Mod_DARKPLACESMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend) if (!loadmodel->surfmesh.isanimated) { - Mod_MakeCollisionBIH(loadmodel, true); + Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih); loadmodel->TraceBox = Mod_CollisionBIH_TraceBox; loadmodel->TraceLine = Mod_CollisionBIH_TraceLine; loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh; @@ -3063,7 +3063,7 @@ void Mod_PSKMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend) if (!loadmodel->surfmesh.isanimated) { - Mod_MakeCollisionBIH(loadmodel, true); + Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih); loadmodel->TraceBox = Mod_CollisionBIH_TraceBox; loadmodel->TraceLine = Mod_CollisionBIH_TraceLine; loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh; @@ -3557,7 +3557,7 @@ void Mod_INTERQUAKEMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend) if (!loadmodel->surfmesh.isanimated) { - Mod_MakeCollisionBIH(loadmodel, true); + Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih); loadmodel->TraceBox = Mod_CollisionBIH_TraceBox; loadmodel->TraceLine = Mod_CollisionBIH_TraceLine; loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh; diff --git a/model_brush.c b/model_brush.c index 7563dd38..1cadbecb 100644 --- a/model_brush.c +++ b/model_brush.c @@ -3738,11 +3738,13 @@ void Mod_Q1BSP_Load(dp_model_t *mod, void *buffer, void *bufferend) if (mod_q1bsp_polygoncollisions.integer) { - Mod_MakeCollisionBIH(mod, true); + Mod_MakeCollisionBIH(mod, true, &mod->collision_bih); // point traces and contents checks still use the bsp tree mod->TraceLine = Mod_CollisionBIH_TraceLine; mod->TraceBox = Mod_CollisionBIH_TraceBox; } + else + Mod_MakeCollisionBIH(mod, true, &mod->render_bih); // generate VBOs and other shared data before cloning submodels if (i == 0) @@ -6589,7 +6591,7 @@ static int Mod_Q3BSP_PointSuperContents(struct model_s *model, int frame, const return supercontents; } -void Mod_MakeCollisionBIH(dp_model_t *model, qboolean userendersurfaces) +bih_t *Mod_MakeCollisionBIH(dp_model_t *model, qboolean userendersurfaces, bih_t *out) { int j; int bihnumleafs; @@ -6626,14 +6628,14 @@ void Mod_MakeCollisionBIH(dp_model_t *model, qboolean userendersurfaces) for (j = 0, surface = model->data_surfaces + model->firstmodelsurface;j < nummodelsurfaces;j++, surface++) { if (surface->texture->basematerialflags & MATERIALFLAG_MESHCOLLISIONS) - bihnumleafs += surface->num_triangles; + bihnumleafs += surface->num_triangles + surface->num_collisiontriangles; else bihnumleafs += surface->num_collisiontriangles; } } if (!bihnumleafs) - return; + return NULL; // allocate the memory for the BIH leaf nodes bihleafs = Mem_Alloc(loadmodel->mempool, sizeof(bih_leaf_t) * bihnumleafs); @@ -6709,17 +6711,19 @@ void Mod_MakeCollisionBIH(dp_model_t *model, qboolean userendersurfaces) temp_leafsortscratch = temp_leafsort + bihnumleafs; // now build it - BIH_Build(&model->collision_bih, bihnumleafs, bihleafs, bihmaxnodes, bihnodes, temp_leafsort, temp_leafsortscratch); + BIH_Build(out, bihnumleafs, bihleafs, bihmaxnodes, bihnodes, temp_leafsort, temp_leafsortscratch); // we're done with the temporary data Mem_Free(temp_leafsort); // resize the BIH nodes array if it over-allocated - if (model->collision_bih.maxnodes > model->collision_bih.numnodes) + if (out->maxnodes > out->numnodes) { - model->collision_bih.maxnodes = model->collision_bih.numnodes; - model->collision_bih.nodes = Mem_Realloc(loadmodel->mempool, model->collision_bih.nodes, model->collision_bih.numnodes * sizeof(bih_node_t)); + out->maxnodes = out->numnodes; + out->nodes = Mem_Realloc(loadmodel->mempool, out->nodes, out->numnodes * sizeof(bih_node_t)); } + + return out; } static int Mod_Q3BSP_SuperContentsFromNativeContents(dp_model_t *model, int nativecontents) @@ -7035,7 +7039,8 @@ void Mod_Q3BSP_Load(dp_model_t *mod, void *buffer, void *bufferend) if (j < mod->nummodelsurfaces) mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes; - Mod_MakeCollisionBIH(mod, false); + Mod_MakeCollisionBIH(mod, false, &mod->collision_bih); + Mod_MakeCollisionBIH(mod, true, &mod->render_bih); // generate VBOs and other shared data before cloning submodels if (i == 0) @@ -7472,7 +7477,8 @@ void Mod_OBJ_Load(dp_model_t *mod, void *buffer, void *bufferend) 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_MakeCollisionBIH(loadmodel, true); + Mod_MakeCollisionBIH(loadmodel, true, &mod->collision_bih); + mod->render_bih = mod->collision_bih; } diff --git a/model_shared.h b/model_shared.h index f8a8dabe..8b15a6ef 100644 --- a/model_shared.h +++ b/model_shared.h @@ -960,6 +960,7 @@ typedef struct model_s int nummodelbrushes; // BIH (Bounding Interval Hierarchy) for this (sub)model bih_t collision_bih; + bih_t render_bih; // if not set, use collision_bih instead for rendering purposes too // for md3 models int num_tags; int num_tagframes; @@ -1169,7 +1170,7 @@ void Mod_CollisionBIH_TraceLine(dp_model_t *model, const struct frameblend_s *fr void Mod_CollisionBIH_TraceBox(dp_model_t *model, const struct frameblend_s *frameblend, const skeleton_t *skeleton, struct trace_s *trace, const vec3_t start, const vec3_t boxmins, const vec3_t boxmaxs, const vec3_t end, int hitsupercontentsmask); void Mod_CollisionBIH_TracePoint_Mesh(dp_model_t *model, const struct frameblend_s *frameblend, const skeleton_t *skeleton, struct trace_s *trace, const vec3_t start, int hitsupercontentsmask); int Mod_CollisionBIH_PointSuperContents_Mesh(struct model_s *model, int frame, const vec3_t point); -void Mod_MakeCollisionBIH(dp_model_t *model, qboolean userendersurfaces); +bih_t *Mod_MakeCollisionBIH(dp_model_t *model, qboolean userendersurfaces, bih_t *out); // alias models struct frameblend_s; -- 2.39.2