WildCode's alias model VA prepatory patch

This commit is contained in:
Bill Currie 2003-04-08 04:13:49 +00:00
parent 8fc721a2bb
commit 01bff9c79e
5 changed files with 261 additions and 117 deletions

View file

@ -309,7 +309,7 @@ typedef struct {
int triangles; int triangles;
mdl_t mdl; mdl_t mdl;
int tex_coord;
int numposes; int numposes;
int poseverts; int poseverts;
int posedata; // numposes * poseverts trivert_t int posedata; // numposes * poseverts trivert_t
@ -462,6 +462,7 @@ void Mod_Print (void);
extern struct cvar_s *gl_mesh_cache; extern struct cvar_s *gl_mesh_cache;
extern struct cvar_s *gl_subdivide_size; extern struct cvar_s *gl_subdivide_size;
extern struct cvar_s *gl_alias_render_tri;
extern model_t *loadmodel; extern model_t *loadmodel;
extern char loadname[32]; extern char loadname[32];
extern byte *mod_base; extern byte *mod_base;

View file

@ -71,6 +71,10 @@ typedef struct {
// TODO: could be shorts // TODO: could be shorts
typedef struct {
float st[2];
} tex_coord_t;
typedef struct { typedef struct {
int onseam; int onseam;
int s; int s;

View file

@ -345,133 +345,163 @@ Mod_MakeAliasModelDisplayLists (model_t *m, aliashdr_t *hdr, void *_m, int _s, i
aliasmodel = m; aliasmodel = m;
paliashdr = hdr; paliashdr = hdr;
if (gl_mesh_cache->int_val if (!gl_alias_render_tri->int_val) {
&& gl_mesh_cache->int_val <= paliashdr->mdl.numtris) {
do_cache = true;
mdfour (model_digest, (unsigned char *) _m, _s); if (gl_mesh_cache->int_val
&& gl_mesh_cache->int_val <= paliashdr->mdl.numtris) {
do_cache = true;
// look for a cached version mdfour (model_digest, (unsigned char *) _m, _s);
strcpy (cache, "glquake/");
QFS_StripExtension (m->name + strlen ("progs/"), // look for a cached version
strcpy (cache, "glquake/");
QFS_StripExtension (m->name + strlen ("progs/"),
cache + strlen ("glquake/")); cache + strlen ("glquake/"));
strncat (cache, ".qfms", sizeof (cache) - strlen (cache)); strncat (cache, ".qfms", sizeof (cache) - strlen (cache));
QFS_FOpenFile (cache, &f); QFS_FOpenFile (cache, &f);
if (f) { if (f) {
unsigned char d1[MDFOUR_DIGEST_BYTES]; unsigned char d1[MDFOUR_DIGEST_BYTES];
unsigned char d2[MDFOUR_DIGEST_BYTES]; unsigned char d2[MDFOUR_DIGEST_BYTES];
struct mdfour md; struct mdfour md;
int len, vers; int len, vers;
int nc = 0, no = 0; int nc = 0, no = 0;
int *c = 0, *vo = 0; int *c = 0, *vo = 0;
memset (d1, 0, sizeof (d1)); memset (d1, 0, sizeof (d1));
memset (d2, 0, sizeof (d2)); memset (d2, 0, sizeof (d2));
Qread (f, &vers, sizeof (int)); Qread (f, &vers, sizeof (int));
Qread (f, &len, sizeof (int)); Qread (f, &len, sizeof (int));
Qread (f, &nc, sizeof (int)); Qread (f, &nc, sizeof (int));
Qread (f, &no, sizeof (int)); Qread (f, &no, sizeof (int));
if (vers == 1 && (nc + no) == len) { if (vers == 1 && (nc + no) == len) {
c = malloc (((nc + 1023) & ~1023) * sizeof (c[0])); c = malloc (((nc + 1023) & ~1023) * sizeof (c[0]));
vo = malloc (((no + 1023) & ~1023) * sizeof (vo[0])); vo = malloc (((no + 1023) & ~1023) * sizeof (vo[0]));
if (!c || !vo) if (!c || !vo)
Sys_Error ("gl_mesh.c: out of memory"); Sys_Error ("gl_mesh.c: out of memory");
Qread (f, c, nc * sizeof (c[0])); Qread (f, c, nc * sizeof (c[0]));
Qread (f, vo, no * sizeof (vo[0])); Qread (f, vo, no * sizeof (vo[0]));
Qread (f, d1, MDFOUR_DIGEST_BYTES); Qread (f, d1, MDFOUR_DIGEST_BYTES);
Qread (f, d2, MDFOUR_DIGEST_BYTES); Qread (f, d2, MDFOUR_DIGEST_BYTES);
Qclose (f); Qclose (f);
mdfour_begin (&md); mdfour_begin (&md);
mdfour_update (&md, (unsigned char *) &vers, sizeof(int)); mdfour_update (&md, (unsigned char *) &vers, sizeof(int));
mdfour_update (&md, (unsigned char *) &len, sizeof(int)); mdfour_update (&md, (unsigned char *) &len, sizeof(int));
mdfour_update (&md, (unsigned char *) &nc, sizeof(int)); mdfour_update (&md, (unsigned char *) &nc, sizeof(int));
mdfour_update (&md, (unsigned char *) &no, sizeof(int)); mdfour_update (&md, (unsigned char *) &no, sizeof(int));
mdfour_update (&md, (unsigned char *) c, nc * sizeof (c[0])); mdfour_update (&md, (unsigned char *) c, nc * sizeof (c[0]));
mdfour_update (&md, (unsigned char *) vo, no * sizeof (vo[0])); mdfour_update (&md, (unsigned char *) vo, no * sizeof (vo[0]));
mdfour_update (&md, d1, MDFOUR_DIGEST_BYTES); mdfour_update (&md, d1, MDFOUR_DIGEST_BYTES);
mdfour_result (&md, mesh_digest); mdfour_result (&md, mesh_digest);
if (memcmp (d2, mesh_digest, MDFOUR_DIGEST_BYTES) == 0 if (memcmp (d2, mesh_digest, MDFOUR_DIGEST_BYTES) == 0
&& memcmp (d1, model_digest, MDFOUR_DIGEST_BYTES) == 0) { && memcmp (d1, model_digest, MDFOUR_DIGEST_BYTES) == 0) {
remesh = false; remesh = false;
numcommands = nc; numcommands = nc;
numorder = no; numorder = no;
if (numcommands > commands_size) { if (numcommands > commands_size) {
if (commands) if (commands)
free (commands); free (commands);
commands_size = (numcommands + 1023) & ~1023; commands_size = (numcommands + 1023) & ~1023;
commands = c; commands = c;
} else { } else {
memcpy (commands, c, numcommands * sizeof (c[0])); memcpy (commands, c, numcommands * sizeof (c[0]));
free(c); free(c);
} }
if (numorder > vertexorder_size) { if (numorder > vertexorder_size) {
if (vertexorder) if (vertexorder)
free (vertexorder); free (vertexorder);
vertexorder_size = (numorder + 1023) & ~1023; vertexorder_size = (numorder + 1023) & ~1023;
vertexorder = vo; vertexorder = vo;
} else { } else {
memcpy (vertexorder, vo, numorder * sizeof (vo[0])); memcpy (vertexorder, vo, numorder * sizeof (vo[0]));
free (vo); free (vo);
}
} }
} }
} }
} }
} if (remesh) {
if (remesh) { // build it from scratch
// build it from scratch Sys_DPrintf ("meshing %s...\n", m->name);
Sys_DPrintf ("meshing %s...\n", m->name);
BuildTris (); // trifans or lists BuildTris (); // trifans or lists
if (do_cache) { if (do_cache) {
// save out the cached version // save out the cached version
snprintf (fullpath, sizeof (fullpath), "%s/%s", snprintf (fullpath, sizeof (fullpath), "%s/%s",
qfs_gamedir->dir.def, cache); qfs_gamedir->dir.def, cache);
f = QFS_WOpen (fullpath, 9); f = QFS_WOpen (fullpath, 9);
if (f) { if (f) {
struct mdfour md; struct mdfour md;
int vers = 1; int vers = 1;
int len = numcommands + numorder; int len = numcommands + numorder;
mdfour_begin (&md); mdfour_begin (&md);
mdfour_update (&md, (unsigned char *) &vers, sizeof (int)); mdfour_update (&md, (unsigned char *) &vers, sizeof (int));
mdfour_update (&md, (unsigned char *) &len, sizeof (int)); mdfour_update (&md, (unsigned char *) &len, sizeof (int));
mdfour_update (&md, (unsigned char *) &numcommands, mdfour_update (&md, (unsigned char *) &numcommands,
sizeof (int)); sizeof (int));
mdfour_update (&md, (unsigned char *) &numorder, sizeof (int)); mdfour_update (&md, (unsigned char *) &numorder, sizeof (int));
mdfour_update (&md, (unsigned char *) commands, mdfour_update (&md, (unsigned char *) commands,
numcommands * sizeof (commands[0])); numcommands * sizeof (commands[0]));
mdfour_update (&md, (unsigned char *) vertexorder, mdfour_update (&md, (unsigned char *) vertexorder,
numorder * sizeof (vertexorder[0])); numorder * sizeof (vertexorder[0]));
mdfour_update (&md, model_digest, MDFOUR_DIGEST_BYTES); mdfour_update (&md, model_digest, MDFOUR_DIGEST_BYTES);
mdfour_result (&md, mesh_digest); mdfour_result (&md, mesh_digest);
Qwrite (f, &vers, sizeof (int)); Qwrite (f, &vers, sizeof (int));
Qwrite (f, &len, sizeof (int)); Qwrite (f, &len, sizeof (int));
Qwrite (f, &numcommands, sizeof (int)); Qwrite (f, &numcommands, sizeof (int));
Qwrite (f, &numorder, sizeof (int)); Qwrite (f, &numorder, sizeof (int));
Qwrite (f, commands, numcommands * sizeof (commands[0])); Qwrite (f, commands, numcommands * sizeof (commands[0]));
Qwrite (f, vertexorder, numorder * sizeof (vertexorder[0])); Qwrite (f, vertexorder, numorder * sizeof (vertexorder[0]));
Qwrite (f, model_digest, MDFOUR_DIGEST_BYTES); Qwrite (f, model_digest, MDFOUR_DIGEST_BYTES);
Qwrite (f, mesh_digest, MDFOUR_DIGEST_BYTES); Qwrite (f, mesh_digest, MDFOUR_DIGEST_BYTES);
Qclose (f); Qclose (f);
}
} }
}
// save the data out
paliashdr->poseverts = numorder;
cmds = Hunk_Alloc (numcommands * sizeof (int));
paliashdr->commands = (byte *) cmds - (byte *) paliashdr;
memcpy (cmds, commands, numcommands * sizeof (int));
} else {
tex_coord_t *tex_coord;
numorder = 0;
for (i=0; i < pheader->mdl.numtris; i++) {
add_vertex(triangles[i].vertindex[0]);
add_vertex(triangles[i].vertindex[1]);
add_vertex(triangles[i].vertindex[2]);
}
paliashdr->poseverts = numorder;
tex_coord = Hunk_Alloc (numorder * sizeof(tex_coord_t));
paliashdr->tex_coord = (byte *) tex_coord - (byte *) paliashdr;
for (i=0; i < numorder; i++) {
float s, t;
int k;
k = vertexorder[i];
s = stverts[k].s;
t = stverts[k].t;
if (!triangles[i/3].facesfront && stverts[k].onseam)
s += pheader->mdl.skinwidth / 2; // on back side
s = (s + 0.5) / pheader->mdl.skinwidth;
t = (t + 0.5) / pheader->mdl.skinheight;
tex_coord[i].st[0] = s;
tex_coord[i].st[1] = t;
} }
} }
// save the data out
paliashdr->poseverts = numorder;
cmds = Hunk_Alloc (numcommands * sizeof (int));
paliashdr->commands = (byte *) cmds - (byte *) paliashdr;
memcpy (cmds, commands, numcommands * sizeof (int));
if (extra) { if (extra) {
trivertx16_t *verts; trivertx16_t *verts;
verts = Hunk_Alloc (paliashdr->numposes * paliashdr->poseverts verts = Hunk_Alloc (paliashdr->numposes * paliashdr->poseverts

View file

@ -60,6 +60,7 @@ texture_t *r_notexture_mip;
cvar_t *gl_mesh_cache; cvar_t *gl_mesh_cache;
cvar_t *gl_subdivide_size; cvar_t *gl_subdivide_size;
cvar_t *gl_alias_render_tri;
static void Mod_CallbackLoad (void *object, cache_allocator_t allocator); static void Mod_CallbackLoad (void *object, cache_allocator_t allocator);
@ -102,6 +103,7 @@ Mod_Init_Cvars (void)
gl_mesh_cache = Cvar_Get ("gl_mesh_cache", "256", CVAR_ARCHIVE, NULL, gl_mesh_cache = Cvar_Get ("gl_mesh_cache", "256", CVAR_ARCHIVE, NULL,
"minimum triangle count in a model for its mesh" "minimum triangle count in a model for its mesh"
" to be cached. 0 to disable caching"); " to be cached. 0 to disable caching");
gl_alias_render_tri = Cvar_Get("gl_alias_render_tri", "0", CVAR_ARCHIVE, NULL, "When loading alias models mesh for pure triangle rendering");
} }
void void

View file

@ -74,6 +74,8 @@ typedef struct {
typedef struct { typedef struct {
blended_vert_t *verts; blended_vert_t *verts;
int *order; int *order;
tex_coord_t *tex_coord;
int count;
} vert_order_t; } vert_order_t;
float r_avertexnormals[NUMVERTEXNORMALS][3] = { float r_avertexnormals[NUMVERTEXNORMALS][3] = {
@ -88,6 +90,84 @@ float r_avertexnormal_dots[SHADEDOT_QUANT][256] =
vec3_t shadevector; vec3_t shadevector;
static void
GL_DrawAliasFrameTri (vert_order_t *vo)
{
float color[4];
int count;
blended_vert_t *verts;
tex_coord_t *tex_coord;
verts = vo->verts;
tex_coord = vo->tex_coord;
color[3] = modelalpha;
count = vo->count;
qfglBegin (GL_TRIANGLES);
do {
qfglTexCoord2fv (tex_coord->st);
VectorMA (ambientcolor, verts->lightdot, shadecolor, color);
qfglColor4fv (color);
qfglVertex3fv (verts->vert);
tex_coord++;
verts++;
} while (count--);
qfglEnd();
}
static void
GL_DrawAliasFrameTri_fb (vert_order_t *vo)
{
int count;
float color[4] = { 1.0, 1.0, 1.0, 0.0};
blended_vert_t *verts;
tex_coord_t *tex_coord;
verts = vo->verts;
color[3] = modelalpha * 1.0;
count = vo->count;
tex_coord = vo->tex_coord;
qfglBegin (GL_TRIANGLES);
do {
qfglTexCoord2fv (tex_coord->st);
qfglColor4fv (color);
qfglVertex3fv (verts->vert);
tex_coord++;
verts++;
} while (--count);
qfglEnd();
}
static void
GL_DrawAliasFrameTriMulti (vert_order_t *vo)
{
float color[4];
int count;
blended_vert_t *verts;
tex_coord_t *tex_coord;
verts = vo->verts;
tex_coord = vo->tex_coord;
color[3] = modelalpha;
count = vo->count;
qfglBegin (GL_TRIANGLES);
do {
// texture coordinates come from the draw list
qglMultiTexCoord2fv (gl_mtex_enum + 0, tex_coord->st);
qglMultiTexCoord2fv (gl_mtex_enum + 1, tex_coord->st);
tex_coord++;
// normals and vertexes come from the frame list
VectorMA (ambientcolor, verts->lightdot, shadecolor, color);
qfglColor4fv (color);
qfglVertex3fv (verts->vert);
verts++;
} while (--count);
qfglEnd ();
}
static void static void
GL_DrawAliasFrame (vert_order_t *vo) GL_DrawAliasFrame (vert_order_t *vo)
{ {
@ -277,14 +357,18 @@ GL_GetAliasFrameVerts16 (int frame, aliashdr_t *paliashdr, entity_t *e)
pose = paliashdr->frames[frame].firstpose; pose = paliashdr->frames[frame].firstpose;
numposes = paliashdr->frames[frame].numposes; numposes = paliashdr->frames[frame].numposes;
verts = (trivertx16_t *) ((byte *) paliashdr + paliashdr->posedata); verts = (trivertx16_t *) ((byte *) paliashdr + paliashdr->posedata);
count = paliashdr->poseverts; count = paliashdr->poseverts;
vo = Hunk_TempAlloc (sizeof (*vo) + count * sizeof (blended_vert_t)); vo = Hunk_TempAlloc (sizeof (*vo) + count * sizeof (blended_vert_t));
vo->order = (int *) ((byte *) paliashdr + paliashdr->commands); vo->order = (int *) ((byte *) paliashdr + paliashdr->commands);
vo->verts = (blended_vert_t *) &vo[1]; vo->verts = (blended_vert_t *) &vo[1];
if (paliashdr->tex_coord) {
vo->tex_coord = (tex_coord_t *) ((byte *) paliashdr + paliashdr->tex_coord);
} else {
vo->tex_coord = NULL;
}
vo->count = count;
if (numposes > 1) { if (numposes > 1) {
interval = paliashdr->frames[frame].interval; interval = paliashdr->frames[frame].interval;
pose += (int) (r_realtime / interval) % numposes; pose += (int) (r_realtime / interval) % numposes;
@ -386,6 +470,12 @@ GL_GetAliasFrameVerts (int frame, aliashdr_t *paliashdr, entity_t *e)
vo = Hunk_TempAlloc (sizeof (*vo) + count * sizeof (blended_vert_t)); vo = Hunk_TempAlloc (sizeof (*vo) + count * sizeof (blended_vert_t));
vo->order = (int *) ((byte *) paliashdr + paliashdr->commands); vo->order = (int *) ((byte *) paliashdr + paliashdr->commands);
vo->verts = (blended_vert_t *) &vo[1]; vo->verts = (blended_vert_t *) &vo[1];
if (paliashdr->tex_coord) {
vo->tex_coord = (tex_coord_t *) ((byte *) paliashdr + paliashdr->tex_coord);
} else {
vo->tex_coord = NULL;
}
vo->count = count;
if (numposes > 1) { if (numposes > 1) {
interval = paliashdr->frames[frame].interval; interval = paliashdr->frames[frame].interval;
@ -619,12 +709,19 @@ R_DrawAliasModel (entity_t *e)
// draw all the triangles // draw all the triangles
if (model->fullbright) { if (model->fullbright) {
qfglBindTexture (GL_TEXTURE_2D, texture); qfglBindTexture (GL_TEXTURE_2D, texture);
GL_DrawAliasFrame_fb (vo); if (vo->tex_coord)
GL_DrawAliasFrameTri_fb (vo);
else
GL_DrawAliasFrame_fb (vo);
} else if (!fb_texture) { } else if (!fb_texture) {
// Model has no fullbrights, don't bother with multi // Model has no fullbrights, don't bother with multi
qfglBindTexture (GL_TEXTURE_2D, texture); qfglBindTexture (GL_TEXTURE_2D, texture);
GL_DrawAliasFrame (vo); if (vo->tex_coord)
GL_DrawAliasFrameTri (vo);
else
GL_DrawAliasFrame (vo);
} else { // try multitexture } else { // try multitexture
if (gl_mtex_active) { // set up the textures if (gl_mtex_active) { // set up the textures
qglActiveTexture (gl_mtex_enum + 0); qglActiveTexture (gl_mtex_enum + 0);
@ -635,17 +732,27 @@ R_DrawAliasModel (entity_t *e)
qfglTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); qfglTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
qfglEnable (GL_TEXTURE_2D); qfglEnable (GL_TEXTURE_2D);
GL_DrawAliasFrameMulti (vo); // do the heavy lifting // do the heavy lifting
if (vo->tex_coord)
GL_DrawAliasFrameTriMulti (vo);
else
GL_DrawAliasFrameMulti (vo);
// restore the settings // restore the settings
qfglDisable (GL_TEXTURE_2D); qfglDisable (GL_TEXTURE_2D);
qglActiveTexture (gl_mtex_enum + 0); qglActiveTexture (gl_mtex_enum + 0);
} else { } else {
qfglBindTexture (GL_TEXTURE_2D, texture); if (vo->tex_coord) {
GL_DrawAliasFrame (vo); qfglBindTexture (GL_TEXTURE_2D, texture);
GL_DrawAliasFrameTri (vo);
qfglBindTexture (GL_TEXTURE_2D, fb_texture); qfglBindTexture (GL_TEXTURE_2D, fb_texture);
GL_DrawAliasFrame_fb (vo); GL_DrawAliasFrameTri_fb (vo);
} else {
qfglBindTexture (GL_TEXTURE_2D, texture);
GL_DrawAliasFrame (vo);
qfglBindTexture (GL_TEXTURE_2D, fb_texture);
GL_DrawAliasFrame_fb (vo);
}
} }
} }