}
else if (ui)
{
- // for ui we have to preserve the order of surfaces (not using sortedmodelsurfaces)
+ // for ui we have to preserve the order of surfaces (not using modelsurfaces_sorted)
for (i = model->submodelsurfaces_start; i < model->submodelsurfaces_end; i++)
r_surfacelist[numsurfacelist++] = surfaces + i;
}
void R_Mod_DrawAddWaterPlanes(entity_render_t *ent)
{
- int i, j, n, flagsmask;
+ int i, n, flagsmask;
model_t *model = ent->model;
msurface_t *surfaces;
if (model == NULL)
if (ent == r_refdef.scene.worldentity)
{
for (i = model->submodelsurfaces_start;i < model->submodelsurfaces_end;i++)
- {
- j = model->modelsurfaces_sorted[i];
- if (r_refdef.viewcache.world_surfacevisible[j])
- if (surfaces[j].texture->basematerialflags & flagsmask)
- R_Water_AddWaterPlane(surfaces + j, 0);
- }
+ if (r_refdef.viewcache.world_surfacevisible[i])
+ if (surfaces[i].texture->basematerialflags & flagsmask)
+ R_Water_AddWaterPlane(surfaces + i, 0);
}
else
{
else
n = 0;
for (i = model->submodelsurfaces_start;i < model->submodelsurfaces_end;i++)
- {
- j = model->modelsurfaces_sorted[i];
- if (surfaces[j].texture->basematerialflags & flagsmask)
- R_Water_AddWaterPlane(surfaces + j, n);
- }
+ if (surfaces[i].texture->basematerialflags & flagsmask)
+ R_Water_AddWaterPlane(surfaces + i, n);
}
rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
}
loadmodel->modeldatatypestring = "MDL";
loadmodel->type = mod_alias;
- loadmodel->DrawSky = NULL;
- loadmodel->DrawAddWaterPlanes = NULL;
loadmodel->Draw = R_Mod_Draw;
loadmodel->DrawDepth = R_Mod_DrawDepth;
loadmodel->DrawDebug = R_Mod_DrawDebug;
loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
}
-
- // because shaders can do somewhat unexpected things, check for unusual features now
- for (i = 0;i < loadmodel->num_textures;i++)
- {
- if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
- mod->DrawSky = R_Mod_DrawSky;
- if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
- mod->DrawAddWaterPlanes = R_Mod_DrawAddWaterPlanes;
- }
}
void Mod_IDP2_Load(model_t *mod, void *buffer, void *bufferend)
loadmodel->modeldatatypestring = "MD2";
loadmodel->type = mod_alias;
- loadmodel->DrawSky = NULL;
- loadmodel->DrawAddWaterPlanes = NULL;
loadmodel->Draw = R_Mod_Draw;
loadmodel->DrawDepth = R_Mod_DrawDepth;
loadmodel->DrawDebug = R_Mod_DrawDebug;
loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
}
-
- // because shaders can do somewhat unexpected things, check for unusual features now
- for (i = 0;i < loadmodel->num_textures;i++)
- {
- if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
- mod->DrawSky = R_Mod_DrawSky;
- if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
- mod->DrawAddWaterPlanes = R_Mod_DrawAddWaterPlanes;
- }
}
void Mod_IDP3_Load(model_t *mod, void *buffer, void *bufferend)
loadmodel->modeldatatypestring = "MD3";
loadmodel->type = mod_alias;
- loadmodel->DrawSky = NULL;
- loadmodel->DrawAddWaterPlanes = NULL;
loadmodel->Draw = R_Mod_Draw;
loadmodel->DrawDepth = R_Mod_DrawDepth;
loadmodel->DrawDebug = R_Mod_DrawDebug;
loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
}
-
- // because shaders can do somewhat unexpected things, check for unusual features now
- for (i = 0;i < loadmodel->num_textures;i++)
- {
- if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
- mod->DrawSky = R_Mod_DrawSky;
- if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
- mod->DrawAddWaterPlanes = R_Mod_DrawAddWaterPlanes;
- }
}
void Mod_ZYMOTICMODEL_Load(model_t *mod, void *buffer, void *bufferend)
return;
}
- loadmodel->DrawSky = NULL;
- loadmodel->DrawAddWaterPlanes = NULL;
loadmodel->Draw = R_Mod_Draw;
loadmodel->DrawDepth = R_Mod_DrawDepth;
loadmodel->DrawDebug = R_Mod_DrawDebug;
loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
}
-
- // because shaders can do somewhat unexpected things, check for unusual features now
- for (i = 0;i < loadmodel->num_textures;i++)
- {
- if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
- mod->DrawSky = R_Mod_DrawSky;
- if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
- mod->DrawAddWaterPlanes = R_Mod_DrawAddWaterPlanes;
- }
}
void Mod_DARKPLACESMODEL_Load(model_t *mod, void *buffer, void *bufferend)
return;
}
- loadmodel->DrawSky = NULL;
- loadmodel->DrawAddWaterPlanes = NULL;
loadmodel->Draw = R_Mod_Draw;
loadmodel->DrawDepth = R_Mod_DrawDepth;
loadmodel->DrawDebug = R_Mod_DrawDebug;
loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
}
-
- // because shaders can do somewhat unexpected things, check for unusual features now
- for (i = 0;i < loadmodel->num_textures;i++)
- {
- if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
- mod->DrawSky = R_Mod_DrawSky;
- if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
- mod->DrawAddWaterPlanes = R_Mod_DrawAddWaterPlanes;
- }
}
// no idea why PSK/PSA files contain weird quaternions but they do...
loadmodel->modeldatatypestring = "PSK";
loadmodel->type = mod_alias;
- loadmodel->DrawSky = NULL;
- loadmodel->DrawAddWaterPlanes = NULL;
loadmodel->Draw = R_Mod_Draw;
loadmodel->DrawDepth = R_Mod_DrawDepth;
loadmodel->DrawDebug = R_Mod_DrawDebug;
loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
}
-
- // because shaders can do somewhat unexpected things, check for unusual features now
- for (i = 0;i < loadmodel->num_textures;i++)
- {
- if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
- mod->DrawSky = R_Mod_DrawSky;
- if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
- mod->DrawAddWaterPlanes = R_Mod_DrawAddWaterPlanes;
- }
}
void Mod_INTERQUAKEMODEL_Load(model_t *mod, void *buffer, void *bufferend)
text = header.num_text && header.ofs_text ? (const char *)(pbase + header.ofs_text) : "";
- loadmodel->DrawSky = NULL;
- loadmodel->DrawAddWaterPlanes = NULL;
loadmodel->Draw = R_Mod_Draw;
loadmodel->DrawDepth = R_Mod_DrawDepth;
loadmodel->DrawDebug = R_Mod_DrawDebug;
if (joint1 ) Mem_Free(joint1 );joint1 = NULL;
if (pose ) Mem_Free(pose );pose = NULL;
if (pose1 ) Mem_Free(pose1 );pose1 = NULL;
-
- // because shaders can do somewhat unexpected things, check for unusual features now
- for (i = 0;i < loadmodel->num_textures;i++)
- {
- if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
- mod->DrawSky = R_Mod_DrawSky;
- if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
- mod->DrawAddWaterPlanes = R_Mod_DrawAddWaterPlanes;
- }
}
mod->radius = modelradius;
mod->radius2 = modelradius * modelradius;
- // this gets altered below if sky or water is used
- mod->DrawSky = NULL;
- mod->DrawAddWaterPlanes = NULL;
+ Mod_SetDrawSkyAndWater(mod);
- // scan surfaces for sky and water and flag the submodel as possessing these features or not
- // build lightstyle lists for quick marking of dirty lightmaps when lightstyles flicker
if (mod->submodelsurfaces_start < mod->submodelsurfaces_end)
{
- for (j = mod->submodelsurfaces_start; j < mod->submodelsurfaces_end; j++)
- if (mod->data_surfaces[j].texture->basematerialflags & MATERIALFLAG_SKY)
- break;
- if (j < mod->submodelsurfaces_end)
- mod->DrawSky = R_Mod_DrawSky;
-
- for (j = mod->submodelsurfaces_start;j < mod->submodelsurfaces_end;j++)
- if (mod->data_surfaces[j].texture && mod->data_surfaces[j].texture->basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
- break;
- if (j < mod->submodelsurfaces_end)
- mod->DrawAddWaterPlanes = R_Mod_DrawAddWaterPlanes;
-
// build lightstyle update chains
// (used to rapidly mark lightmapupdateflags on many surfaces
// when d_lightstylevalue changes)
mod->radius = modelradius;
mod->radius2 = modelradius * modelradius;
- // this gets altered below if sky or water is used
- mod->DrawSky = NULL;
- mod->DrawAddWaterPlanes = NULL;
+ Mod_SetDrawSkyAndWater(mod);
- // scan surfaces for sky and water and flag the submodel as possessing these features or not
// build lightstyle lists for quick marking of dirty lightmaps when lightstyles flicker
if (mod->submodelsurfaces_start < mod->submodelsurfaces_end)
{
- for (j = mod->submodelsurfaces_start;j < mod->submodelsurfaces_end;j++)
- if (mod->data_surfaces[j].texture && (mod->data_surfaces[j].texture->basematerialflags & MATERIALFLAG_SKY))
- break;
- if (j < mod->submodelsurfaces_end)
- mod->DrawSky = R_Mod_DrawSky;
-
- for (j = mod->submodelsurfaces_start;j < mod->submodelsurfaces_end;j++)
- if (mod->data_surfaces[j].texture && (mod->data_surfaces[j].texture->basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
- break;
- if (j < mod->submodelsurfaces_end)
- mod->DrawAddWaterPlanes = R_Mod_DrawAddWaterPlanes;
-
// build lightstyle update chains
// (used to rapidly mark lightmapupdateflags on many surfaces
// when d_lightstylevalue changes)
loadmodel->brush.submodels = (model_t **)Mem_Alloc(loadmodel->mempool, loadmodel->brush.numsubmodels * sizeof(model_t *));
mod = loadmodel;
+ mod->modelsurfaces_sorted = (int*)Mem_Alloc(loadmodel->mempool, mod->num_surfaces * sizeof(*mod->modelsurfaces_sorted));
for (i = 0;i < loadmodel->brush.numsubmodels;i++)
{
if (i > 0)
mod->submodelsurfaces_end = mod->brushq3.data_models[i].firstface + mod->brushq3.data_models[i].numfaces;
mod->firstmodelbrush = mod->brushq3.data_models[i].firstbrush;
mod->nummodelbrushes = mod->brushq3.data_models[i].numbrushes;
- mod->modelsurfaces_sorted = (int *)Mem_Alloc(loadmodel->mempool, mod->num_surfaces * sizeof(*mod->modelsurfaces_sorted));
VectorCopy(mod->brushq3.data_models[i].mins, mod->normalmins);
VectorCopy(mod->brushq3.data_models[i].maxs, mod->normalmaxs);
//printf("Editing model %d... BEFORE re-bounding: %f %f %f - %f %f %f\n", i, mod->normalmins[0], mod->normalmins[1], mod->normalmins[2], mod->normalmaxs[0], mod->normalmaxs[1], mod->normalmaxs[2]);
for (j = mod->submodelsurfaces_start;j < mod->submodelsurfaces_end;j++)
{
- const msurface_t *surface = mod->data_surfaces + j + mod->submodelsurfaces_start;
+ const msurface_t *surface = mod->data_surfaces + j;
const float *v = mod->surfmesh.data_vertex3f + 3 * surface->num_firstvertex;
int k;
if (!surface->num_vertices)
mod->radius = modelradius;
mod->radius2 = modelradius * modelradius;
- // this gets altered below if sky or water is used
- mod->DrawSky = NULL;
- mod->DrawAddWaterPlanes = NULL;
-
- for (j = mod->submodelsurfaces_start;j < mod->submodelsurfaces_end;j++)
- if (mod->data_surfaces[j].texture && mod->data_surfaces[j].texture->basematerialflags & MATERIALFLAG_SKY)
- break;
- if (j < mod->submodelsurfaces_end)
- mod->DrawSky = R_Mod_DrawSky;
-
- for (j = mod->submodelsurfaces_start; j < mod->submodelsurfaces_end; j++)
- if (mod->data_surfaces[j].texture->basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
- break;
- if (j < mod->submodelsurfaces_end)
- mod->DrawAddWaterPlanes = R_Mod_DrawAddWaterPlanes;
-
+ Mod_SetDrawSkyAndWater(mod);
Mod_MakeCollisionBIH(mod, false, &mod->collision_bih);
Mod_MakeCollisionBIH(mod, true, &mod->render_bih);
mod->radius = modelradius;
mod->radius2 = modelradius * modelradius;
- // this gets altered below if sky or water is used
- mod->DrawSky = NULL;
- mod->DrawAddWaterPlanes = NULL;
-
- for (j = mod->submodelsurfaces_start; j < mod->submodelsurfaces_end; j++)
- if (mod->data_surfaces[j].texture->basematerialflags & MATERIALFLAG_SKY)
- break;
- if (j < mod->submodelsurfaces_end)
- mod->DrawSky = R_Mod_DrawSky;
-
- for (j = mod->submodelsurfaces_start; j < mod->submodelsurfaces_end; j++)
- if (mod->data_surfaces[j].texture->basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
- break;
- if (j < mod->submodelsurfaces_end)
- mod->DrawAddWaterPlanes = R_Mod_DrawAddWaterPlanes;
+ Mod_SetDrawSkyAndWater(mod);
Mod_MakeCollisionBIH(mod, true, &mod->collision_bih);
mod->render_bih = mod->collision_bih;
Mem_Free(buf);
}
+ Mod_SetDrawSkyAndWater(mod);
Mod_BuildVBOs();
break;
}
*lastvertexpointer = lastvertex;
}
+void Mod_SetDrawSkyAndWater(model_t* mod)
+{
+ size_t j;
+ uint64_t basematerialflags = 0;
+ // by default assume there is no sky or water used in this model
+ mod->DrawSky = NULL;
+ mod->DrawAddWaterPlanes = NULL;
+ // combine all basematerialflags observed in the submodelsurfaces range, then check for special flags
+ for (j = mod->submodelsurfaces_start; j < mod->submodelsurfaces_end; j++)
+ if (mod->data_surfaces[j].texture)
+ basematerialflags |= mod->data_surfaces[j].texture->basematerialflags;
+ if (basematerialflags & MATERIALFLAG_SKY)
+ mod->DrawSky = R_Mod_DrawSky;
+ if (basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
+ mod->DrawAddWaterPlanes = R_Mod_DrawAddWaterPlanes;
+}
+
typedef struct Mod_MakeSortedSurfaces_qsortsurface_s
{
- int submodel;
int surfaceindex;
q3deffect_t* effect;
texture_t* texture;
{
const Mod_MakeSortedSurfaces_qsortsurface_t* l = (Mod_MakeSortedSurfaces_qsortsurface_t*)a;
const Mod_MakeSortedSurfaces_qsortsurface_t* r = (Mod_MakeSortedSurfaces_qsortsurface_t*)b;
- if (l->submodel < r->submodel)
- return -1;
- if (l->submodel > r->submodel)
- return 1;
if (l->effect < r->effect)
return -1;
if (l->effect > r->effect)
// the goal is to sort by submodel (can't change which submodel a surface belongs to), and then by effects and textures
for (j = 0; j < mod->num_surfaces; j++)
{
- info[j].submodel = 0;
info[j].surfaceindex = j;
info[j].effect = mod->data_surfaces[j].effect;
info[j].texture = mod->data_surfaces[j].texture;
info[j].lightmaptexture = mod->data_surfaces[j].lightmaptexture;
}
for (k = 0; k < mod->brush.numsubmodels; k++)
- for (j = mod->brush.submodels[k]->submodelsurfaces_start; j < mod->brush.submodels[k]->submodelsurfaces_end; j++)
- info[j].submodel = k;
- qsort(info, mod->num_surfaces, sizeof(*info), Mod_MakeSortedSurfaces_qsortfunc);
+ if (mod->brush.submodels[k]->submodelsurfaces_end > mod->brush.submodels[k]->submodelsurfaces_start + 1)
+ qsort(info + mod->brush.submodels[k]->submodelsurfaces_start, (size_t)mod->brush.submodels[k]->submodelsurfaces_end - mod->brush.submodels[k]->submodelsurfaces_start, sizeof(*info), Mod_MakeSortedSurfaces_qsortfunc);
for (j = 0; j < mod->num_surfaces; j++)
mod->modelsurfaces_sorted[j] = info[j].surfaceindex;
}
const char *modeldatatypestring;
// generates vertex data for a given frameblend
void(*AnimateVertices)(const struct model_s * RESTRICT model, const struct frameblend_s * RESTRICT frameblend, const struct skeleton_s *skeleton, float * RESTRICT vertex3f, float * RESTRICT normal3f, float * RESTRICT svector3f, float * RESTRICT tvector3f);
- // draw the model's sky polygons (only used by brush models)
+ // draw the model's sky polygons
void(*DrawSky)(struct entity_render_s *ent);
- // draw refraction/reflection textures for the model's water polygons (only used by brush models)
+ // draw refraction/reflection textures for the model's water polygons
void(*DrawAddWaterPlanes)(struct entity_render_s *ent);
// draw the model using lightmap/dlight shading
void(*Draw)(struct entity_render_s *ent);
// automatically called after model loader returns
void Mod_BuildVBOs(void);
+/// Sets the mod->DrawSky and mod->DrawAddWaterPlanes pointers conditionally based on whether surfaces in this submodel use these features
+/// called specifically by brush model loaders when generating submodels
+/// automatically called after model loader returns
+void Mod_SetDrawSkyAndWater(model_t* mod);
+
shadowmesh_t *Mod_ShadowMesh_Alloc(struct mempool_s *mempool, int maxverts, int maxtriangles);
int Mod_ShadowMesh_AddVertex(shadowmesh_t *mesh, const float *vertex3f);
void Mod_ShadowMesh_AddMesh(shadowmesh_t *mesh, const float *vertex3f, int numtris, const int *element3i);
loadmodel->type = mod_sprite;
- loadmodel->DrawSky = NULL;
loadmodel->Draw = R_Model_Sprite_Draw;
loadmodel->DrawDepth = NULL;
loadmodel->DrawLight = NULL;
- loadmodel->DrawAddWaterPlanes = NULL;
version = LittleLong(((dsprite_t *)buffer)->version);
if (version == SPRITE_VERSION || version == SPRITE32_VERSION)
loadmodel->type = mod_sprite;
- loadmodel->DrawSky = NULL;
loadmodel->Draw = R_Model_Sprite_Draw;
loadmodel->DrawDepth = NULL;
loadmodel->DrawLight = NULL;
- loadmodel->DrawAddWaterPlanes = NULL;
pinqsprite = (dsprite2_t *)buffer;