summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAndrey Nazarov <skuller@skuller.net>2013-03-16 19:19:00 +0400
committerAndrey Nazarov <skuller@skuller.net>2013-03-20 22:04:53 +0400
commit579a26b4dfb7172bc29d9b853f335af310eb114c (patch)
treee839b21a3a3b1f7a1b0ad99e73c77d4c16b95d7e /src
parentf53832714d549a908a83b3528ea385197306b522 (diff)
Clean up and sanitize alias model drawing.
Validate texture coordinates. Validate vertex normal indices. Check that skin upload width/height matches model. Draw alias models in solid white color when skin is missing or found to be invalid.
Diffstat (limited to 'src')
-rw-r--r--src/refresh/sw/alias.c64
-rw-r--r--src/refresh/sw/model.c27
-rw-r--r--src/refresh/sw/polyset.c24
-rw-r--r--src/refresh/sw/sw.h6
4 files changed, 54 insertions, 67 deletions
diff --git a/src/refresh/sw/alias.c b/src/refresh/sw/alias.c
index 46ee64c..0970f6d 100644
--- a/src/refresh/sw/alias.c
+++ b/src/refresh/sw/alias.c
@@ -437,7 +437,7 @@ static void R_AliasSetUpTransform(void)
R_AliasSetupSkin
===============
*/
-static qboolean R_AliasSetupSkin(void)
+static void R_AliasSetupSkin(void)
{
int skinnum;
image_t *pskindesc;
@@ -451,20 +451,21 @@ static qboolean R_AliasSetupSkin(void)
currentmodel->name, skinnum);
skinnum = 0;
}
-
pskindesc = currentmodel->skins[skinnum];
}
- if (!pskindesc)
- return qfalse;
-
- r_affinetridesc.pskin = pskindesc->pixels[0];
- r_affinetridesc.skinwidth = pskindesc->width * TEX_BYTES;
- r_affinetridesc.skinheight = pskindesc->height;
-
- R_PolysetUpdateTables(); // FIXME: precalc edge lookups
+ if (pskindesc == NULL ||
+ pskindesc->upload_width != currentmodel->skinwidth ||
+ pskindesc->upload_height != currentmodel->skinheight) {
+ Com_DPrintf("R_AliasSetupSkin %s: bad skin %p\n",
+ currentmodel->name, pskindesc);
+ memset(&r_affinetridesc, 0, sizeof(r_affinetridesc));
+ return;
+ }
- return qtrue;
+ r_affinetridesc.pskin = pskindesc->pixels[0];
+ r_affinetridesc.skinwidth = pskindesc->upload_width * TEX_BYTES;
+ r_affinetridesc.skinheight = pskindesc->upload_height;
}
@@ -600,14 +601,19 @@ static void R_AliasSetupBlend(void)
int mask;
color_t color;
- r_alias_alpha = 255 * currententity->alpha;
- r_alias_one_minus_alpha = 255 - r_alias_alpha;
+ if (currententity->flags & RF_TRANSLUCENT) {
+ r_alias_alpha = 255 * currententity->alpha;
+ r_alias_one_minus_alpha = 255 - r_alias_alpha;
+ } else {
+ r_alias_alpha = 255;
+ r_alias_one_minus_alpha = 0;
+ }
/*
** select the proper span routine based on translucency
*/
mask = currententity->flags & RF_SHELL_MASK;
- if (mask) {
+ if (mask || r_affinetridesc.pskin == NULL) {
if (mask == RF_SHELL_RED)
color.u32 = d_8to24table[SHELL_RED_COLOR];
else if (mask == RF_SHELL_GREEN)
@@ -620,9 +626,9 @@ static void R_AliasSetupBlend(void)
color.u32 = d_8to24table[SHELL_RB_COLOR];
else if (mask == (RF_SHELL_BLUE | RF_SHELL_GREEN))
color.u32 = d_8to24table[SHELL_BG_COLOR];
- else if (mask == (RF_SHELL_DOUBLE))
+ else if (mask == RF_SHELL_DOUBLE)
color.u32 = d_8to24table[SHELL_DOUBLE_COLOR];
- else if (mask == (RF_SHELL_HALF_DAM))
+ else if (mask == RF_SHELL_HALF_DAM)
color.u32 = d_8to24table[SHELL_HALF_DAM_COLOR];
else
color.u32 = d_8to24table[SHELL_WHITE_COLOR];
@@ -633,7 +639,7 @@ static void R_AliasSetupBlend(void)
d_pdrawspans = R_PolysetDrawSpansConstant8_Blended;
} else if (currententity->flags & RF_TRANSLUCENT) {
- if (currententity->alpha == 1)
+ if (r_alias_alpha == 255)
d_pdrawspans = R_PolysetDrawSpans8_Opaque;
else
d_pdrawspans = R_PolysetDrawSpans8_Blended;
@@ -652,9 +658,8 @@ void R_AliasDrawModel(void)
if (r_lerpmodels->integer == 0)
currententity->backlerp = 0;
- if ((currententity->flags & (RF_WEAPONMODEL | RF_LEFTHAND)) == (RF_WEAPONMODEL | RF_LEFTHAND)) {
+ if ((currententity->flags & (RF_WEAPONMODEL | RF_LEFTHAND)) == (RF_WEAPONMODEL | RF_LEFTHAND))
aliasxscale = -aliasxscale;
- }
/*
** we have to set our frame pointers and transformations before
@@ -665,21 +670,14 @@ void R_AliasDrawModel(void)
// see if the bounding box lets us trivially reject, also sets
// trivial accept status
- if (R_AliasCheckBBox() == BBOX_TRIVIAL_REJECT) {
- if ((currententity->flags & (RF_WEAPONMODEL | RF_LEFTHAND)) == (RF_WEAPONMODEL | RF_LEFTHAND)) {
- aliasxscale = -aliasxscale;
- }
- return;
- }
+ if (R_AliasCheckBBox() == BBOX_TRIVIAL_REJECT)
+ goto exit;
// set up the skin and verify it exists
- if (!R_AliasSetupSkin()) {
- Com_DPrintf("R_AliasDrawModel %s: NULL skin found\n",
- currentmodel->name);
- return;
- }
+ R_AliasSetupSkin();
r_amodels_drawn++;
+
R_AliasSetupLighting();
R_AliasSetupBlend();
@@ -696,10 +694,8 @@ void R_AliasDrawModel(void)
R_AliasPreparePoints();
- if ((currententity->flags & (RF_WEAPONMODEL | RF_LEFTHAND)) == (RF_WEAPONMODEL | RF_LEFTHAND)) {
+exit:
+ if ((currententity->flags & (RF_WEAPONMODEL | RF_LEFTHAND)) == (RF_WEAPONMODEL | RF_LEFTHAND))
aliasxscale = -aliasxscale;
- }
}
-
-
diff --git a/src/refresh/sw/model.c b/src/refresh/sw/model.c
index 4cf61ec..3a60740 100644
--- a/src/refresh/sw/model.c
+++ b/src/refresh/sw/model.c
@@ -202,8 +202,8 @@ qerror_t MOD_LoadMD2(model_t *model, const void *rawdata, size_t length)
dst_tri = model->tris;
for (i = 0; i < header.num_tris; i++, src_tri++, dst_tri++) {
for (j = 0; j < 3; j++) {
- unsigned idx_xyz = LittleShort(src_tri->index_xyz[j]);
- unsigned idx_st = LittleShort(src_tri->index_st[j]);
+ uint16_t idx_xyz = LittleShort(src_tri->index_xyz[j]);
+ uint16_t idx_st = LittleShort(src_tri->index_st[j]);
if (idx_xyz >= header.num_xyz || idx_st >= header.num_st) {
ret = Q_ERR_BAD_INDEX;
@@ -218,12 +218,24 @@ qerror_t MOD_LoadMD2(model_t *model, const void *rawdata, size_t length)
// load base s and t vertices
model->sts = MOD_Malloc(header.num_st * sizeof(maliasst_t));
model->numsts = header.num_st;
+ model->skinwidth = header.skinwidth;
+ model->skinheight = header.skinheight;
src_st = (dmd2stvert_t *)((byte *)rawdata + header.ofs_st);
dst_st = model->sts;
for (i = 0; i < header.num_st; i++, src_st++, dst_st++) {
dst_st->s = (int16_t)LittleShort(src_st->s);
dst_st->t = (int16_t)LittleShort(src_st->t);
+
+ if (dst_st->s < 0 || dst_st->s >= header.skinwidth) {
+ ret = Q_ERR_BAD_INDEX;
+ goto fail;
+ }
+
+ if (dst_st->t < 0 || dst_st->t >= header.skinheight) {
+ ret = Q_ERR_BAD_INDEX;
+ goto fail;
+ }
}
// load the frames
@@ -238,12 +250,19 @@ qerror_t MOD_LoadMD2(model_t *model, const void *rawdata, size_t length)
dst_frame->scale[j] = LittleFloat(src_frame->scale[j]);
dst_frame->translate[j] = LittleFloat(src_frame->translate[j]);
}
+
// verts are all 8 bit, so no swapping needed
dst_frame->verts = MOD_Malloc(header.num_xyz * sizeof(maliasvert_t));
-
- // TODO: check normal indices
memcpy(dst_frame->verts, src_frame->verts, header.num_xyz * sizeof(maliasvert_t));
+ // check normal indices
+ for (j = 0; j < header.num_xyz; j++) {
+ if (dst_frame->verts[j].lightnormalindex > NUMVERTEXNORMALS) {
+ ret = Q_ERR_BAD_INDEX;
+ goto fail;
+ }
+ }
+
src_frame = (dmd2frame_t *)((byte *)src_frame + header.framesize);
}
diff --git a/src/refresh/sw/polyset.c b/src/refresh/sw/polyset.c
index 1efdb8c..e1f2716 100644
--- a/src/refresh/sw/polyset.c
+++ b/src/refresh/sw/polyset.c
@@ -95,10 +95,6 @@ static const adivtab_t adivtab[32 * 32] = {
#include "adivtab.h"
};
-static byte *skintable[MAX_LBM_HEIGHT];
-static int skinwidth;
-static byte *skinstart;
-
void (*d_pdrawspans)(spanpackage_t *pspanpackage);
void R_PolysetDrawSpansConstant8_Blended(spanpackage_t *pspanpackage);
@@ -108,26 +104,6 @@ void R_PolysetDrawSpans8_Opaque(spanpackage_t *pspanpackage);
static void R_PolysetSetEdgeTable(void);
static void R_RasterizeAliasPolySmooth(void);
-/*
-================
-R_PolysetUpdateTables
-================
-*/
-void R_PolysetUpdateTables(void)
-{
- int i;
- byte *s;
-
- if (r_affinetridesc.skinwidth != skinwidth ||
- r_affinetridesc.pskin != skinstart) {
- skinwidth = r_affinetridesc.skinwidth;
- skinstart = r_affinetridesc.pskin;
- s = skinstart;
- for (i = 0; i < MAX_LBM_HEIGHT; i++, s += skinwidth)
- skintable[i] = s;
- }
-}
-
/*
================
diff --git a/src/refresh/sw/sw.h b/src/refresh/sw/sw.h
index c6714dc..c684794 100644
--- a/src/refresh/sw/sw.h
+++ b/src/refresh/sw/sw.h
@@ -64,8 +64,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#define WARP_WIDTH 320
#define WARP_HEIGHT 240
-#define MAX_LBM_HEIGHT 480
-
#define PARTICLE_Z_CLIP 8.0
#define TRANSPARENT_COLOR 0xFF
@@ -107,7 +105,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#define NEAR_CLIP 0.01
-#define MAXALIASVERTS 2000 // TODO: tune this
+#define MAXALIASVERTS 2048 // MD2_MAX_VERTS
#define ALIAS_Z_CLIP_PLANE 4
// turbulence stuff
@@ -176,7 +174,6 @@ typedef struct finalvert_s {
typedef struct {
void *pskin;
- int pskindesc;
int skinwidth;
int skinheight;
} affinetridesc_t;
@@ -321,7 +318,6 @@ extern affinetridesc_t r_affinetridesc;
void D_DrawSurfaces(void);
void D_ViewChanged(void);
void D_WarpScreen(void);
-void R_PolysetUpdateTables(void);
//=======================================================================//