summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/refresh/gl/gl.h3
-rw-r--r--src/refresh/gl/mesh.c2
-rw-r--r--src/refresh/gl/models.c169
-rw-r--r--src/refresh/models.c4
-rw-r--r--src/refresh/sw/alias.c2
-rw-r--r--src/refresh/sw/sw.h1
6 files changed, 103 insertions, 78 deletions
diff --git a/src/refresh/gl/gl.h b/src/refresh/gl/gl.h
index 3064967..5e644e6 100644
--- a/src/refresh/gl/gl.h
+++ b/src/refresh/gl/gl.h
@@ -423,8 +423,7 @@ void GL_ShutdownImages(void);
* gl_tess.c
*
*/
-#define TESS_MAX_FACES 256
-#define TESS_MAX_VERTICES (16 * TESS_MAX_FACES)
+#define TESS_MAX_VERTICES 4096
#define TESS_MAX_INDICES (3 * TESS_MAX_VERTICES)
typedef struct {
diff --git a/src/refresh/gl/mesh.c b/src/refresh/gl/mesh.c
index e469339..490a64e 100644
--- a/src/refresh/gl/mesh.c
+++ b/src/refresh/gl/mesh.c
@@ -591,7 +591,7 @@ static void draw_alias_mesh(maliasmesh_t *mesh)
GL_BindTexture(0, texnum_for_mesh(mesh));
(*tessfunc)(mesh);
- c.trisDrawn += mesh->numverts;
+ c.trisDrawn += mesh->numtris;
if (shadelight) {
GL_ArrayBits(GLA_VERTEX | GLA_TC | GLA_COLOR);
diff --git a/src/refresh/gl/models.c b/src/refresh/gl/models.c
index b9fc8e2..22119cd 100644
--- a/src/refresh/gl/models.c
+++ b/src/refresh/gl/models.c
@@ -21,29 +21,36 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "format/md3.h"
#include "format/sp2.h"
+#if MAX_ALIAS_VERTS > TESS_MAX_VERTICES
+#error TESS_MAX_VERTICES
+#endif
+
+#if MD2_MAX_TRIANGLES > TESS_MAX_INDICES / 3
+#error TESS_MAX_INDICES
+#endif
+
qerror_t MOD_LoadMD2(model_t *model, const void *rawdata, size_t length)
{
- dmd2header_t header;
- dmd2frame_t *src_frame;
- dmd2trivertx_t *src_vert;
- dmd2triangle_t *src_tri;
- dmd2stvert_t *src_tc;
- maliasframe_t *dst_frame;
- maliasvert_t *dst_vert;
- maliasmesh_t *dst_mesh;
- QGL_INDEX_TYPE *finalIndices;
- maliastc_t *dst_tc;
- int i, j, k;
- uint16_t remap[MD2_MAX_TRIANGLES * 3];
- uint16_t vertIndices[MD2_MAX_TRIANGLES * 3];
- uint16_t tcIndices[MD2_MAX_TRIANGLES * 3];
- int numverts, numindices;
- char skinname[MAX_QPATH];
- char *src_skin;
- vec_t scaleS, scaleT;
- int val;
- vec3_t mins, maxs;
- qerror_t ret;
+ dmd2header_t header;
+ dmd2frame_t *src_frame;
+ dmd2trivertx_t *src_vert;
+ dmd2triangle_t *src_tri;
+ dmd2stvert_t *src_tc;
+ char *src_skin;
+ maliasframe_t *dst_frame;
+ maliasvert_t *dst_vert;
+ maliasmesh_t *dst_mesh;
+ maliastc_t *dst_tc;
+ int i, j, k, val;
+ uint16_t remap[TESS_MAX_INDICES];
+ uint16_t vertIndices[TESS_MAX_INDICES];
+ uint16_t tcIndices[TESS_MAX_INDICES];
+ uint16_t finalIndices[TESS_MAX_INDICES];
+ int numverts, numindices;
+ char skinname[MAX_QPATH];
+ vec_t scale_s, scale_t;
+ vec3_t mins, maxs;
+ qerror_t ret;
if (length < sizeof(header)) {
return Q_ERR_FILE_TOO_SMALL;
@@ -66,44 +73,40 @@ qerror_t MOD_LoadMD2(model_t *model, const void *rawdata, size_t length)
return ret;
}
- Hunk_Begin(&model->hunk, 0x400000);
- model->type = MOD_ALIAS;
-
// load all triangle indices
+ numindices = 0;
src_tri = (dmd2triangle_t *)((byte *)rawdata + header.ofs_tris);
for (i = 0; i < header.num_tris; i++) {
for (j = 0; j < 3; j++) {
uint16_t idx_xyz = LittleShort(src_tri->index_xyz[j]);
uint16_t idx_st = LittleShort(src_tri->index_st[j]);
+ // some broken models have 0xFFFF indices
if (idx_xyz >= header.num_xyz || idx_st >= header.num_st) {
- ret = Q_ERR_BAD_INDEX;
- goto fail;
+ break;
}
- vertIndices[i * 3 + j] = idx_xyz;
- tcIndices[i * 3 + j] = idx_st;
+ vertIndices[numindices + j] = idx_xyz;
+ tcIndices[numindices + j] = idx_st;
+ }
+ if (j == 3) {
+ // only count good triangles
+ numindices += 3;
}
src_tri++;
}
- numindices = header.num_tris * 3;
-
- model->meshes = MOD_Malloc(sizeof(maliasmesh_t));
- model->nummeshes = 1;
-
- dst_mesh = model->meshes;
- dst_mesh->indices = MOD_Malloc(numindices * sizeof(QGL_INDEX_TYPE));
- dst_mesh->numtris = header.num_tris;
- dst_mesh->numindices = numindices;
+ if (numindices < 3) {
+ return Q_ERR_TOO_FEW;
+ }
for (i = 0; i < numindices; i++) {
remap[i] = 0xFFFF;
}
+ // remap all triangle indices
numverts = 0;
src_tc = (dmd2stvert_t *)((byte *)rawdata + header.ofs_st);
- finalIndices = dst_mesh->indices;
for (i = 0; i < numindices; i++) {
if (remap[i] != 0xFFFF) {
continue; // already remapped
@@ -124,9 +127,34 @@ qerror_t MOD_LoadMD2(model_t *model, const void *rawdata, size_t length)
finalIndices[i] = numverts++;
}
+ if (numverts > TESS_MAX_VERTICES) {
+ return Q_ERR_TOO_MANY;
+ }
+
+ Hunk_Begin(&model->hunk, 0x400000);
+ model->type = MOD_ALIAS;
+ model->nummeshes = 1;
+ model->numframes = header.num_frames;
+ model->meshes = MOD_Malloc(sizeof(maliasmesh_t));
+ model->frames = MOD_Malloc(header.num_frames * sizeof(maliasframe_t));
+
+ dst_mesh = model->meshes;
+ dst_mesh->numtris = numindices / 3;
+ dst_mesh->numindices = numindices;
+ dst_mesh->numverts = numverts;
+ dst_mesh->numskins = header.num_skins;
dst_mesh->verts = MOD_Malloc(numverts * header.num_frames * sizeof(maliasvert_t));
dst_mesh->tcoords = MOD_Malloc(numverts * sizeof(maliastc_t));
- dst_mesh->numverts = numverts;
+ dst_mesh->indices = MOD_Malloc(numindices * sizeof(QGL_INDEX_TYPE));
+
+ if (dst_mesh->numtris != header.num_tris) {
+ Com_DPrintf("%s has %d bad triangles\n", model->name, header.num_tris - dst_mesh->numtris);
+ }
+
+ // store final triangle indices
+ for (i = 0; i < numindices; i++) {
+ dst_mesh->indices[i] = finalIndices[i];
+ }
// load all skins
src_skin = (char *)rawdata + header.ofs_skins;
@@ -139,27 +167,23 @@ qerror_t MOD_LoadMD2(model_t *model, const void *rawdata, size_t length)
dst_mesh->skins[i] = IMG_Find(skinname, IT_SKIN, IF_NONE);
src_skin += MD2_MAX_SKINNAME;
}
- dst_mesh->numskins = header.num_skins;
// load all tcoords
src_tc = (dmd2stvert_t *)((byte *)rawdata + header.ofs_st);
dst_tc = dst_mesh->tcoords;
- scaleS = 1.0f / header.skinwidth;
- scaleT = 1.0f / header.skinheight;
+ scale_s = 1.0f / header.skinwidth;
+ scale_t = 1.0f / header.skinheight;
for (i = 0; i < numindices; i++) {
- if (remap[i] == i) {
- float s = (int16_t)LittleShort(src_tc[tcIndices[i]].s);
- float t = (int16_t)LittleShort(src_tc[tcIndices[i]].t);
-
- dst_tc[finalIndices[i]].st[0] = s * scaleS;
- dst_tc[finalIndices[i]].st[1] = t * scaleT;
+ if (remap[i] != i) {
+ continue;
}
+ dst_tc[finalIndices[i]].st[0] =
+ (int16_t)LittleShort(src_tc[tcIndices[i]].s) * scale_s;
+ dst_tc[finalIndices[i]].st[1] =
+ (int16_t)LittleShort(src_tc[tcIndices[i]].t) * scale_t;
}
// load all frames
- model->frames = MOD_Malloc(header.num_frames * sizeof(maliasframe_t));
- model->numframes = header.num_frames;
-
src_frame = (dmd2frame_t *)((byte *)rawdata + header.ofs_frames);
dst_frame = model->frames;
for (j = 0; j < header.num_frames; j++) {
@@ -169,28 +193,31 @@ qerror_t MOD_LoadMD2(model_t *model, const void *rawdata, size_t length)
// load frame vertices
ClearBounds(mins, maxs);
for (i = 0; i < numindices; i++) {
- if (remap[i] == i) {
- src_vert = &src_frame->verts[vertIndices[i]];
- dst_vert = &dst_mesh->verts[j * numverts + finalIndices[i]];
+ if (remap[i] != i) {
+ continue;
+ }
+ src_vert = &src_frame->verts[vertIndices[i]];
+ dst_vert = &dst_mesh->verts[j * numverts + finalIndices[i]];
+
+ dst_vert->pos[0] = src_vert->v[0];
+ dst_vert->pos[1] = src_vert->v[1];
+ dst_vert->pos[2] = src_vert->v[2];
- dst_vert->pos[0] = src_vert->v[0];
- dst_vert->pos[1] = src_vert->v[1];
- dst_vert->pos[2] = src_vert->v[2];
- k = src_vert->lightnormalindex;
- if (k >= NUMVERTEXNORMALS) {
- ret = Q_ERR_BAD_INDEX;
- goto fail;
- }
- dst_vert->norm[0] = gl_static.latlngtab[k][0];
- dst_vert->norm[1] = gl_static.latlngtab[k][1];
+ val = src_vert->lightnormalindex;
+ if (val >= NUMVERTEXNORMALS) {
+ dst_vert->norm[0] = 0;
+ dst_vert->norm[1] = 0;
+ } else {
+ dst_vert->norm[0] = gl_static.latlngtab[val][0];
+ dst_vert->norm[1] = gl_static.latlngtab[val][1];
+ }
- for (k = 0; k < 3; k++) {
- val = dst_vert->pos[k];
- if (val < mins[k])
- mins[k] = val;
- if (val > maxs[k])
- maxs[k] = val;
- }
+ for (k = 0; k < 3; k++) {
+ val = dst_vert->pos[k];
+ if (val < mins[k])
+ mins[k] = val;
+ if (val > maxs[k])
+ maxs[k] = val;
}
}
diff --git a/src/refresh/models.c b/src/refresh/models.c
index fc11d8b..e11cb59 100644
--- a/src/refresh/models.c
+++ b/src/refresh/models.c
@@ -159,7 +159,7 @@ qerror_t MOD_ValidateMD2(dmd2header_t *header, size_t length)
// check st
if (header->num_st < 3)
return Q_ERR_TOO_FEW;
- if (header->num_st > MD2_MAX_VERTS)
+ if (header->num_st > MAX_ALIAS_VERTS)
return Q_ERR_TOO_MANY;
end = header->ofs_st + sizeof(dmd2stvert_t) * header->num_st;
@@ -169,7 +169,7 @@ qerror_t MOD_ValidateMD2(dmd2header_t *header, size_t length)
// check xyz and frames
if (header->num_xyz < 3)
return Q_ERR_TOO_FEW;
- if (header->num_xyz > MD2_MAX_VERTS)
+ if (header->num_xyz > MAX_ALIAS_VERTS)
return Q_ERR_TOO_MANY;
if (header->num_frames < 1)
return Q_ERR_TOO_FEW;
diff --git a/src/refresh/sw/alias.c b/src/refresh/sw/alias.c
index 5d2c2e0..9d7e402 100644
--- a/src/refresh/sw/alias.c
+++ b/src/refresh/sw/alias.c
@@ -277,7 +277,7 @@ static void R_AliasPreparePoints(void)
maliasst_t *pstverts;
maliastri_t *ptri;
finalvert_t *pfv[3];
- finalvert_t finalverts[MAXALIASVERTS +
+ finalvert_t finalverts[MAX_ALIAS_VERTS +
((CACHE_SIZE - 1) / sizeof(finalvert_t)) + 3];
finalvert_t *pfinalverts;
diff --git a/src/refresh/sw/sw.h b/src/refresh/sw/sw.h
index 1fea7ee..d00681a 100644
--- a/src/refresh/sw/sw.h
+++ b/src/refresh/sw/sw.h
@@ -102,7 +102,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#define NEAR_CLIP 0.01
-#define MAXALIASVERTS 2048 // MD2_MAX_VERTS
#define ALIAS_Z_CLIP_PLANE 4
// turbulence stuff