Clipping cleanups.

Calculate radius for alias models as well as brush.
Culling is no longer optional on alias models (was only ever disabled for viewmodel, which is a lot of extra effort to avoid clip testing 1 thing out of hundreds).
Clip QSG2 scaled alias models with a scaled bbox.
This commit is contained in:
Ragnvald Maartmann-Moe IV 2002-08-20 00:48:59 +00:00
parent e9febea31c
commit 32a85e7130
8 changed files with 138 additions and 130 deletions

View File

@ -143,12 +143,27 @@ extern inline
qboolean
R_CullBox (const vec3_t mins, const vec3_t maxs)
{
int i;
int i;
for (i=0 ; i<4 ; i++)
for (i=0 ; i < 4 ; i++)
if (BoxOnPlaneSide (mins, maxs, &frustum[i]) == 2)
return true;
return false;
}
extern inline qboolean
R_CullSphere (const vec3_t origin, const float radius)
{
int i;
float r;
for (i = 0; i < 4; i++)
{
r = DotProduct (origin, frustum[i].normal) - frustum[i].dist;
if (r <= -radius)
return true;
}
return false;
}
#endif // __mathlib_h

View File

@ -252,7 +252,7 @@ typedef struct
// ALIAS MODELS ===============================================================
// Alias models are position independent, so the cache manager can move them.
/* NOTE: the first three lines must match maliasgroupframedesc_t */
// NOTE: the first three lines must match maliasgroupframedesc_t
typedef struct
{
trivertx_t bboxmin;
@ -312,7 +312,7 @@ typedef struct {
int numposes;
int poseverts;
int posedata; // numposes*poseverts trivert_t
int posedata; // numposes * poseverts trivert_t
int commands; // gl command list with embedded s/t
unsigned short crc;
@ -328,7 +328,7 @@ extern trivertx_t *poseverts[MAXALIASFRAMES];
extern int aliasbboxmins[3];
extern int aliasbboxmaxs[3];
// Whole model =======================================================
// Whole model ================================================================
typedef enum {mod_brush, mod_sprite, mod_alias} modtype_t;
@ -344,84 +344,86 @@ typedef enum {mod_brush, mod_sprite, mod_alias} modtype_t;
typedef struct model_s
{
char name[MAX_QPATH];
qboolean needload; // bmodels and sprites don't cache normally
qboolean hasfullbrights;
char name[MAX_QPATH];
qboolean needload; // bmodels and sprites don't cache normally
qboolean hasfullbrights;
modtype_t type;
int numframes;
synctype_t synctype;
int flags;
modtype_t type;
int numframes;
synctype_t synctype;
int flags;
// lighting info
float min_light;
byte shadow_alpha; // 255 = 1.0
byte fullbright;
float min_light;
byte shadow_alpha; // 255 = 1.0
byte fullbright;
// volume occupied by the model graphics
vec3_t mins, maxs;
float radius;
// coarse cull, for fine culling, axis-aligned bbox isn't good enough
float radius;
// FIXME: bbox cruft has to stay until sw rendering gets updated
vec3_t mins, maxs;
// solid volume for clipping
qboolean clipbox;
vec3_t clipmins, clipmaxs;
// solid volume for clipping
qboolean clipbox;
vec3_t clipmins, clipmaxs;
// brush model
int firstmodelsurface, nummodelsurfaces;
int firstmodelsurface, nummodelsurfaces;
int numsubmodels;
int numsubmodels;
dmodel_t *submodels;
int numplanes;
int numplanes;
mplane_t *planes;
int numleafs; // number of visible leafs, not counting 0
int numleafs; // number of visible leafs, not counting 0
mleaf_t *leafs;
int numvertexes;
int numvertexes;
mvertex_t *vertexes;
int numedges;
int numedges;
medge_t *edges;
int numnodes;
int numnodes;
mnode_t *nodes;
int numtexinfo;
int numtexinfo;
mtexinfo_t *texinfo;
int numsurfaces;
int numsurfaces;
msurface_t *surfaces;
int numsurfedges;
int numsurfedges;
int *surfedges;
int numclipnodes;
int numclipnodes;
dclipnode_t *clipnodes;
int nummarksurfaces;
int nummarksurfaces;
msurface_t **marksurfaces;
hull_t hulls[MAX_MAP_HULLS];
hull_t hulls[MAX_MAP_HULLS];
int numtextures;
int numtextures;
texture_t **textures;
byte *visdata;
byte *lightdata;
char *entities;
unsigned int checksum;
unsigned int checksum2;
unsigned int checksum;
unsigned int checksum2;
// additional model data
cache_user_t cache; // only access through Mod_Extradata
cache_user_t cache; // only access through Mod_Extradata
} model_t;
// ============================================================================
extern float RadiusFromBounds (const vec3_t mins, const vec3_t maxs);
void Mod_Init (void);
void Mod_Init_Cvars (void);
void Mod_ClearAll (void);

View File

@ -47,11 +47,10 @@ static const char rcsid[] =
#include "QF/sys.h"
#include "QF/vfs.h"
#include "compat.h"
#include "d_iface.h"
#include "r_local.h"
#include "compat.h"
aliashdr_t *pheader;
stvert_t *stverts;
@ -69,15 +68,13 @@ int aliasbboxmins[3], aliasbboxmaxs[3];
void *
Mod_LoadAllSkins (int numskins, daliasskintype_t *pskintype, int *pskinindex)
{
int snum, gnum, t;
int skinsize;
byte *skin;
int groupskins;
float *poutskinintervals;
int groupskins, skinsize, gnum, snum, t;
daliasskingroup_t *pinskingroup;
daliasskininterval_t *pinskinintervals;
maliasskindesc_t *pskindesc;
maliasskingroup_t *paliasskingroup;
float *poutskinintervals;
if (numskins < 1 || numskins > MAX_SKINS)
Sys_Error ("Mod_LoadAliasModel: Invalid # of skins: %d", numskins);
@ -137,17 +134,13 @@ Mod_LoadAllSkins (int numskins, daliasskintype_t *pskintype, int *pskinindex)
void
Mod_LoadAliasModel (model_t *mod, void *buffer, cache_allocator_t allocator)
{
int i, j;
byte *p;
int i, j, len, size, version, numframes, start, end, total;
mdl_t *pinmodel, *pmodel;
stvert_t *pinstverts;
dtriangle_t *pintriangles;
int version, numframes;
int size;
daliasframetype_t *pframetype;
daliasskintype_t *pskintype;
int start, end, total;
byte *p;
int len;
unsigned short crc;
void *mem;
@ -197,8 +190,7 @@ Mod_LoadAliasModel (model_t *mod, void *buffer, cache_allocator_t allocator)
if (pmodel->numverts <= 0)
Sys_Error ("model %s has no vertices", mod->name);
if (pmodel->numverts > stverts_size)
{
if (pmodel->numverts > stverts_size) {
stverts = realloc (stverts, pmodel->numverts * sizeof (stvert_t));
if (!stverts)
Sys_Error ("model_alias: out of memory");
@ -210,9 +202,9 @@ Mod_LoadAliasModel (model_t *mod, void *buffer, cache_allocator_t allocator)
if (pmodel->numtris <= 0)
Sys_Error ("model %s has no triangles", mod->name);
if (pmodel->numtris > triangles_size)
{
triangles = realloc (triangles, pmodel->numtris * sizeof (mtriangle_t));
if (pmodel->numtris > triangles_size) {
triangles =
realloc (triangles, pmodel->numtris * sizeof (mtriangle_t));
if (!triangles)
Sys_Error ("model_alias: out of memory");
triangles_size = pmodel->numtris;
@ -235,8 +227,8 @@ Mod_LoadAliasModel (model_t *mod, void *buffer, cache_allocator_t allocator)
// load the skins
pskintype = (daliasskintype_t *) &pinmodel[1];
pskintype =
Mod_LoadAllSkins (pheader->mdl.numskins, pskintype, &pheader->skindesc);
pskintype = Mod_LoadAllSkins (pheader->mdl.numskins, pskintype,
&pheader->skindesc);
// load base s and t vertices
pinstverts = (stvert_t *) pskintype;
@ -293,6 +285,8 @@ Mod_LoadAliasModel (model_t *mod, void *buffer, cache_allocator_t allocator)
pheader->mdl.scale_origin[i];
}
mod->radius = RadiusFromBounds (mod->mins, mod->maxs);
// build the draw lists
Mod_MakeAliasModelDisplayLists (mod, pheader, buffer, com_filesize, extra);

View File

@ -131,9 +131,7 @@ Mod_LeafPVS (mleaf_t *leaf, model_t *model)
return Mod_DecompressVis (leaf->compressed_vis, model);
}
/*
BRUSHMODEL LOADING
*/
// BRUSHMODEL LOADING =========================================================
byte *mod_base;
@ -467,7 +465,8 @@ CalcSurfaceExtents (msurface_t *s)
s->texturemins[i] = bmins[i] * 16;
s->extents[i] = (bmaxs[i] - bmins[i]) * 16;
if (!(tex->flags & TEX_SPECIAL) && s->extents[i] > 512 /* 256 */ )
Sys_Error ("Bad surface extents: %x %d", tex->flags, s->extents[i]);
Sys_Error ("Bad surface extents: %x %d", tex->flags,
s->extents[i]);
}
}
@ -595,8 +594,6 @@ Mod_LoadLeafs (lump_t *l)
dleaf_t *in;
mleaf_t *out;
int i, j, count, p;
// char s[80];
qboolean isnotmap = true;
in = (void *) (mod_base + l->fileofs);
@ -607,8 +604,8 @@ Mod_LoadLeafs (lump_t *l)
loadmodel->leafs = out;
loadmodel->numleafs = count;
// snprintf(s, sizeof (s), "maps/%s.bsp",
// Info_ValueForKey(cl.serverinfo,"map"));
// snprintf(s, sizeof (s), "maps/%s.bsp",
// Info_ValueForKey(cl.serverinfo,"map"));
if (!strncmp ("maps/", loadmodel->name, 5))
isnotmap = false;
for (i = 0; i < count; i++, in++, out++) {
@ -782,11 +779,9 @@ Mod_LoadSurfedges (lump_t *l)
void
Mod_LoadPlanes (lump_t *l)
{
int i, j;
int i, j, bits, count;
mplane_t *out;
dplane_t *in;
int count;
int bits;
in = (void *) (mod_base + l->fileofs);
if (l->filelen % sizeof (*in))
@ -811,19 +806,6 @@ Mod_LoadPlanes (lump_t *l)
}
}
float
RadiusFromBounds (const vec3_t mins, const vec3_t maxs)
{
int i;
vec3_t corner;
for (i = 0; i < 3; i++) {
corner[i] = max (fabs (mins[i]), fabs (maxs[i]));
}
return Length (corner);
}
void
Mod_LoadBrushModel (model_t *mod, void *buffer)
{
@ -837,15 +819,13 @@ Mod_LoadBrushModel (model_t *mod, void *buffer)
i = LittleLong (header->version);
if (i != BSPVERSION)
Sys_Error
("Mod_LoadBrushModel: %s has wrong version number (%i should be %i)",
mod->name, i, BSPVERSION);
Sys_Error ("Mod_LoadBrushModel: %s has wrong version number (%i "
"should be %i)", mod->name, i, BSPVERSION);
// swap all the lumps
mod_base = (byte *) header;
for (i = 0; i < sizeof (dheader_t) / 4; i++)
((int *) header)[i] = LittleLong (((int *) header)[i]);
// checksum all of the map, except for entities
@ -855,17 +835,15 @@ Mod_LoadBrushModel (model_t *mod, void *buffer)
for (i = 0; i < HEADER_LUMPS; i++) {
if (i == LUMP_ENTITIES)
continue;
mod->checksum ^=
LittleLong (Com_BlockChecksum
(mod_base + header->lumps[i].fileofs,
header->lumps[i].filelen));
mod->checksum ^= LittleLong (Com_BlockChecksum
(mod_base + header->lumps[i].fileofs,
header->lumps[i].filelen));
if (i == LUMP_VISIBILITY || i == LUMP_LEAFS || i == LUMP_NODES)
continue;
mod->checksum2 ^=
LittleLong (Com_BlockChecksum
(mod_base + header->lumps[i].fileofs,
header->lumps[i].filelen));
mod->checksum2 ^= LittleLong (Com_BlockChecksum
(mod_base + header->lumps[i].fileofs,
header->lumps[i].filelen));
}
// load into heap

View File

@ -63,13 +63,12 @@ char loadname[32]; // for hunk tags
model_t mod_known[MAX_MOD_KNOWN];
int mod_numknown;
texture_t *r_notexture_mip;
cvar_t *gl_subdivide_size;
cvar_t *gl_mesh_cache;
texture_t *r_notexture_mip;
void
Mod_Init (void)
{
@ -81,8 +80,7 @@ Mod_Init (void)
int mip3size = 2*2;
memset (mod_novis, 0xff, sizeof (mod_novis));
r_notexture_mip = Hunk_AllocName (sizeof (texture_t)
+ mip0size + mip1size
r_notexture_mip = Hunk_AllocName (sizeof (texture_t) + mip0size + mip1size
+ mip2size + mip3size, "notexture");
r_notexture_mip->width = r_notexture_mip->height = 16;
@ -289,3 +287,14 @@ Mod_Print (void)
Sys_Printf ("%8p : %s\n", mod->cache.data, mod->name);
}
}
float
RadiusFromBounds (const vec3_t mins, const vec3_t maxs)
{
int i;
vec3_t corner;
for (i = 0; i < 3; i++)
corner[i] = max (fabs (mins[i]), fabs (maxs[i]));
return Length (corner);
}

View File

@ -244,10 +244,10 @@ GL_DrawAliasShadow (aliashdr_t *paliashdr, vert_order_t *vo)
paliashdr->mdl.scale_origin[1];
point[2] =
verts->vert[2] * paliashdr->mdl.scale[2] +
paliashdr->mdl.scale_origin[2];
paliashdr->mdl.scale_origin[2] + lheight;
point[0] -= shadevector[0] * (point[2] + lheight);
point[1] -= shadevector[1] * (point[2] + lheight);
point[0] -= shadevector[0] * point[2];
point[1] -= shadevector[1] * point[2];
point[2] = height;
qfglVertex3fv (point);
@ -282,7 +282,7 @@ GL_GetAliasFrameVerts16 (int frame, aliashdr_t *paliashdr, entity_t *e)
count = paliashdr->poseverts;
vo = Hunk_TempAlloc (sizeof (*vo) + count * sizeof (blended_vert_t));
vo->order = (int *) ((byte *) paliashdr + paliashdr->commands);
vo->verts = (blended_vert_t*)&vo[1];
vo->verts = (blended_vert_t *) &vo[1];
if (numposes > 1) {
interval = paliashdr->frames[frame].interval;
@ -336,6 +336,7 @@ GL_GetAliasFrameVerts16 (int frame, aliashdr_t *paliashdr, entity_t *e)
i++, vo_v++, verts1++, verts2++) {
float *n1, *n2;
float d1, d2;
VectorBlend (v1, v2, blend, vo_v->vert);
VectorScale (vo_v->vert, 1.0 / 256.0, vo_v->vert);
n1 = r_avertexnormals[verts1->lightnormalindex];
@ -356,7 +357,7 @@ GL_GetAliasFrameVerts16 (int frame, aliashdr_t *paliashdr, entity_t *e)
VectorScale (verts->v, 1.0 / 256.0, vo_v->vert);
n = r_avertexnormals[verts->lightnormalindex];
d = DotProduct (shadevector, n);
vo_v->lightdot = max (0, d);
vo_v->lightdot = max (0.0, d);
}
return vo;
}
@ -385,7 +386,7 @@ GL_GetAliasFrameVerts (int frame, aliashdr_t *paliashdr, entity_t *e)
count = paliashdr->poseverts;
vo = Hunk_TempAlloc (sizeof (*vo) + count * sizeof (blended_vert_t));
vo->order = (int *) ((byte *) paliashdr + paliashdr->commands);
vo->verts = (blended_vert_t*)&vo[1];
vo->verts = (blended_vert_t *) &vo[1];
if (numposes > 1) {
interval = paliashdr->frames[frame].interval;
@ -458,7 +459,7 @@ GL_GetAliasFrameVerts (int frame, aliashdr_t *paliashdr, entity_t *e)
VectorCopy (verts->v, vo_v->vert);
n = r_avertexnormals[verts->lightnormalindex];
d = DotProduct (shadevector, n);
vo_v->lightdot = max (0, d);
vo_v->lightdot = max (0.0, d);
}
return vo;
}
@ -506,7 +507,7 @@ R_AliasGetSkindesc (int skinnum, aliashdr_t *ahdr)
}
void
R_DrawAliasModel (entity_t *e, qboolean cull)
R_DrawAliasModel (entity_t *e)
{
float add, an, minshade, shade;
int lnum, i, texture;
@ -521,7 +522,13 @@ R_DrawAliasModel (entity_t *e, qboolean cull)
VectorAdd (e->origin, model->mins, mins);
VectorAdd (e->origin, model->maxs, maxs);
if (cull && R_CullBox (mins, maxs))
if (e->scale != 1.0) {
VectorScale (mins, e->scale, mins);
VectorScale (maxs, e->scale, maxs);
// radius = radius * scale;
}
if (R_CullBox (mins, maxs))
return;
VectorSubtract (r_origin, e->origin, modelorg);
@ -537,14 +544,15 @@ R_DrawAliasModel (entity_t *e, qboolean cull)
for (lnum = 0; lnum < r_maxdlights; lnum++) {
if (r_dlights[lnum].die >= r_realtime) {
float d;
float d;
VectorSubtract (e->origin, r_dlights[lnum].origin, dist);
d = DotProduct (dist, dist);
d = max (d, 64) * 200;
add = r_dlights[lnum].radius * r_dlights[lnum].radius * 8 / d;
d = max (d, 64.0) * 200.0;
add = r_dlights[lnum].radius * r_dlights[lnum].radius * 8.0 /
d;
if (add > 0)
if (add > 0.0)
VectorMA (ambientcolor, add, r_dlights[lnum].color,
ambientcolor);
}
@ -552,7 +560,7 @@ R_DrawAliasModel (entity_t *e, qboolean cull)
// clamp lighting so it doesn't overbright as much
for (i = 0; i < 3; i++) {
ambientcolor[i] = min (ambientcolor[i], 128/200.0);
ambientcolor[i] = min (ambientcolor[i], 128.0 / 200.0);
if (ambientcolor[i] + shadecolor[i] > 1)
shadecolor[i] = 1 - ambientcolor[i];
}
@ -565,10 +573,10 @@ R_DrawAliasModel (entity_t *e, qboolean cull)
shadecolor[2] += minshade - shade;
}
an = e->angles[1] * (M_PI / 180);
an = e->angles[1] * (M_PI / 180.0);
shadevector[0] = cos (-an);
shadevector[1] = sin (-an);
shadevector[2] = 1;
shadevector[2] = 1.0;
VectorNormalize (shadevector);
}
@ -577,6 +585,7 @@ R_DrawAliasModel (entity_t *e, qboolean cull)
// locate the proper data
paliashdr = Cache_Get (&e->model->cache);
c_alias_polys += paliashdr->mdl.numtris;
VectorScale (paliashdr->mdl.scale, e->scale, scale);
// draw all the triangles
qfglPushMatrix ();
@ -585,7 +594,6 @@ R_DrawAliasModel (entity_t *e, qboolean cull)
qfglTranslatef (paliashdr->mdl.scale_origin[0],
paliashdr->mdl.scale_origin[1],
paliashdr->mdl.scale_origin[2]);
VectorScale (paliashdr->mdl.scale, e->scale, scale)
qfglScalef (scale[0], scale[1], scale[2]);
// if the model has a colorised/external skin, use it, otherwise use
@ -655,7 +663,7 @@ R_DrawAliasModel (entity_t *e, qboolean cull)
qfglDisable (GL_TEXTURE_2D);
qfglDepthMask (GL_FALSE);
color_black[3] = modelalpha * ((model->shadow_alpha + 1) / 2);
color_black[3] = modelalpha * model->shadow_alpha;
qfglColor4ubv (color_black);
GL_DrawAliasShadow (paliashdr, vo);

View File

@ -103,7 +103,7 @@ float modelalpha; // Ender (Extend) Alpha
void R_MarkLeaves (void);
void R_DrawAliasModel (entity_t *e, qboolean cull);
void R_DrawAliasModel (entity_t *e);
void R_DrawSpriteModel (entity_t *e);
@ -193,7 +193,7 @@ R_DrawEntitiesOnList (void)
if (currententity == r_player_entity)
currententity->angles[PITCH] *= 0.3;
R_DrawAliasModel (currententity, true);
R_DrawAliasModel (currententity);
}
if (gl_affinemodels->int_val)
qfglHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_DONT_CARE);
@ -225,7 +225,7 @@ R_DrawViewModel (void)
qfglDepthRange (gldepthmin, gldepthmin + 0.3 * (gldepthmax - gldepthmin));
if (gl_affinemodels->int_val)
qfglHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
R_DrawAliasModel (currententity, false);
R_DrawAliasModel (currententity);
if (gl_affinemodels->int_val)
qfglHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_DONT_CARE);
qfglDepthRange (gldepthmin, gldepthmax);

View File

@ -272,30 +272,31 @@ R_DrawBrushModel (entity_t *e)
float dot;
float color[4];
int i, k;
model_t *clmodel;
model_t *model;
mplane_t *pplane;
msurface_t *psurf;
qboolean rotated;
vec3_t mins, maxs;
clmodel = e->model;
model = e->model;
if (e->angles[0] || e->angles[1] || e->angles[2]) {
rotated = true;
for (i = 0; i < 3; i++) {
mins[i] = e->origin[i] - clmodel->radius;
maxs[i] = e->origin[i] + clmodel->radius;
mins[i] = e->origin[i] - model->radius;
maxs[i] = e->origin[i] + model->radius;
}
} else {
rotated = false;
VectorAdd (e->origin, clmodel->mins, mins);
VectorAdd (e->origin, clmodel->maxs, maxs);
VectorAdd (e->origin, model->mins, mins);
VectorAdd (e->origin, model->maxs, maxs);
}
#if 0 // QSG FIXME
if (e->scale != 1.0) {
VectorScale (mins, e->scale, mins);
VectorScale (maxs, e->scale, maxs);
radius = model->radius * e->scale;
}
#endif
@ -320,10 +321,10 @@ R_DrawBrushModel (entity_t *e)
modelorg[2] = DotProduct (temp, up);
}
psurf = &clmodel->surfaces[clmodel->firstmodelsurface];
psurf = &model->surfaces[model->firstmodelsurface];
// calculate dynamic lighting for bmodel if it's not an instanced model
if (clmodel->firstmodelsurface != 0 && r_dlight_lightmap->int_val) {
if (model->firstmodelsurface != 0 && r_dlight_lightmap->int_val) {
vec3_t lightorigin;
for (k = 0; k < r_maxdlights; k++) {
@ -332,7 +333,7 @@ R_DrawBrushModel (entity_t *e)
VectorSubtract (r_dlights[k].origin, e->origin, lightorigin);
R_RecursiveMarkLights (lightorigin, &r_dlights[k], 1 << k,
clmodel->nodes + clmodel->hulls[0].firstclipnode);
model->nodes + model->hulls[0].firstclipnode);
}
}
@ -342,7 +343,7 @@ R_DrawBrushModel (entity_t *e)
e->angles[0] = -e->angles[0]; // stupid quake bug
// draw texture
for (i = 0; i < clmodel->nummodelsurfaces; i++, psurf++) {
for (i = 0; i < model->nummodelsurfaces; i++, psurf++) {
// find which side of the node we are on
pplane = psurf->plane;
@ -413,6 +414,7 @@ R_RecursiveWorldNode (mnode_t *node)
return;
if (node->visframe != r_visframecount)
return;
if (R_CullBox (node->minmaxs, node->minmaxs + 3))
return;