model_t *model;
const msurface_t *surface;
const msurface_t *surfaces;
- const int *surfacelist;
const texture_t *texture;
int numtriangles;
- int numsurfacelist;
- int surfacelistindex;
int surfaceindex;
int triangleindex;
float localorigin[3];
#endif
dynamic = model->surfmesh.isanimated;
- numsurfacelist = model->nummodelsurfaces;
- surfacelist = model->sortedmodelsurfaces;
surfaces = model->data_surfaces;
bih = NULL;
}
else
{
- for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
+ for (surfaceindex = model->submodelsurfaces_start;surfaceindex < model->submodelsurfaces_end;surfaceindex++)
{
- 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))
static void R_DrawDebugModel(void)
{
entity_render_t *ent = rsurface.entity;
- int i, j, flagsmask;
+ int j, flagsmask;
const msurface_t *surface;
model_t *model = ent->model;
GL_DepthMask(false);
GL_DepthRange(0, 1);
GL_BlendFunc(GL_ONE, GL_ONE);
- for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
+ for (j = model->submodelsurfaces_start;j < model->submodelsurfaces_end;j++)
{
if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
continue;
+ surface = model->data_surfaces + j;
rsurface.texture = R_GetCurrentTexture(surface->texture);
if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
{
GL_DepthMask(true);
}
qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
- for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
+ for (j = model->submodelsurfaces_start; j < model->submodelsurfaces_end; j++)
{
if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
continue;
+ surface = model->data_surfaces + j;
rsurface.texture = R_GetCurrentTexture(surface->texture);
if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
{
GL_BlendFunc(GL_ONE, GL_ZERO);
GL_DepthMask(true);
}
- for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
+ for (j = model->submodelsurfaces_start; j < model->submodelsurfaces_end; j++)
{
if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
continue;
+ surface = model->data_surfaces + j;
rsurface.texture = R_GetCurrentTexture(surface->texture);
if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
{
}
// check if this is an empty model
- if (model->nummodelsurfaces == 0)
+ if (model->submodelsurfaces_start >= model->submodelsurfaces_end)
return;
rsurface.lightmaptexture = NULL;
if (ent == r_refdef.scene.worldentity)
{
// for the world entity, check surfacevisible
- for (i = 0;i < model->nummodelsurfaces;i++)
+ for (i = model->submodelsurfaces_start;i < model->submodelsurfaces_end;i++)
{
- j = model->sortedmodelsurfaces[i];
+ j = model->modelsurfaces_sorted[i];
if (r_refdef.viewcache.world_surfacevisible[j])
r_surfacelist[numsurfacelist++] = surfaces + j;
}
else if (ui)
{
// for ui we have to preserve the order of surfaces (not using sortedmodelsurfaces)
- for (i = 0; i < model->nummodelsurfaces; i++)
- r_surfacelist[numsurfacelist++] = surfaces + model->firstmodelsurface + i;
+ for (i = model->submodelsurfaces_start; i < model->submodelsurfaces_end; i++)
+ r_surfacelist[numsurfacelist++] = surfaces + i;
}
else
{
// add all surfaces
- for (i = 0; i < model->nummodelsurfaces; i++)
- r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
+ for (i = model->submodelsurfaces_start; i < model->submodelsurfaces_end; i++)
+ r_surfacelist[numsurfacelist++] = surfaces + model->modelsurfaces_sorted[i];
}
/*
static void R_View_WorldVisibility_CullSurfaces(void)
{
int surfaceindex;
- int surfaceindexstart;
- int surfaceindexend;
unsigned char *surfacevisible;
msurface_t *surfaces;
model_t *model = r_refdef.scene.worldmodel;
return;
if (r_usesurfaceculling.integer < 1)
return;
- surfaceindexstart = model->firstmodelsurface;
- surfaceindexend = surfaceindexstart + model->nummodelsurfaces;
surfaces = model->data_surfaces;
surfacevisible = r_refdef.viewcache.world_surfacevisible;
- for (surfaceindex = surfaceindexstart; surfaceindex < surfaceindexend; surfaceindex++)
+ for (surfaceindex = model->submodelsurfaces_start; surfaceindex < model->submodelsurfaces_end; surfaceindex++)
{
if (surfacevisible[surfaceindex])
{
// add visible surfaces to draw list
if (ent == r_refdef.scene.worldentity)
{
- for (i = 0;i < model->nummodelsurfaces;i++)
+ for (i = model->submodelsurfaces_start;i < model->submodelsurfaces_end;i++)
{
- j = model->sortedmodelsurfaces[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);
n = ent->entitynumber;
else
n = 0;
- for (i = 0;i < model->nummodelsurfaces;i++)
+ for (i = model->submodelsurfaces_start;i < model->submodelsurfaces_end;i++)
{
- j = model->sortedmodelsurfaces[i];
+ j = model->modelsurfaces_sorted[i];
if (surfaces[j].texture->basematerialflags & flagsmask)
R_Water_AddWaterPlane(surfaces + j, n);
}
info->outnumleafs = 0;
info->outnumsurfaces = 0;
memset(info->outleafpvs, 0, (info->model->brush.num_leafs + 7) >> 3);
- memset(info->outsurfacepvs, 0, (info->model->nummodelsurfaces + 7) >> 3);
+ memset(info->outsurfacepvs, 0, (info->model->num_surfaces + 7) >> 3);
memset(info->outshadowtrispvs, 0, (info->model->surfmesh.num_triangles + 7) >> 3);
memset(info->outlighttrispvs, 0, (info->model->surfmesh.num_triangles + 7) >> 3);
}
VectorCopy(info.relativelightorigin, info.outmaxs);
memset(visitingleafpvs, 0, (info.model->brush.num_leafs + 7) >> 3);
memset(outleafpvs, 0, (info.model->brush.num_leafs + 7) >> 3);
- memset(outsurfacepvs, 0, (info.model->nummodelsurfaces + 7) >> 3);
+ memset(outsurfacepvs, 0, (info.model->num_surfaces + 7) >> 3);
memset(outshadowtrispvs, 0, (info.model->surfmesh.num_triangles + 7) >> 3);
memset(outlighttrispvs, 0, (info.model->surfmesh.num_triangles + 7) >> 3);
if (info.model->brush.GetPVS && !info.noocclusion)
loadmodel->AnimateVertices = Mod_MDL_AnimateVertices;
loadmodel->num_surfaces = 1;
- loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
+ loadmodel->submodelsurfaces_start = 0;
+ loadmodel->submodelsurfaces_end = loadmodel->num_surfaces;
data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int));
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->modelsurfaces_sorted = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
+ loadmodel->modelsurfaces_sorted[0] = 0;
loadmodel->numskins = LittleLong(pinmodel->numskins);
BOUNDI(loadmodel->numskins,0,65536);
iskinheight = 1.0f / skinheight;
loadmodel->num_surfaces = 1;
- loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
+ loadmodel->submodelsurfaces_start = 0;
+ loadmodel->submodelsurfaces_end = 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->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->modelsurfaces_sorted = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
+ loadmodel->modelsurfaces_sorted[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]);
meshtriangles += LittleLong(pinmesh->num_triangles);
}
- loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
+ loadmodel->submodelsurfaces_start = 0;
+ loadmodel->submodelsurfaces_end = loadmodel->num_surfaces;
loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
loadmodel->num_texturesperskin = loadmodel->num_surfaces;
data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t) + meshtriangles * sizeof(int[3]) + (meshvertices <= 65536 ? meshtriangles * sizeof(unsigned short[3]) : 0) + meshvertices * sizeof(float[2]) + meshvertices * loadmodel->numframes * sizeof(md3vertex_t));
loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
- loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
+ loadmodel->modelsurfaces_sorted = (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 = meshvertices;
loadmodel->surfmesh.num_triangles = meshtriangles;
{
if (memcmp(pinmesh->identifier, "IDP3", 4))
Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
- loadmodel->sortedmodelsurfaces[i] = i;
+ loadmodel->modelsurfaces_sorted[i] = i;
surface = loadmodel->data_surfaces + i;
surface->texture = loadmodel->data_textures + i;
surface->num_firsttriangle = meshtriangles;
meshvertices = pheader->numverts;
meshtriangles = pheader->numtris;
- loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
+ loadmodel->submodelsurfaces_start = 0;
+ loadmodel->submodelsurfaces_end = loadmodel->num_surfaces;
loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
loadmodel->num_texturesperskin = loadmodel->num_surfaces;
data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t) + meshtriangles * sizeof(int[3]) + (meshvertices <= 65536 ? meshtriangles * sizeof(unsigned short[3]) : 0) + meshvertices * (sizeof(float[14]) + sizeof(unsigned short) + sizeof(unsigned char[2][4])) + loadmodel->num_poses * loadmodel->num_bones * sizeof(short[7]) + loadmodel->num_bones * sizeof(float[12]));
loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
- loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
+ loadmodel->modelsurfaces_sorted = (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 = meshvertices;
loadmodel->surfmesh.num_triangles = meshtriangles;
if (renderlist + count * 3 > renderlistend || (i == pheader->numshaders - 1 && renderlist + count * 3 != renderlistend))
Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
- loadmodel->sortedmodelsurfaces[i] = i;
+ loadmodel->modelsurfaces_sorted[i] = i;
surface = loadmodel->data_surfaces + i;
surface->texture = loadmodel->data_textures + i;
surface->num_firsttriangle = meshtriangles;
loadmodel->numframes = pheader->num_frames;
loadmodel->num_bones = pheader->num_bones;
loadmodel->num_poses = loadmodel->numframes;
- loadmodel->nummodelsurfaces = loadmodel->num_surfaces = pheader->num_meshs;
+ loadmodel->submodelsurfaces_start = 0;
+ loadmodel->submodelsurfaces_end = loadmodel->num_surfaces = pheader->num_meshs;
loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
loadmodel->num_texturesperskin = loadmodel->num_surfaces;
// do most allocations as one merged chunk
data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t) + meshtriangles * sizeof(int[3]) + (meshvertices <= 65536 ? meshtriangles * sizeof(unsigned short[3]) : 0) + meshvertices * (sizeof(float[14]) + sizeof(unsigned short) + sizeof(unsigned char[2][4])) + loadmodel->num_poses * loadmodel->num_bones * sizeof(short[7]) + loadmodel->num_bones * sizeof(float[12]) + loadmodel->numskins * sizeof(animscene_t) + loadmodel->num_bones * sizeof(aliasbone_t) + loadmodel->numframes * sizeof(animscene_t));
loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
- loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
+ loadmodel->modelsurfaces_sorted = (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 = meshvertices;
loadmodel->surfmesh.num_triangles = meshtriangles;
const float *intexcoord;
msurface_t *surface;
- loadmodel->sortedmodelsurfaces[i] = i;
+ loadmodel->modelsurfaces_sorted[i] = i;
surface = loadmodel->data_surfaces + i;
surface->texture = loadmodel->data_textures + i;
surface->num_firsttriangle = meshtriangles;
loadmodel->numskins = 1;
loadmodel->num_bones = numbones;
loadmodel->num_poses = loadmodel->numframes;
- loadmodel->nummodelsurfaces = loadmodel->num_surfaces = nummatts;
+ loadmodel->submodelsurfaces_start = 0;
+ loadmodel->submodelsurfaces_end = loadmodel->num_surfaces = nummatts;
loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
loadmodel->num_texturesperskin = loadmodel->num_surfaces;
loadmodel->surfmesh.num_vertices = meshvertices;
size = loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t) + loadmodel->surfmesh.num_triangles * sizeof(int[3]) + loadmodel->surfmesh.num_vertices * sizeof(float[3]) + loadmodel->surfmesh.num_vertices * sizeof(float[3]) + loadmodel->surfmesh.num_vertices * sizeof(float[3]) + loadmodel->surfmesh.num_vertices * sizeof(float[3]) + loadmodel->surfmesh.num_vertices * sizeof(float[2]) + loadmodel->surfmesh.num_vertices * sizeof(unsigned char[4]) + loadmodel->surfmesh.num_vertices * sizeof(unsigned char[4]) + loadmodel->surfmesh.num_vertices * sizeof(unsigned short) + loadmodel->num_poses * loadmodel->num_bones * sizeof(short[7]) + loadmodel->num_bones * sizeof(float[12]) + loadmodel->numskins * sizeof(animscene_t) + loadmodel->num_bones * sizeof(aliasbone_t) + loadmodel->numframes * sizeof(animscene_t) + ((loadmodel->surfmesh.num_vertices <= 65536) ? (loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3])) : 0);
data = (unsigned char *)Mem_Alloc(loadmodel->mempool, size);
loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
- loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
+ loadmodel->modelsurfaces_sorted = (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.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
loadmodel->surfmesh.data_vertex3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
{
// since psk models do not have named sections, reuse their shader name as the section name
Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + index, skinfiles, matts[index].name, matts[index].name);
- loadmodel->sortedmodelsurfaces[index] = index;
+ loadmodel->modelsurfaces_sorted[index] = index;
loadmodel->data_surfaces[index].texture = loadmodel->data_textures + index;
loadmodel->data_surfaces[index].num_firstvertex = 0;
loadmodel->data_surfaces[index].num_vertices = loadmodel->surfmesh.num_vertices;
loadmodel->numframes = max(header.num_anims, 1);
loadmodel->num_bones = header.num_joints;
loadmodel->num_poses = max(header.num_frames, 1);
- loadmodel->nummodelsurfaces = loadmodel->num_surfaces = header.num_meshes;
+ loadmodel->submodelsurfaces_start = 0;
+ loadmodel->submodelsurfaces_end = loadmodel->num_surfaces = header.num_meshes;
loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
loadmodel->num_texturesperskin = loadmodel->num_surfaces;
// do most allocations as one merged chunk
data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t) + meshtriangles * sizeof(int[3]) + (meshvertices <= 65536 ? meshtriangles * sizeof(unsigned short[3]) : 0) + meshvertices * (sizeof(float[14]) + (vcolor4f || vcolor4ub ? sizeof(float[4]) : 0)) + (vblendindexes && vblendweights ? meshvertices * (sizeof(unsigned short) + sizeof(unsigned char[2][4])) : 0) + loadmodel->num_poses * loadmodel->num_bones * sizeof(short[7]) + loadmodel->num_bones * sizeof(float[12]) + loadmodel->numskins * sizeof(animscene_t) + loadmodel->num_bones * sizeof(aliasbone_t) + loadmodel->numframes * sizeof(animscene_t));
loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
- loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
+ loadmodel->modelsurfaces_sorted = (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 = meshvertices;
loadmodel->surfmesh.num_triangles = meshtriangles;
mesh.first_triangle = LittleLong(meshes[i].first_triangle);
mesh.num_triangles = LittleLong(meshes[i].num_triangles);
- loadmodel->sortedmodelsurfaces[i] = i;
+ loadmodel->modelsurfaces_sorted[i] = i;
surface = loadmodel->data_surfaces + i;
surface->texture = loadmodel->data_textures + i;
surface->num_firsttriangle = mesh.first_triangle;
// fixes up sky surfaces that have SKY contents behind them, so that they do not cast shadows (e1m5 logo shadow trick).
static void Mod_Q1BSP_AssignNoShadowSkySurfaces(model_t *mod)
{
- int i;
+ int surfaceindex;
msurface_t *surface;
vec3_t center;
int contents;
- for (i = 0, surface = mod->data_surfaces + mod->firstmodelsurface; i < mod->nummodelsurfaces; i++, surface++)
+ for (surfaceindex = mod->submodelsurfaces_start; surfaceindex < mod->submodelsurfaces_end;surfaceindex++)
{
+ surface = mod->data_surfaces + surfaceindex;
if (surface->texture->basematerialflags & MATERIALFLAG_SKY)
{
// check if the point behind the surface polygon is SOLID or SKY contents
}
}
datapointer = (unsigned char *)Mem_Alloc(mod->mempool, mod->num_surfaces * sizeof(int) + totalstyles * sizeof(model_brush_lightstyleinfo_t) + totalstylesurfaces * sizeof(int *));
+ mod->modelsurfaces_sorted = (int*)datapointer;datapointer += mod->num_surfaces * sizeof(int);
for (i = 0;i < mod->brush.numsubmodels;i++)
{
// LadyHavoc: this code was originally at the end of this loop, but
mod->brushq1.hulls[j].lastclipnode = mod->brushq1.numclipnodes - 1;
}
- mod->firstmodelsurface = bm->firstface;
- mod->nummodelsurfaces = bm->numfaces;
+ mod->submodelsurfaces_start = bm->firstface;
+ mod->submodelsurfaces_end = bm->firstface + bm->numfaces;
// set node/leaf parents for this submodel
Mod_BSP_LoadNodes_RecursiveSetParent(mod->brush.data_nodes + mod->brushq1.hulls[0].firstclipnode, NULL);
// this has to occur after hull info has been set, as it uses Mod_Q1BSP_PointSuperContents
Mod_Q1BSP_AssignNoShadowSkySurfaces(mod);
- // make the model surface list (used by shadowing/lighting)
- mod->sortedmodelsurfaces = (int *)datapointer;datapointer += mod->nummodelsurfaces * sizeof(int);
- Mod_MakeSortedSurfaces(mod);
-
// copy the submodel bounds, then enlarge the yaw and rotated bounds according to radius
// (previously this code measured the radius of the vertices of surfaces in the submodel, but that broke submodels that contain only CLIP brushes, which do not produce surfaces)
VectorCopy(bm->mins, mod->normalmins);
// 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->nummodelsurfaces)
+ if (mod->submodelsurfaces_start < mod->submodelsurfaces_end)
{
- for (j = 0, surface = &mod->data_surfaces[mod->firstmodelsurface];j < mod->nummodelsurfaces;j++, surface++)
- if (surface->texture->basematerialflags & MATERIALFLAG_SKY)
+ for (j = mod->submodelsurfaces_start; j < mod->submodelsurfaces_end; j++)
+ if (mod->data_surfaces[j].texture->basematerialflags & MATERIALFLAG_SKY)
break;
- if (j < mod->nummodelsurfaces)
+ if (j < mod->submodelsurfaces_end)
mod->DrawSky = R_Mod_DrawSky;
- for (j = 0, surface = &mod->data_surfaces[mod->firstmodelsurface];j < mod->nummodelsurfaces;j++, surface++)
- if (surface->texture && surface->texture->basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
+ 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->nummodelsurfaces)
+ 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)
memset(stylecounts, 0, sizeof(stylecounts));
- for (k = 0;k < mod->nummodelsurfaces;k++)
- {
- surface = mod->data_surfaces + mod->firstmodelsurface + k;
+ for (k = mod->submodelsurfaces_start;k < mod->submodelsurfaces_end;k++)
for (j = 0;j < MAXLIGHTMAPS;j++)
- stylecounts[surface->lightmapinfo->styles[j]]++;
- }
+ stylecounts[mod->data_surfaces[k].lightmapinfo->styles[j]]++;
mod->brushq1.num_lightstyles = 0;
for (k = 0;k < 255;k++)
{
mod->brushq1.num_lightstyles++;
}
}
- for (k = 0;k < mod->nummodelsurfaces;k++)
+ for (k = mod->submodelsurfaces_start;k < mod->submodelsurfaces_end;k++)
{
- surface = mod->data_surfaces + mod->firstmodelsurface + k;
+ surface = mod->data_surfaces + k;
for (j = 0;j < MAXLIGHTMAPS;j++)
{
if (surface->lightmapinfo->styles[j] != 255)
{
int r = remapstyles[surface->lightmapinfo->styles[j]];
- styleinfo[r].surfacelist[styleinfo[r].numsurfaces++] = mod->firstmodelsurface + k;
+ styleinfo[r].surfacelist[styleinfo[r].numsurfaces++] = k;
}
}
}
//Mod_Q1BSP_ProcessLightList();
}
}
+ mod = loadmodel;
+
+ // make the model surface list (used by shadowing/lighting)
+ Mod_MakeSortedSurfaces(loadmodel);
Con_DPrintf("Stats for q1bsp model \"%s\": %i faces, %i nodes, %i leafs, %i visleafs, %i visleafportals, mesh: %i vertices, %i triangles, %i surfaces\n", loadmodel->name, loadmodel->num_surfaces, loadmodel->brush.num_nodes, loadmodel->brush.num_leafs, mod->brush.num_pvsclusters, loadmodel->brush.num_portals, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->num_surfaces);
}
}
}
datapointer = (unsigned char *)Mem_Alloc(mod->mempool, mod->num_surfaces * sizeof(int) + totalstyles * sizeof(model_brush_lightstyleinfo_t) + totalstylesurfaces * sizeof(int *));
+ mod->modelsurfaces_sorted = (int*)datapointer; datapointer += mod->num_surfaces * sizeof(int);
// set up the world model, then on each submodel copy from the world model
// and set up the submodel with the respective model info.
mod = loadmodel;
// we store the headnode (there's only one in Q2BSP) as if it were the first hull
mod->brushq1.hulls[0].firstclipnode = bm->headnode[0];
- mod->firstmodelsurface = bm->firstface;
- mod->nummodelsurfaces = bm->numfaces;
+ mod->submodelsurfaces_start = bm->firstface;
+ mod->submodelsurfaces_end = bm->firstface + bm->numfaces;
// set node/leaf parents for this submodel
// note: if the root of this submodel is a leaf (headnode[0] < 0) then there is nothing to do...
Mod_BSP_LoadNodes_RecursiveSetParent(rootnode, NULL);
// make the model surface list (used by shadowing/lighting)
- mod->sortedmodelsurfaces = (int *)datapointer;datapointer += mod->nummodelsurfaces * sizeof(int);
Mod_Q2BSP_FindSubmodelBrushRange_r(mod, rootnode, &firstbrush, &lastbrush);
if (firstbrush <= lastbrush)
{
mod->firstmodelbrush = 0;
mod->nummodelbrushes = 0;
}
- Mod_MakeSortedSurfaces(mod);
VectorCopy(bm->mins, mod->normalmins);
VectorCopy(bm->maxs, mod->normalmaxs);
// 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->nummodelsurfaces)
+ if (mod->submodelsurfaces_start < mod->submodelsurfaces_end)
{
- for (j = 0, surface = &mod->data_surfaces[mod->firstmodelsurface];j < mod->nummodelsurfaces;j++, surface++)
- if (surface->texture->basematerialflags & MATERIALFLAG_SKY)
+ 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->nummodelsurfaces)
+ if (j < mod->submodelsurfaces_end)
mod->DrawSky = R_Mod_DrawSky;
- for (j = 0, surface = &mod->data_surfaces[mod->firstmodelsurface];j < mod->nummodelsurfaces;j++, surface++)
- if (surface->texture->basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
+ 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->nummodelsurfaces)
+ 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)
memset(stylecounts, 0, sizeof(stylecounts));
- for (k = 0;k < mod->nummodelsurfaces;k++)
- {
- surface = mod->data_surfaces + mod->firstmodelsurface + k;
+ for (k = mod->submodelsurfaces_start;k < mod->submodelsurfaces_end;k++)
for (j = 0;j < MAXLIGHTMAPS;j++)
- stylecounts[surface->lightmapinfo->styles[j]]++;
- }
+ stylecounts[mod->data_surfaces[k].lightmapinfo->styles[j]]++;
mod->brushq1.num_lightstyles = 0;
for (k = 0;k < 255;k++)
{
mod->brushq1.num_lightstyles++;
}
}
- for (k = 0;k < mod->nummodelsurfaces;k++)
+ for (k = mod->submodelsurfaces_start;k < mod->submodelsurfaces_end;k++)
{
- surface = mod->data_surfaces + mod->firstmodelsurface + k;
+ surface = mod->data_surfaces + k;
for (j = 0;j < MAXLIGHTMAPS;j++)
{
if (surface->lightmapinfo->styles[j] != 255)
{
int r = remapstyles[surface->lightmapinfo->styles[j]];
- styleinfo[r].surfacelist[styleinfo[r].numsurfaces++] = mod->firstmodelsurface + k;
+ styleinfo[r].surfacelist[styleinfo[r].numsurfaces++] = k;
}
}
}
}
mod = loadmodel;
+ // make the model surface list (used by shadowing/lighting)
+ Mod_MakeSortedSurfaces(loadmodel);
+
Con_DPrintf("Stats for q2bsp model \"%s\": %i faces, %i nodes, %i leafs, %i clusters, %i clusterportals, mesh: %i vertices, %i triangles, %i surfaces\n", loadmodel->name, loadmodel->num_surfaces, loadmodel->brush.num_nodes, loadmodel->brush.num_leafs, mod->brush.num_pvsclusters, loadmodel->brush.num_portals, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->num_surfaces);
}
int triangleindex;
int bihleafindex;
int nummodelbrushes = model->nummodelbrushes;
- int nummodelsurfaces = model->nummodelsurfaces;
const int *e;
const int *collisionelement3i;
const float *collisionvertex3f;
bihnumleafs = 0;
if (userendersurfaces)
{
- for (j = 0, surface = model->data_surfaces + model->firstmodelsurface;j < nummodelsurfaces;j++, surface++)
- bihnumleafs += surface->num_triangles;
+ for (j = model->submodelsurfaces_start;j < model->submodelsurfaces_end;j++)
+ bihnumleafs += model->data_surfaces[j].num_triangles;
}
else
{
for (brushindex = 0, brush = model->brush.data_brushes + brushindex+model->firstmodelbrush;brushindex < nummodelbrushes;brushindex++, brush++)
if (brush->colbrushf)
bihnumleafs++;
- for (j = 0, surface = model->data_surfaces + model->firstmodelsurface;j < nummodelsurfaces;j++, surface++)
+ for (j = model->submodelsurfaces_start;j < model->submodelsurfaces_end;j++)
{
- if (surface->texture->basematerialflags & MATERIALFLAG_MESHCOLLISIONS)
- bihnumleafs += surface->num_triangles + surface->num_collisiontriangles;
+ if (model->data_surfaces[j].texture->basematerialflags & MATERIALFLAG_MESHCOLLISIONS)
+ bihnumleafs += model->data_surfaces[j].num_triangles + model->data_surfaces[j].num_collisiontriangles;
else
- bihnumleafs += surface->num_collisiontriangles;
+ bihnumleafs += model->data_surfaces[j].num_collisiontriangles;
}
}
// add render surfaces
renderelement3i = model->surfmesh.data_element3i;
rendervertex3f = model->surfmesh.data_vertex3f;
- for (j = 0, surface = model->data_surfaces + model->firstmodelsurface;j < nummodelsurfaces;j++, surface++)
+ for (j = model->submodelsurfaces_start; j < model->submodelsurfaces_end; j++)
{
+ surface = model->data_surfaces + j;
for (triangleindex = 0, e = renderelement3i + 3*surface->num_firsttriangle;triangleindex < surface->num_triangles;triangleindex++, e += 3)
{
if (!userendersurfaces && !(surface->texture->basematerialflags & MATERIALFLAG_MESHCOLLISIONS))
// add collision surfaces
collisionelement3i = model->brush.data_collisionelement3i;
collisionvertex3f = model->brush.data_collisionvertex3f;
- for (j = 0, surface = model->data_surfaces + model->firstmodelsurface;j < nummodelsurfaces;j++, surface++)
+ for (j = model->submodelsurfaces_start; j < model->submodelsurfaces_end; j++)
{
+ surface = model->data_surfaces + j;
for (triangleindex = 0, e = collisionelement3i + 3*surface->num_firstcollisiontriangle;triangleindex < surface->num_collisiontriangles;triangleindex++, e += 3)
{
bihleafs[bihleafindex].type = BIH_COLLISIONTRIANGLE;
loadmodel->brush.submodels[i] = mod;
// make the model surface list (used by shadowing/lighting)
- mod->firstmodelsurface = mod->brushq3.data_models[i].firstface;
- mod->nummodelsurfaces = mod->brushq3.data_models[i].numfaces;
+ mod->submodelsurfaces_start = mod->brushq3.data_models[i].firstface;
+ 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->sortedmodelsurfaces = (int *)Mem_Alloc(loadmodel->mempool, mod->nummodelsurfaces * sizeof(*mod->sortedmodelsurfaces));
- Mod_MakeSortedSurfaces(mod);
+ 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);
// outside the level - an unimportant concern)
//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 = 0;j < mod->nummodelsurfaces;j++)
+ for (j = mod->submodelsurfaces_start;j < mod->submodelsurfaces_end;j++)
{
- const msurface_t *surface = mod->data_surfaces + j + mod->firstmodelsurface;
+ const msurface_t *surface = mod->data_surfaces + j + mod->submodelsurfaces_start;
const float *v = mod->surfmesh.data_vertex3f + 3 * surface->num_firstvertex;
int k;
if (!surface->num_vertices)
mod->DrawSky = NULL;
mod->DrawAddWaterPlanes = NULL;
- for (j = 0;j < mod->nummodelsurfaces;j++)
- if (mod->data_surfaces[j + mod->firstmodelsurface].texture->basematerialflags & MATERIALFLAG_SKY)
+ 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->nummodelsurfaces)
+ if (j < mod->submodelsurfaces_end)
mod->DrawSky = R_Mod_DrawSky;
- for (j = 0;j < mod->nummodelsurfaces;j++)
- if (mod->data_surfaces[j + mod->firstmodelsurface].texture->basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
+ 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->nummodelsurfaces)
+ if (j < mod->submodelsurfaces_end)
mod->DrawAddWaterPlanes = R_Mod_DrawAddWaterPlanes;
Mod_MakeCollisionBIH(mod, false, &mod->collision_bih);
if (i == 0)
Mod_BuildVBOs();
}
+ mod = loadmodel;
+
+ // make the model surface list (used by shadowing/lighting)
+ Mod_MakeSortedSurfaces(loadmodel);
if (mod_q3bsp_sRGBlightmaps.integer)
{
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(model_t *));
loadmodel->brush.submodels = (model_t **)data;data += loadmodel->brush.numsubmodels * sizeof(model_t *);
- loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
+ loadmodel->modelsurfaces_sorted = (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->brush.data_pvsclusters = nobsp_pvs;
//if (loadmodel->num_nodes) loadmodel->data_nodes = (mnode_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_nodes * sizeof(mnode_t));
//loadmodel->data_leafsurfaces = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->num_leafsurfaces * sizeof(int));
- loadmodel->brush.data_leafsurfaces = loadmodel->sortedmodelsurfaces;
+ loadmodel->brush.data_leafsurfaces = loadmodel->modelsurfaces_sorted;
VectorCopy(loadmodel->normalmins, loadmodel->brush.data_leafs->mins);
VectorCopy(loadmodel->normalmaxs, loadmodel->brush.data_leafs->maxs);
loadmodel->brush.data_leafs->combinedsupercontents = 0; // FIXME?
loadmodel->brush.submodels[i] = mod;
// make the model surface list (used by shadowing/lighting)
- mod->firstmodelsurface = submodelfirstsurface[i];
- mod->nummodelsurfaces = submodelfirstsurface[i+1] - submodelfirstsurface[i];
+ mod->submodelsurfaces_start = submodelfirstsurface[i];
+ mod->submodelsurfaces_end = submodelfirstsurface[i+1];
mod->firstmodelbrush = 0;
mod->nummodelbrushes = 0;
- mod->sortedmodelsurfaces = loadmodel->sortedmodelsurfaces + mod->firstmodelsurface;
- Mod_MakeSortedSurfaces(mod);
VectorClear(mod->normalmins);
VectorClear(mod->normalmaxs);
l = false;
- for (j = 0;j < mod->nummodelsurfaces;j++)
+ for (j = mod->submodelsurfaces_start;j < mod->submodelsurfaces_end;j++)
{
- const msurface_t *surface = mod->data_surfaces + j + mod->firstmodelsurface;
+ const msurface_t *surface = mod->data_surfaces + j;
const float *v3f = mod->surfmesh.data_vertex3f + 3 * surface->num_firstvertex;
int k;
if (!surface->num_vertices)
mod->DrawSky = NULL;
mod->DrawAddWaterPlanes = NULL;
- for (j = 0;j < mod->nummodelsurfaces;j++)
- if (mod->data_surfaces[j + mod->firstmodelsurface].texture->basematerialflags & MATERIALFLAG_SKY)
+ for (j = mod->submodelsurfaces_start; j < mod->submodelsurfaces_end; j++)
+ if (mod->data_surfaces[j].texture->basematerialflags & MATERIALFLAG_SKY)
break;
- if (j < mod->nummodelsurfaces)
+ if (j < mod->submodelsurfaces_end)
mod->DrawSky = R_Mod_DrawSky;
- for (j = 0;j < mod->nummodelsurfaces;j++)
- if (mod->data_surfaces[j + mod->firstmodelsurface].texture->basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
+ 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->nummodelsurfaces)
+ if (j < mod->submodelsurfaces_end)
mod->DrawAddWaterPlanes = R_Mod_DrawAddWaterPlanes;
Mod_MakeCollisionBIH(mod, true, &mod->collision_bih);
mod = loadmodel;
Mem_Free(submodelfirstsurface);
+ // make the model surface list (used by shadowing/lighting)
+ Mod_MakeSortedSurfaces(loadmodel);
+
Con_DPrintf("Stats for obj model \"%s\": %i faces, %i nodes, %i leafs, %i clusters, %i clusterportals, mesh: %i vertices, %i triangles, %i surfaces\n", loadmodel->name, loadmodel->num_surfaces, loadmodel->brush.num_nodes, loadmodel->brush.num_leafs, mod->brush.num_pvsclusters, loadmodel->brush.num_portals, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->num_surfaces);
}
// make a single combined collision mesh for physics engine use
// TODO rewrite this to use the collision brushes as source, to fix issues with e.g. common/caulk which creates no drawsurface
numcollisionmeshtriangles = 0;
- for (k = 0;k < mod->nummodelsurfaces;k++)
+ for (k = mod->submodelsurfaces_start;k < mod->submodelsurfaces_end;k++)
{
- surface = mod->data_surfaces + mod->firstmodelsurface + k;
+ surface = mod->data_surfaces + k;
if (!strcmp(surface->texture->name, "collision") || !strcmp(surface->texture->name, "collisionconvex")) // found collision mesh
{
usesinglecollisionmesh = true;
Mod_ShadowMesh_AddMesh(mod->brush.collisionmesh, mod->surfmesh.data_vertex3f, surface->num_triangles, (mod->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
else
{
- for (k = 0;k < mod->nummodelsurfaces;k++)
+ for (k = mod->submodelsurfaces_start; k < mod->submodelsurfaces_end; k++)
{
- surface = mod->data_surfaces + mod->firstmodelsurface + k;
+ surface = mod->data_surfaces + k;
if (!(surface->texture->supercontents & SUPERCONTENTS_SOLID))
continue;
Mod_ShadowMesh_AddMesh(mod->brush.collisionmesh, mod->surfmesh.data_vertex3f, surface->num_triangles, (mod->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
*lastvertexpointer = lastvertex;
}
+typedef struct Mod_MakeSortedSurfaces_qsortsurface_s
+{
+ int submodel;
+ int surfaceindex;
+ q3deffect_t* effect;
+ texture_t* texture;
+ rtexture_t* lightmaptexture;
+}
+Mod_MakeSortedSurfaces_qsortsurface_t;
+
+int Mod_MakeSortedSurfaces_qsortfunc(const void *a, const void *b)
+{
+ 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)
+ return 1;
+ if (l->texture < r->texture)
+ return -1;
+ if (l->texture > r->texture)
+ return 1;
+ if (l->lightmaptexture < r->lightmaptexture)
+ return -1;
+ if (l->lightmaptexture > r->lightmaptexture)
+ return 1;
+ if (l->surfaceindex < r->surfaceindex)
+ return -1;
+ if (l->surfaceindex > r->surfaceindex)
+ return 1;
+ return 0;
+}
+
void Mod_MakeSortedSurfaces(model_t *mod)
{
// make an optimal set of texture-sorted batches to draw...
- int j, t;
- int *firstsurfacefortexture;
- int *numsurfacesfortexture;
- if (!mod->sortedmodelsurfaces)
- mod->sortedmodelsurfaces = (int *) Mem_Alloc(loadmodel->mempool, mod->nummodelsurfaces * sizeof(*mod->sortedmodelsurfaces));
- firstsurfacefortexture = (int *) Mem_Alloc(tempmempool, mod->num_textures * sizeof(*firstsurfacefortexture));
- numsurfacesfortexture = (int *) Mem_Alloc(tempmempool, mod->num_textures * sizeof(*numsurfacesfortexture));
- memset(numsurfacesfortexture, 0, mod->num_textures * sizeof(*numsurfacesfortexture));
- for (j = 0;j < mod->nummodelsurfaces;j++)
+ int j, k;
+ Mod_MakeSortedSurfaces_qsortsurface_t *info = (Mod_MakeSortedSurfaces_qsortsurface_t*)R_FrameData_Alloc(mod->num_surfaces * sizeof(*info));
+ if (!mod->modelsurfaces_sorted)
+ mod->modelsurfaces_sorted = (int *) Mem_Alloc(loadmodel->mempool, mod->num_surfaces * sizeof(*mod->modelsurfaces_sorted));
+ // 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++)
{
- const msurface_t *surface = mod->data_surfaces + j + mod->firstmodelsurface;
- if(!surface->texture)
- continue;
- t = (int)(surface->texture - mod->data_textures);
- numsurfacesfortexture[t]++;
+ 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;
}
- j = 0;
- for (t = 0;t < mod->num_textures;t++)
- {
- firstsurfacefortexture[t] = j;
- j += numsurfacesfortexture[t];
- }
- for (j = 0;j < mod->nummodelsurfaces;j++)
- {
- const msurface_t *surface = mod->data_surfaces + j + mod->firstmodelsurface;
- if (!surface->texture)
- continue;
- t = (int)(surface->texture - mod->data_textures);
- mod->sortedmodelsurfaces[firstsurfacefortexture[t]++] = j + mod->firstmodelsurface;
- }
- Mem_Free(firstsurfacefortexture);
- Mem_Free(numsurfacesfortexture);
+ 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);
+ for (j = 0; j < mod->num_surfaces; j++)
+ mod->modelsurfaces_sorted[j] = info[j].surfaceindex;
}
void Mod_BuildVBOs(void)
if (l > 0)
outbufferpos += l;
submodel = model->brush.numsubmodels ? model->brush.submodels[submodelindex] : model;
- for (surfaceindex = 0;surfaceindex < submodel->nummodelsurfaces;surfaceindex++)
+ for (surfaceindex = submodel->submodelsurfaces_start;surfaceindex < submodel->submodelsurfaces_end;surfaceindex++)
{
- surface = model->data_surfaces + submodel->sortedmodelsurfaces[surfaceindex];
+ surface = model->data_surfaces + surfaceindex;
l = dpsnprintf(outbuffer + outbufferpos, outbuffermax - outbufferpos, "usemtl %s\n", (surface->texture && surface->texture->name[0]) ? surface->texture->name : "default");
if (l > 0)
outbufferpos += l;
const int *element3i = model->surfmesh.data_element3i;
const int *e;
float v2[3][3];
- for (surfaceindex = 0, surface = model->data_surfaces;surfaceindex < model->nummodelsurfaces;surfaceindex++, surface++)
+ for (surfaceindex = model->submodelsurfaces_start;surfaceindex < model->submodelsurfaces_end;surfaceindex++)
{
+ surface = model->data_surfaces + surfaceindex;
if (!BoxesOverlap(surface->mins, surface->maxs, mins, maxs))
continue;
if (surface->texture->basematerialflags & MATERIALFLAG_NOSHADOW)
{
mod->max_surfaces = 2 * max(mod->num_surfaces, 64);
mod->data_surfaces = (msurface_t *)Mem_Realloc(mod->mempool, mod->data_surfaces, mod->max_surfaces * sizeof(*mod->data_surfaces));
- mod->sortedmodelsurfaces = (int *)Mem_Realloc(mod->mempool, mod->sortedmodelsurfaces, mod->max_surfaces * sizeof(*mod->sortedmodelsurfaces));
+ mod->modelsurfaces_sorted = (int *)Mem_Realloc(mod->mempool, mod->modelsurfaces_sorted, mod->max_surfaces * sizeof(*mod->modelsurfaces_sorted));
}
surf = mod->data_surfaces + mod->num_surfaces;
mod->num_surfaces++;
{
int i, j;
texture_t *tex;
- msurface_t *surf, *surf2;
+ unsigned char* included = R_FrameData_Alloc(mod->num_surfaces * sizeof(unsigned char));
// build the sorted surfaces list properly to reduce material setup
// this is easy because we're just sorting on texture and don't care about the order of textures
- mod->nummodelsurfaces = 0;
+ mod->submodelsurfaces_start = 0;
+ mod->submodelsurfaces_end = 0;
for (i = 0; i < mod->num_surfaces; i++)
- mod->data_surfaces[i].included = false;
+ included[i] = 0;
for (i = 0; i < mod->num_surfaces; i++)
{
- surf = mod->data_surfaces + i;
- if (surf->included)
+ if (included[i])
continue;
- tex = surf->texture;
+ tex = mod->data_surfaces[i].texture;
// j = i is intentional
for (j = i; j < mod->num_surfaces; j++)
{
- surf2 = mod->data_surfaces + j;
- if (surf2->included)
- continue;
- if (surf2->texture == tex)
+ if (!included[j] && mod->data_surfaces[j].texture == tex)
{
- surf2->included = true;
- mod->sortedmodelsurfaces[mod->nummodelsurfaces++] = j;
+ included[j] = 1;
+ mod->modelsurfaces_sorted[mod->submodelsurfaces_end++] = j;
}
}
}
msurface_lightmapinfo_t;
struct q3deffect_s;
+
+/// <summary>
+/// describes the textures to use on a range of triangles in the model, and mins/maxs (AABB) for culling.
+/// </summary>
typedef struct msurface_s
{
- // bounding box for onscreen checks
- vec3_t mins;
- vec3_t maxs;
- // the texture to use on the surface
+ /// range of triangles and vertices in model->surfmesh
+ int num_triangles; // triangles
+ int num_firsttriangle; // first element is this *3
+ int num_vertices; // length of the range referenced by elements
+ int num_firstvertex; // min vertex referenced by elements
+
+ /// the texture to use on the surface
texture_t *texture;
- // the lightmap texture fragment to use on the rendering mesh
+ /// the lightmap texture fragment to use on the rendering mesh
struct rtexture_s *lightmaptexture;
- // the lighting direction texture fragment to use on the rendering mesh
+ /// the lighting direction texture fragment to use on the rendering mesh
struct rtexture_s *deluxemaptexture;
- // lightmaptexture rebuild information not used in q3bsp
- msurface_lightmapinfo_t *lightmapinfo; // q1bsp
- // fog volume info in q3bsp
- struct q3deffect_s *effect; // q3bsp
- // mesh information for collisions (only used by q3bsp curves)
- int num_firstcollisiontriangle;
-
- // surfaces own ranges of vertices and triangles in the model->surfmesh
- int num_triangles; // number of triangles
- int num_firsttriangle; // first triangle
- int num_vertices; // number of vertices
- int num_firstvertex; // first vertex
-
- // mesh information for collisions (only used by q3bsp curves)
- int num_collisiontriangles; // q3bsp
- int num_collisionvertices; // q3bsp
-
- // used by Mod_Mesh_Finalize when building sortedmodelsurfaces
- qbool included;
+
+ // the following fields are used situationally and are not part of rendering in typical usage
+
+ /// bounding box for onscreen checks
+ vec3_t mins;
+ vec3_t maxs;
+
+ /// lightmaptexture rebuild information not used in q3bsp
+ msurface_lightmapinfo_t* lightmapinfo; // q1bsp
+ /// fog volume info in q3bsp
+ struct q3deffect_s* effect; // q3bsp
+
+ /// mesh information for collisions (only used by q3bsp curves)
+ int num_firstcollisiontriangle; // q3bsp only
+ int num_collisiontriangles; // number of triangles (if surface has collisions enabled)
+ int num_collisionvertices; // number of vertices referenced by collision triangles (if surface has collisions enabled)
}
msurface_t;
animscene_t *skinscenes; // [numskins]
// skin animation info
animscene_t *animscenes; // [numframes]
- // range of surface numbers in this (sub)model
- int firstmodelsurface;
- int nummodelsurfaces;
- int *sortedmodelsurfaces;
+ // range of surface numbers in this model
+ int submodelsurfaces_start;
+ int submodelsurfaces_end;
+ /// surface indices of model in an optimal draw order (submodelindex -> texture -> lightmap -> index)
+ int *modelsurfaces_sorted; // same size as num_surfaces
// range of collision brush numbers in this (sub)model
int firstmodelbrush;
int nummodelbrushes;
static msurface_t *getsurface(model_t *model, int surfacenum)
{
- if (surfacenum < 0 || surfacenum >= model->nummodelsurfaces)
+ if (surfacenum < 0 || surfacenum >= model->submodelsurfaces_end - model->submodelsurfaces_start)
return NULL;
- return model->data_surfaces + surfacenum + model->firstmodelsurface;
+ return model->data_surfaces + surfacenum + model->submodelsurfaces_start;
}
applytransform_inverted(prog, point, ed, p);
best = -1;
bestdist = 1000000000;
- for (surfacenum = 0;surfacenum < model->nummodelsurfaces;surfacenum++)
+ for (surfacenum = model->submodelsurfaces_start;surfacenum < model->submodelsurfaces_end;surfacenum++)
{
- surface = model->data_surfaces + surfacenum + model->firstmodelsurface;
+ surface = model->data_surfaces + surfacenum;
// first see if the nearest point on the surface's box is closer than the previous match
clipped[0] = bound(surface->mins[0], p[0], surface->maxs[0]) - p[0];
clipped[1] = bound(surface->mins[1], p[1], surface->maxs[1]) - p[1];
if (dist < bestdist)
{
// that's closer too, store it as the best match
- best = surfacenum;
+ best = surfacenum - model->submodelsurfaces_start;
bestdist = dist;
}
}
relativeshadowmaxs[0] = relativeshadoworigin[0] + relativeshadowradius;
relativeshadowmaxs[1] = relativeshadoworigin[1] + relativeshadowradius;
relativeshadowmaxs[2] = relativeshadoworigin[2] + relativeshadowradius;
- ent->model->DrawShadowMap(r_shadow_shadowmapside, ent, relativeshadoworigin, NULL, relativeshadowradius, ent->model->nummodelsurfaces, ent->model->sortedmodelsurfaces, NULL, relativeshadowmins, relativeshadowmaxs);
+ ent->model->DrawShadowMap(r_shadow_shadowmapside, ent, relativeshadoworigin, NULL, relativeshadowradius, ent->model->submodelsurfaces_end - ent->model->submodelsurfaces_start, ent->model->modelsurfaces_sorted + ent->model->submodelsurfaces_start, NULL, relativeshadowmins, relativeshadowmaxs);
rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
}
R_Shadow_SetupEntityLight(ent);
- model->DrawLight(ent, model->nummodelsurfaces, model->sortedmodelsurfaces, NULL);
+ model->DrawLight(ent, model->submodelsurfaces_end - model->submodelsurfaces_start, model->modelsurfaces_sorted + model->submodelsurfaces_start, NULL);
rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
}
relativeshadowmaxs[1] = relativelightorigin[1] + r_shadows_throwdistance.value * fabs(relativelightdirection[1]) + radius * (fabs(relativeforward[1]) + fabs(relativeright[1]));
relativeshadowmaxs[2] = relativelightorigin[2] + r_shadows_throwdistance.value * fabs(relativelightdirection[2]) + radius * (fabs(relativeforward[2]) + fabs(relativeright[2]));
RSurf_ActiveModelEntity(ent, false, false, false);
- ent->model->DrawShadowMap(0, ent, relativelightorigin, relativelightdirection, relativethrowdistance, ent->model->nummodelsurfaces, ent->model->sortedmodelsurfaces, NULL, relativeshadowmins, relativeshadowmaxs);
+ ent->model->DrawShadowMap(0, ent, relativelightorigin, relativelightdirection, relativethrowdistance, ent->model->submodelsurfaces_end - ent->model->submodelsurfaces_start, ent->model->modelsurfaces_sorted + ent->model->submodelsurfaces_start, NULL, relativeshadowmins, relativeshadowmaxs);
rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
}
// check if trimesh can be defined with convex
convex_compatible = false;
- for (i = 0;i < model->nummodelsurfaces;i++)
+ for (i = model->submodelsurfaces_start;i < model->submodelsurfaces_end;i++)
{
- if (!strcmp(((msurface_t *)(model->data_surfaces + model->firstmodelsurface + i))->texture->name, "collisionconvex"))
+ if (!strcmp(model->data_surfaces[i].texture->name, "collisionconvex"))
{
convex_compatible = true;
break;