From bc6e12f9c8c430e98d6cf89c96c3bfeb903e90d1 Mon Sep 17 00:00:00 2001 From: lordhavoc Date: Mon, 25 Feb 2002 12:52:56 +0000 Subject: [PATCH] cleaned up backend code a bit more, added R_Mesh_Draw_GetBuffer (untested - returns addresses in geometry buffers to fill in, to save memcpy on singlepass objects), rewrote Q2 model loading (now Q2 models are the same as Q1 models after loading), removed Q2 model renderer (and good riddence!), changed aliasvert array from 3 float to 4 float alignment to make copies faster git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@1569 d7cf8633-e32d-0410-b094-e92efae38249 --- gl_backend.c | 122 +++++++++++--------------- gl_backend.h | 28 +++++- gl_models.c | 184 +++++++------------------------------- gl_rsurf.c | 6 ++ model_alias.c | 234 ++++++++++++++++++++++++++++++------------------- model_alias.h | 6 +- model_shared.h | 11 +-- r_light.c | 2 +- 8 files changed, 263 insertions(+), 330 deletions(-) diff --git a/gl_backend.c b/gl_backend.c index a8110bd8..e03740b1 100644 --- a/gl_backend.c +++ b/gl_backend.c @@ -895,7 +895,7 @@ void R_Mesh_AddTransparent(void) void R_Mesh_Draw(const rmeshinfo_t *m) { // these are static because gcc runs out of virtual registers otherwise - static int i, j, overbright; + static int i, j, overbright, *index; static float *in, scaler; static float cr, cg, cb, ca; static buf_mesh_t *mesh; @@ -960,7 +960,7 @@ void R_Mesh_Draw(const rmeshinfo_t *m) mesh = &buf_transmesh[currenttransmesh++]; mesh->firsttriangle = currenttranstriangle; mesh->firstvert = currenttransvertex; - memcpy(&buf_transtri[currenttranstriangle].index[0], m->index, sizeof(int[3]) * m->numtriangles); + index = &buf_transtri[currenttranstriangle].index[0]; currenttranstriangle += m->numtriangles; currenttransvertex += m->numverts; @@ -987,12 +987,14 @@ void R_Mesh_Draw(const rmeshinfo_t *m) mesh = &buf_mesh[currentmesh++]; mesh->firsttriangle = currenttriangle; mesh->firstvert = currentvertex; - memcpy(&buf_tri[currenttriangle].index[0], m->index, sizeof(int[3]) * m->numtriangles); + index = &buf_tri[currenttriangle].index[0]; + currenttriangle += m->numtriangles; currentvertex += m->numverts; } // code shared for transparent and opaque meshs + memcpy(index, m->index, sizeof(int[3]) * m->numtriangles); mesh->blendfunc1 = m->blendfunc1; mesh->blendfunc2 = m->blendfunc2; mesh->depthmask = (m->blendfunc2 == GL_ZERO || m->depthwrite); @@ -1092,7 +1094,7 @@ void R_Mesh_Draw(const rmeshinfo_t *m) void R_Mesh_Draw_NativeOnly(const rmeshinfo_t *m) { // these are static because gcc runs out of virtual registers otherwise - static int i, j, overbright; + static int i, j, overbright, *index; static float *in, scaler; static buf_mesh_t *mesh; static buf_vertex_t *vert; @@ -1147,7 +1149,7 @@ void R_Mesh_Draw_NativeOnly(const rmeshinfo_t *m) mesh = &buf_transmesh[currenttransmesh++]; mesh->firsttriangle = currenttranstriangle; mesh->firstvert = currenttransvertex; - memcpy(&buf_transtri[currenttranstriangle].index[0], m->index, sizeof(int[3]) * m->numtriangles); + index = &buf_transtri[currenttranstriangle].index[0]; currenttranstriangle += m->numtriangles; currenttransvertex += m->numverts; } @@ -1173,12 +1175,13 @@ void R_Mesh_Draw_NativeOnly(const rmeshinfo_t *m) mesh = &buf_mesh[currentmesh++]; mesh->firsttriangle = currenttriangle; mesh->firstvert = currentvertex; - memcpy(&buf_tri[currenttriangle].index[0], m->index, sizeof(int[3]) * m->numtriangles); + index = &buf_tri[currenttriangle].index[0]; currenttriangle += m->numtriangles; currentvertex += m->numverts; } // code shared for transparent and opaque meshs + memcpy(index, m->index, sizeof(int[3]) * m->numtriangles); mesh->blendfunc1 = m->blendfunc1; mesh->blendfunc2 = m->blendfunc2; mesh->depthmask = (m->blendfunc2 == GL_ZERO || m->depthwrite); @@ -1252,12 +1255,14 @@ void R_Mesh_Draw_NativeOnly(const rmeshinfo_t *m) } } -/* -void R_Mesh_Draw_GetBuffer(volatile rmeshinfo_t *m) +// allocates space in geometry buffers, and fills in pointers to the buffers in passsed struct +// (this is used for very high speed rendering, no copying) +int R_Mesh_Draw_GetBuffer(rmeshbufferinfo_t *m) { // these are static because gcc runs out of virtual registers otherwise - static int i, j, *index, overbright; - static float *in, scaler; + int i, j, overbright; + float scaler; + buf_mesh_t *mesh; if (!backendactive) Sys_Error("R_Mesh_Draw: called when backend is not active\n"); @@ -1266,23 +1271,6 @@ void R_Mesh_Draw_GetBuffer(volatile rmeshinfo_t *m) || !m->numverts) Host_Error("R_Mesh_Draw: no triangles or verts\n"); - scaler = 1; - if (m->blendfunc2 == GL_SRC_COLOR) - { - if (m->blendfunc1 == GL_DST_COLOR) // 2x modulate with framebuffer - scaler *= 0.5f; - } - else - { - if (m->tex[0]) - { - overbright = gl_combine.integer; - if (overbright) - scaler *= 0.25f; - } - scaler *= overbrightscale; - } - if (m->transparent) { if (currenttransmesh >= max_meshs || (currenttranstriangle + m->numtriangles) > max_meshs || (currenttransvertex + m->numverts) > max_verts) @@ -1292,22 +1280,22 @@ void R_Mesh_Draw_GetBuffer(volatile rmeshinfo_t *m) Con_Printf("R_Mesh_Draw: ran out of room for transparent meshs\n"); transranout = true; } - return; + return false; } c_transmeshs++; c_transtris += m->numtriangles; + m->index = &buf_transtri[currenttranstriangle].index[0]; m->vertex = &buf_transvertex[currenttransvertex].v[0]; m->color = &buf_transfcolor[currenttransvertex].c[0]; for (i = 0;i < backendunits;i++) - m->texcoords[i] = &buf_transtexcoord[i][currenttransvertex].tc[0]; + m->texcoords[i] = &buf_transtexcoord[i][currenttransvertex].t[0]; // transmesh is only for storage of transparent meshs until they // are inserted into the main mesh array mesh = &buf_transmesh[currenttransmesh++]; mesh->firsttriangle = currenttranstriangle; mesh->firstvert = currenttransvertex; - memcpy(&buf_transtri[currenttranstriangle].index[0], m->index, sizeof(int[3]) * m->numtriangles); currenttranstriangle += m->numtriangles; currenttransvertex += m->numverts; } @@ -1315,8 +1303,8 @@ void R_Mesh_Draw_GetBuffer(volatile rmeshinfo_t *m) { if (m->numtriangles > max_meshs || m->numverts > max_verts) { - Con_Printf("R_Mesh_Draw_NativeOnly: mesh too big for buffers\n"); - return; + Con_Printf("R_Mesh_Draw_GetBuffer: mesh too big for buffers\n"); + return false; } if (currentmesh >= max_meshs || (currenttriangle + m->numtriangles) > max_batch || (currentvertex + m->numverts) > max_verts) @@ -1324,16 +1312,16 @@ void R_Mesh_Draw_GetBuffer(volatile rmeshinfo_t *m) c_meshs++; c_meshtris += m->numtriangles; - vert = &buf_vertex[currentvertex]; - fcolor = &buf_fcolor[currentvertex]; + m->index = &buf_tri[currenttriangle].index[0]; + m->vertex = &buf_vertex[currentvertex].v[0]; + m->color = &buf_fcolor[currentvertex].c[0]; for (i = 0;i < backendunits;i++) - texcoord[i] = &buf_texcoord[i][currentvertex]; + m->texcoords[i] = &buf_texcoord[i][currentvertex].t[0]; // opaque meshs are rendered directly mesh = &buf_mesh[currentmesh++]; mesh->firsttriangle = currenttriangle; mesh->firstvert = currentvertex; - memcpy(&buf_tri[currenttriangle].index[0], m->index, sizeof(int[3]) * m->numtriangles); currenttriangle += m->numtriangles; currentvertex += m->numverts; } @@ -1345,11 +1333,35 @@ void R_Mesh_Draw_GetBuffer(volatile rmeshinfo_t *m) mesh->depthtest = !m->depthdisable; mesh->triangles = m->numtriangles; mesh->verts = m->numverts; + + overbright = false; + scaler = 1; + if (m->blendfunc2 == GL_SRC_COLOR) + { + if (m->blendfunc1 == GL_DST_COLOR) // 2x modulate with framebuffer + scaler *= 0.5f; + } + else + { + if (m->tex[0]) + { + overbright = gl_combine.integer; + if (overbright) + scaler *= 0.25f; + } + scaler *= overbrightscale; + } + m->colorscale = scaler; + j = -1; - for (i = 0;i < backendunits;i++) + for (i = 0;i < MAX_TEXTUREUNITS;i++) { if ((mesh->textures[i] = m->tex[i])) + { j = i; + if (i >= backendunits) + Sys_Error("R_Mesh_Draw_GetBuffer: texture %i supplied when there are only %i texture units\n", j + 1, backendunits); + } mesh->texturergbscale[i] = m->texrgbscale[i]; if (mesh->texturergbscale[i] != 1 && mesh->texturergbscale[i] != 2 && mesh->texturergbscale[i] != 4) mesh->texturergbscale[i] = 1; @@ -1357,42 +1369,8 @@ void R_Mesh_Draw_GetBuffer(volatile rmeshinfo_t *m) if (overbright && j >= 0) mesh->texturergbscale[j] = 4; - if (m->vertexstep != sizeof(buf_vertex_t)) - Host_Error("R_Mesh_Draw_NativeOnly: unsupported vertexstep\n"); - if (m->colorstep != sizeof(buf_fcolor_t)) - Host_Error("R_Mesh_Draw_NativeOnly: unsupported colorstep\n"); - if (m->color == NULL) - Host_Error("R_Mesh_Draw_NativeOnly: must provide color array\n"); - for (j = 0;j < MAX_TEXTUREUNITS && m->tex[j];j++) - { - if (j >= backendunits) - Sys_Error("R_Mesh_Draw_NativeOnly: texture %i supplied when there are only %i texture units\n", j + 1, backendunits); - if (m->texcoordstep[j] != sizeof(buf_texcoord_t)) - Host_Error("R_Mesh_Draw_NativeOnly: unsupported texcoordstep\n"); - } - - memcpy(vert, m->vertex, m->numverts * sizeof(buf_vertex_t)); - for (j = 0;j < MAX_TEXTUREUNITS && m->tex[j];j++) - memcpy(&texcoord[j][0].t[0], m->texcoords[j], m->numverts * sizeof(buf_texcoord_t)); - #if 0 - for (;j < backendunits;j++) - memset(&texcoord[j][0].t[0], 0, m->numverts * sizeof(buf_texcoord_t)); - #endif - - memcpy(fcolor, m->color, m->numverts * sizeof(buf_fcolor_t)); - - // do this as a second step because memcpy preloaded the cache, which we can't easily do - if (scaler != 1) - { - for (i = 0;i < m->numverts;i++) - { - fcolor[i].c[0] *= scaler; - fcolor[i].c[1] *= scaler; - fcolor[i].c[2] *= scaler; - } - } + return true; } -*/ void R_Mesh_DrawPolygon(rmeshinfo_t *m, int numverts) { diff --git a/gl_backend.h b/gl_backend.h index 2eaae8e8..1c0be7bd 100644 --- a/gl_backend.h +++ b/gl_backend.h @@ -17,8 +17,7 @@ typedef struct int vertexstep; float *color; int colorstep; - // if color is NULL, these are used for all vertices - float cr, cg, cb, ca; + float cr, cg, cb, ca; // if color is NULL, these are used for all vertices int tex[MAX_TEXTUREUNITS]; float *texcoords[MAX_TEXTUREUNITS]; int texcoordstep[MAX_TEXTUREUNITS]; @@ -26,6 +25,28 @@ typedef struct } rmeshinfo_t; +typedef struct +{ + //input to R_Mesh_Draw_GetBuffer + int transparent; + int depthwrite; // force depth writing enabled even if polygon is not opaque + int depthdisable; // disable depth read/write entirely + int blendfunc1; + int blendfunc2; + int numtriangles; + int numverts; + int tex[MAX_TEXTUREUNITS]; + float texrgbscale[MAX_TEXTUREUNITS]; // used only if COMBINE is present + + // output + int *index; + float *vertex; + float *color; + float colorscale; + float *texcoords[MAX_TEXTUREUNITS]; +} +rmeshbufferinfo_t; + // adds console variables and registers the render module (only call from GL_Init) void gl_backend_init(void); // sets up mesh renderer for the frame @@ -40,3 +61,6 @@ void R_Mesh_AddTransparent(void); void R_Mesh_DrawPolygon(rmeshinfo_t *m, int numverts); // same as normal, except for harsh format restrictions (vertex must be 4 float, color must be 4 float, texcoord must be 2 float, flat color not supported) void R_Mesh_Draw_NativeOnly(const rmeshinfo_t *m); +// allocates space in geometry buffers, and fills in pointers to the buffers in passsed struct +// (this is used for very high speed rendering, no copying) +int R_Mesh_Draw_GetBuffer(rmeshbufferinfo_t *m); diff --git a/gl_models.c b/gl_models.c index 07afa557..76862b2d 100644 --- a/gl_models.c +++ b/gl_models.c @@ -83,7 +83,7 @@ void gl_models_start(void) { // allocate vertex processing arrays gl_models_mempool = Mem_AllocPool("GL_Models"); - aliasvert = Mem_Alloc(gl_models_mempool, sizeof(float[MD2MAX_VERTS][3])); + aliasvert = Mem_Alloc(gl_models_mempool, sizeof(float[MD2MAX_VERTS][4])); aliasvertnorm = Mem_Alloc(gl_models_mempool, sizeof(float[MD2MAX_VERTS][3])); aliasvertcolor = Mem_Alloc(gl_models_mempool, sizeof(float[MD2MAX_VERTS][4])); aliasvertcolor2 = Mem_Alloc(gl_models_mempool, sizeof(float[MD2MAX_VERTS][4])); // used temporarily for tinted coloring @@ -119,10 +119,10 @@ void R_AliasTransformVerts(int vertcount) avn = aliasvertnorm; while (vertcount >= 4) { - VectorCopy(av, point);softwaretransform(point, av);av += 3; - VectorCopy(av, point);softwaretransform(point, av);av += 3; - VectorCopy(av, point);softwaretransform(point, av);av += 3; - VectorCopy(av, point);softwaretransform(point, av);av += 3; + VectorCopy(av, point);softwaretransform(point, av);av += 4; + VectorCopy(av, point);softwaretransform(point, av);av += 4; + VectorCopy(av, point);softwaretransform(point, av);av += 4; + VectorCopy(av, point);softwaretransform(point, av);av += 4; VectorCopy(avn, point);softwaretransformdirection(point, avn);avn += 3; VectorCopy(avn, point);softwaretransformdirection(point, avn);avn += 3; VectorCopy(avn, point);softwaretransformdirection(point, avn);avn += 3; @@ -131,7 +131,7 @@ void R_AliasTransformVerts(int vertcount) } while(vertcount > 0) { - VectorCopy(av, point);softwaretransform(point, av);av += 3; + VectorCopy(av, point);softwaretransform(point, av);av += 4; VectorCopy(avn, point);softwaretransformdirection(point, avn);avn += 3; vertcount--; } @@ -175,7 +175,7 @@ void R_AliasLerpVerts(int vertcount, avn[0] = n1[0] * lerp1 + n2[0] * lerp2 + n3[0] * lerp3 + n4[0] * lerp4; avn[1] = n1[1] * lerp1 + n2[1] * lerp2 + n3[1] * lerp3 + n4[1] * lerp4; avn[2] = n1[2] * lerp1 + n2[2] * lerp2 + n3[2] * lerp3 + n4[2] * lerp4; - av += 3; + av += 4; avn += 3; verts1++;verts2++;verts3++;verts4++; } @@ -197,7 +197,7 @@ void R_AliasLerpVerts(int vertcount, avn[0] = n1[0] * lerp1 + n2[0] * lerp2 + n3[0] * lerp3; avn[1] = n1[1] * lerp1 + n2[1] * lerp2 + n3[1] * lerp3; avn[2] = n1[2] * lerp1 + n2[2] * lerp2 + n3[2] * lerp3; - av += 3; + av += 4; avn += 3; verts1++;verts2++;verts3++; } @@ -219,7 +219,7 @@ void R_AliasLerpVerts(int vertcount, avn[0] = n1[0] * lerp1 + n2[0] * lerp2; avn[1] = n1[1] * lerp1 + n2[1] * lerp2; avn[2] = n1[2] * lerp1 + n2[2] * lerp2; - av += 3; + av += 4; avn += 3; verts1++;verts2++; } @@ -243,7 +243,7 @@ void R_AliasLerpVerts(int vertcount, avn[0] = n1[0] * lerp1; avn[1] = n1[1] * lerp1; avn[2] = n1[2] * lerp1; - av += 3; + av += 4; avn += 3; verts1++; } @@ -257,7 +257,7 @@ void R_AliasLerpVerts(int vertcount, av[1] = verts1->v[1] * scale1[1] + translate[1]; av[2] = verts1->v[2] * scale1[2] + translate[2]; VectorCopy(m_bytenormals[verts1->lightnormalindex], avn); - av += 3; + av += 4; avn += 3; verts1++; } @@ -329,7 +329,7 @@ void R_SetupMDLMD2Frames(skinframe_t **skinframe) R_LightModel(model->numverts); } -void R_DrawQ1AliasModel (void) +void R_DrawQ1Q2AliasModel (void) { float fog; vec3_t diff; @@ -343,12 +343,12 @@ void R_DrawQ1AliasModel (void) memset(&aliasmeshinfo, 0, sizeof(aliasmeshinfo)); aliasmeshinfo.vertex = aliasvert; - aliasmeshinfo.vertexstep = sizeof(float[3]); + aliasmeshinfo.vertexstep = sizeof(float[4]); aliasmeshinfo.numverts = model->numverts; aliasmeshinfo.numtriangles = model->numtris; - aliasmeshinfo.index = model->mdldata_indices; + aliasmeshinfo.index = model->mdlmd2data_indices; aliasmeshinfo.colorstep = sizeof(float[4]); - aliasmeshinfo.texcoords[0] = model->mdldata_texcoords; + aliasmeshinfo.texcoords[0] = model->mdlmd2data_texcoords; aliasmeshinfo.texcoordstep[0] = sizeof(float[2]); fog = 0; @@ -440,7 +440,7 @@ void R_DrawQ1AliasModel (void) else R_DrawModelMesh(0, NULL, 1 - fog, 1 - fog, 1 - fog); - if (fog) + if (fog && aliasmeshinfo.blendfunc2 != GL_ONE) { aliasmeshinfo.tex[0] = R_GetTexture(skinframe->fog); aliasmeshinfo.blendfunc1 = GL_SRC_ALPHA; @@ -457,128 +457,6 @@ void R_DrawQ1AliasModel (void) } } -void R_DrawQ2AliasModel (void) -{ - int *order, count; - vec3_t diff; - skinframe_t *skinframe; - model_t *model; - - model = currentrenderentity->model; - - R_SetupMDLMD2Frames(&skinframe); - - if (!r_render.integer) - return; - - // FIXME FIXME FIXME rewrite loader to convert to triangle mesh - glBindTexture(GL_TEXTURE_2D, R_GetTexture(skinframe->base)); - - if (currentrenderentity->effects & EF_ADDITIVE) - { - glBlendFunc(GL_SRC_ALPHA, GL_ONE); // additive rendering - glEnable(GL_BLEND); - glDepthMask(0); - } - else if (currentrenderentity->alpha != 1.0 || R_TextureHasAlpha(skinframe->base)) - { - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glEnable(GL_BLEND); - glDepthMask(0); - } - else - { - glDisable(GL_BLEND); - glDepthMask(1); - } - - // LordHavoc: big mess... - // using vertex arrays only slightly, although it is enough to prevent duplicates - // (saving half the transforms) - glVertexPointer(3, GL_FLOAT, sizeof(float[3]), aliasvert); - glColorPointer(4, GL_FLOAT, sizeof(float[4]), aliasvertcolor); - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_COLOR_ARRAY); - - GL_LockArray(0, model->numverts); - - order = model->md2data_glcmds; - while(1) - { - if (!(count = *order++)) - break; - if (count > 0) - glBegin(GL_TRIANGLE_STRIP); - else - { - glBegin(GL_TRIANGLE_FAN); - count = -count; - } - do - { - glTexCoord2f(((float *)order)[0], ((float *)order)[1]); - glArrayElement(order[2]); - order += 3; - } - while (count--); - } - - GL_UnlockArray(); - - glDisableClientState(GL_COLOR_ARRAY); - glDisableClientState(GL_VERTEX_ARRAY); - - if (fogenabled) - { - glDisable (GL_TEXTURE_2D); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glEnable (GL_BLEND); - glDepthMask(0); // disable zbuffer updates - - VectorSubtract(currentrenderentity->origin, r_origin, diff); - glColor4f(fogcolor[0], fogcolor[1], fogcolor[2], currentrenderentity->alpha * exp(fogdensity/DotProduct(diff,diff))); - - // LordHavoc: big mess... - // using vertex arrays only slightly, although it is enough to prevent duplicates - // (saving half the transforms) - glVertexPointer(3, GL_FLOAT, sizeof(float[3]), aliasvert); - glEnableClientState(GL_VERTEX_ARRAY); - - GL_LockArray(0, model->numverts); - - order = model->md2data_glcmds; - while(1) - { - if (!(count = *order++)) - break; - if (count > 0) - glBegin(GL_TRIANGLE_STRIP); - else - { - glBegin(GL_TRIANGLE_FAN); - count = -count; - } - do - { - glArrayElement(order[2]); - order += 3; - } - while (count--); - } - - GL_UnlockArray(); - - glDisableClientState(GL_VERTEX_ARRAY); - - glEnable (GL_TEXTURE_2D); - glColor3f (1,1,1); - } - - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glEnable (GL_BLEND); - glDepthMask(1); -} - int ZymoticLerpBones(int count, zymbonematrix *bonebase, frameblend_t *blend, zymbone_t *bone) { int i; @@ -789,7 +667,7 @@ void ZymoticTransformVerts(int vertcount, int *bonecounts, zymvertex_t *vert) vert++; } } - out += 3; + out += 4; } } @@ -807,9 +685,9 @@ void ZymoticCalcNormals(int vertcount, int shadercount, int *renderlist) d = *renderlist++; while (d--) { - a = renderlist[0]*3; - b = renderlist[1]*3; - c = renderlist[2]*3; + a = renderlist[0]*4; + b = renderlist[1]*4; + c = renderlist[2]*4; v1[0] = aliasvert[a+0] - aliasvert[b+0]; v1[1] = aliasvert[a+1] - aliasvert[b+1]; v1[2] = aliasvert[a+2] - aliasvert[b+2]; @@ -819,21 +697,25 @@ void ZymoticCalcNormals(int vertcount, int shadercount, int *renderlist) CrossProduct(v1, v2, normal); VectorNormalizeFast(normal); // add surface normal to vertices + a = renderlist[0] * 3; aliasvertnorm[a+0] += normal[0]; aliasvertnorm[a+1] += normal[1]; aliasvertnorm[a+2] += normal[2]; aliasvertusage[renderlist[0]]++; - aliasvertnorm[b+0] += normal[0]; - aliasvertnorm[b+1] += normal[1]; - aliasvertnorm[b+2] += normal[2]; + a = renderlist[1] * 3; + aliasvertnorm[a+0] += normal[0]; + aliasvertnorm[a+1] += normal[1]; + aliasvertnorm[a+2] += normal[2]; aliasvertusage[renderlist[1]]++; - aliasvertnorm[c+0] += normal[0]; - aliasvertnorm[c+1] += normal[1]; - aliasvertnorm[c+2] += normal[2]; + a = renderlist[2] * 3; + aliasvertnorm[a+0] += normal[0]; + aliasvertnorm[a+1] += normal[1]; + aliasvertnorm[a+2] += normal[2]; aliasvertusage[renderlist[2]]++; renderlist += 3; } } + // FIXME: precalc this // average surface normals out = aliasvertnorm; u = aliasvertusage; @@ -861,7 +743,7 @@ void R_DrawZymoticModelMesh(zymtype1header_t *m) texture = (rtexture_t **)(m->lump_shaders.start + (int) m); aliasmeshinfo.vertex = aliasvert; - aliasmeshinfo.vertexstep = sizeof(float[3]); + aliasmeshinfo.vertexstep = sizeof(float[4]); aliasmeshinfo.color = aliasvertcolor; aliasmeshinfo.colorstep = sizeof(float[4]); aliasmeshinfo.texcoords[0] = (float *)(m->lump_texcoords.start + (int) m); @@ -956,8 +838,6 @@ void R_DrawAliasModel (void) if (currentrenderentity->model->aliastype == ALIASTYPE_ZYM) R_DrawZymoticModel(); - else if (currentrenderentity->model->aliastype == ALIASTYPE_MD2) - R_DrawQ2AliasModel(); else - R_DrawQ1AliasModel(); + R_DrawQ1Q2AliasModel(); } diff --git a/gl_rsurf.c b/gl_rsurf.c index 07f800e8..4a8fe723 100644 --- a/gl_rsurf.c +++ b/gl_rsurf.c @@ -1425,6 +1425,8 @@ static void RSurfShader_Wall_Pass_Fog(msurface_t *s) static int RSurfShader_Wall_Fullbright(int stage, msurface_t *s) { + if (stage == 0) + c_brush_polys++; switch(stage) { case 0: @@ -1441,6 +1443,8 @@ static int RSurfShader_Wall_Fullbright(int stage, msurface_t *s) static int RSurfShader_Wall_Vertex(int stage, msurface_t *s) { + if (stage == 0) + c_brush_polys++; switch(stage) { case 0: @@ -1457,6 +1461,8 @@ static int RSurfShader_Wall_Vertex(int stage, msurface_t *s) static int RSurfShader_Wall_Lightmap(int stage, msurface_t *s) { + if (stage == 0) + c_brush_polys++; if (r_vertexsurfaces.integer) { switch(stage) diff --git a/model_alias.c b/model_alias.c index 7f2d0132..85c6ddd2 100644 --- a/model_alias.c +++ b/model_alias.c @@ -281,7 +281,7 @@ void Mod_LoadAliasModel (model_t *mod, void *buffer) loadmodel->name, version, ALIAS_VERSION); loadmodel->type = mod_alias; - loadmodel->aliastype = ALIASTYPE_MDL; + loadmodel->aliastype = ALIASTYPE_MDLMD2; loadmodel->numskins = LittleLong(pinmodel->numskins); BOUNDI(loadmodel->numskins,0,256); @@ -423,7 +423,7 @@ void Mod_LoadAliasModel (model_t *mod, void *buffer) } // load triangle data - loadmodel->mdldata_indices = Mem_Alloc(loadmodel->mempool, sizeof(int[3]) * loadmodel->numtris); + loadmodel->mdlmd2data_indices = Mem_Alloc(loadmodel->mempool, sizeof(int[3]) * loadmodel->numtris); // count the vertices used for (i = 0;i < numverts*2;i++) @@ -461,16 +461,16 @@ void Mod_LoadAliasModel (model_t *mod, void *buffer) // remap the triangle references for (i = 0;i < loadmodel->numtris;i++) { - loadmodel->mdldata_indices[i*3+0] = vertremap[temptris[i][0]]; - loadmodel->mdldata_indices[i*3+1] = vertremap[temptris[i][1]]; - loadmodel->mdldata_indices[i*3+2] = vertremap[temptris[i][2]]; + loadmodel->mdlmd2data_indices[i*3+0] = vertremap[temptris[i][0]]; + loadmodel->mdlmd2data_indices[i*3+1] = vertremap[temptris[i][1]]; + loadmodel->mdlmd2data_indices[i*3+2] = vertremap[temptris[i][2]]; } // store the texture coordinates - loadmodel->mdldata_texcoords = Mem_Alloc(loadmodel->mempool, sizeof(float[2]) * totalverts); + loadmodel->mdlmd2data_texcoords = Mem_Alloc(loadmodel->mempool, sizeof(float[2]) * totalverts); for (i = 0;i < totalverts;i++) { - loadmodel->mdldata_texcoords[i*2+0] = vertst[i][0]; - loadmodel->mdldata_texcoords[i*2+1] = vertst[i][1]; + loadmodel->mdlmd2data_texcoords[i*2+0] = vertst[i][0]; + loadmodel->mdlmd2data_texcoords[i*2+1] = vertst[i][1]; } // load the frames @@ -507,17 +507,19 @@ void Mod_LoadAliasModel (model_t *mod, void *buffer) loadmodel->DrawShadow = NULL; } -static void Mod_MD2_ConvertVerts (int numverts, vec3_t scale, vec3_t translate, trivertx_t *v, trivertx_t *out) +static void Mod_MD2_ConvertVerts (vec3_t scale, vec3_t translate, trivertx_t *v, trivertx_t *out, int *vertremap) { int i, invalidnormals = 0; float dist; + trivertx_t *in; vec3_t temp; - for (i = 0;i < numverts;i++) + for (i = 0;i < loadmodel->numverts;i++) { - VectorCopy(v[i].v, out[i].v); - temp[0] = v[i].v[0] * scale[0] + translate[0]; - temp[1] = v[i].v[1] * scale[1] + translate[1]; - temp[2] = v[i].v[2] * scale[2] + translate[2]; + in = v + vertremap[i]; + VectorCopy(in->v, out[i].v); + temp[0] = in->v[0] * scale[0] + translate[0]; + temp[1] = in->v[1] * scale[1] + translate[1]; + temp[2] = in->v[2] * scale[2] + translate[2]; // update bounding box if (temp[0] < aliasbboxmin[0]) aliasbboxmin[0] = temp[0]; if (temp[1] < aliasbboxmin[1]) aliasbboxmin[1] = temp[1]; @@ -531,7 +533,7 @@ static void Mod_MD2_ConvertVerts (int numverts, vec3_t scale, vec3_t translate, dist += temp[2]*temp[2]; if (modelradius < dist) modelradius = dist; - out[i].lightnormalindex = v[i].lightnormalindex; + out[i].lightnormalindex = in->lightnormalindex; if (out[i].lightnormalindex >= NUMVERTEXNORMALS) { invalidnormals++; @@ -542,58 +544,75 @@ static void Mod_MD2_ConvertVerts (int numverts, vec3_t scale, vec3_t translate, Con_Printf("Mod_MD2_ConvertVerts: \"%s\", %i invalid normal indices found\n", loadmodel->name, invalidnormals); } -void Mod_MD2_ReadHeader(md2_t *in, int *numglcmds) +void Mod_LoadQ2AliasModel (model_t *mod, void *buffer) { + int *vertremap; + md2_t *pinmodel; + long base; int version, end; + int i, j, k, hashindex, num, numxyz, numst, xyz, st; + float *stverts, s, t; + struct md2verthash_s + { + struct md2verthash_s *next; + int xyz; + float st[2]; + } + *hash, **md2verthash, *md2verthashdata; + long datapointer; + md2frame_t *pinframe; + char *inskin; + md2triangle_t *intri; + unsigned short *inst; + int skinwidth, skinheight; + + pinmodel = buffer; + base = (long) buffer; - version = LittleLong (in->version); + version = LittleLong (pinmodel->version); if (version != MD2ALIAS_VERSION) Host_Error ("%s has wrong version number (%i should be %i)", loadmodel->name, version, MD2ALIAS_VERSION); loadmodel->type = mod_alias; - loadmodel->aliastype = ALIASTYPE_MD2; + loadmodel->aliastype = ALIASTYPE_MDLMD2; loadmodel->SERAddEntity = Mod_Alias_SERAddEntity; loadmodel->Draw = R_DrawAliasModel; loadmodel->DrawSky = NULL; loadmodel->DrawShadow = NULL; - if (LittleLong(in->num_tris < 1) || LittleLong(in->num_tris) > MD2MAX_TRIANGLES) - Host_Error ("%s has invalid number of triangles: %i", loadmodel->name, LittleLong(in->num_tris)); - if (LittleLong(in->num_xyz < 1) || LittleLong(in->num_xyz) > MD2MAX_VERTS) - Host_Error ("%s has invalid number of vertices: %i", loadmodel->name, LittleLong(in->num_xyz)); - if (LittleLong(in->num_frames < 1) || LittleLong(in->num_frames) > MD2MAX_FRAMES) - Host_Error ("%s has invalid number of frames: %i", loadmodel->name, LittleLong(in->num_frames)); - if (LittleLong(in->num_skins < 0) || LittleLong(in->num_skins) > MAX_SKINS) - Host_Error ("%s has invalid number of skins: %i", loadmodel->name, LittleLong(in->num_skins)); - - end = LittleLong(in->ofs_end); - if (LittleLong(in->num_skins) >= 1 && (LittleLong(in->ofs_skins <= 0) || LittleLong(in->ofs_skins) >= end)) + if (LittleLong(pinmodel->num_tris < 1) || LittleLong(pinmodel->num_tris) > MD2MAX_TRIANGLES) + Host_Error ("%s has invalid number of triangles: %i", loadmodel->name, LittleLong(pinmodel->num_tris)); + if (LittleLong(pinmodel->num_xyz < 1) || LittleLong(pinmodel->num_xyz) > MD2MAX_VERTS) + Host_Error ("%s has invalid number of vertices: %i", loadmodel->name, LittleLong(pinmodel->num_xyz)); + if (LittleLong(pinmodel->num_frames < 1) || LittleLong(pinmodel->num_frames) > MD2MAX_FRAMES) + Host_Error ("%s has invalid number of frames: %i", loadmodel->name, LittleLong(pinmodel->num_frames)); + if (LittleLong(pinmodel->num_skins < 0) || LittleLong(pinmodel->num_skins) > MAX_SKINS) + Host_Error ("%s has invalid number of skins: %i", loadmodel->name, LittleLong(pinmodel->num_skins)); + + end = LittleLong(pinmodel->ofs_end); + if (LittleLong(pinmodel->num_skins) >= 1 && (LittleLong(pinmodel->ofs_skins <= 0) || LittleLong(pinmodel->ofs_skins) >= end)) Host_Error ("%s is not a valid model", loadmodel->name); - if (LittleLong(in->ofs_st <= 0) || LittleLong(in->ofs_st) >= end) + if (LittleLong(pinmodel->ofs_st <= 0) || LittleLong(pinmodel->ofs_st) >= end) Host_Error ("%s is not a valid model", loadmodel->name); - if (LittleLong(in->ofs_tris <= 0) || LittleLong(in->ofs_tris) >= end) + if (LittleLong(pinmodel->ofs_tris <= 0) || LittleLong(pinmodel->ofs_tris) >= end) Host_Error ("%s is not a valid model", loadmodel->name); - if (LittleLong(in->ofs_frames <= 0) || LittleLong(in->ofs_frames) >= end) + if (LittleLong(pinmodel->ofs_frames <= 0) || LittleLong(pinmodel->ofs_frames) >= end) Host_Error ("%s is not a valid model", loadmodel->name); - if (LittleLong(in->ofs_glcmds <= 0) || LittleLong(in->ofs_glcmds) >= end) + if (LittleLong(pinmodel->ofs_glcmds <= 0) || LittleLong(pinmodel->ofs_glcmds) >= end) Host_Error ("%s is not a valid model", loadmodel->name); - loadmodel->numskins = LittleLong(in->num_skins); - loadmodel->numverts = LittleLong(in->num_xyz); -// loadmodel->md2num_st = LittleLong(in->num_st); - loadmodel->numtris = LittleLong(in->num_tris); - loadmodel->numframes = LittleLong(in->num_frames); - *numglcmds = LittleLong(in->num_glcmds); + loadmodel->numskins = LittleLong(pinmodel->num_skins); + numxyz = LittleLong(pinmodel->num_xyz); + numst = LittleLong(pinmodel->num_st); + loadmodel->numtris = LittleLong(pinmodel->num_tris); + loadmodel->numframes = LittleLong(pinmodel->num_frames); loadmodel->flags = 0; // there are no MD2 flags loadmodel->synctype = ST_RAND; -} -void Mod_MD2_LoadSkins(char *in) -{ - int i; -// load the skins + // load the skins + inskin = (void*)(base + LittleLong(pinmodel->ofs_skins)); if (loadmodel->numskins) { loadmodel->skinscenes = Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins); @@ -604,51 +623,103 @@ void Mod_MD2_LoadSkins(char *in) loadmodel->skinscenes[i].framecount = 1; loadmodel->skinscenes[i].loop = true; loadmodel->skinscenes[i].framerate = 10; - loadmodel->skinframes[i].base = loadtextureimagewithmask (loadmodel->texturepool, in, 0, 0, true, r_mipskins.integer, true); + loadmodel->skinframes[i].base = loadtextureimagewithmask (loadmodel->texturepool, inskin, 0, 0, true, r_mipskins.integer, true); loadmodel->skinframes[i].fog = image_masktex; loadmodel->skinframes[i].pants = NULL; loadmodel->skinframes[i].shirt = NULL; loadmodel->skinframes[i].glow = NULL; loadmodel->skinframes[i].merged = NULL; - in += MD2MAX_SKINNAME; + inskin += MD2MAX_SKINNAME; } } -} -/* -void Mod_MD2_LoadTriangles(md2triangle_t *in) -{ - int i, j; - loadmodel->md2data_tris = Mem_Alloc(loadmodel->mempool, loadmodel->numtris * sizeof(md2triangle_t)); + // load the triangles and stvert data + inst = (void*)(base + LittleLong(pinmodel->ofs_st)); + intri = (void*)(base + LittleLong(pinmodel->ofs_tris)); + skinwidth = LittleLong(pinmodel->skinwidth); + skinheight = LittleLong(pinmodel->skinheight); + + stverts = Mem_Alloc(tempmempool, numst * sizeof(float[2])); + s = 1.0f / skinwidth; + t = 1.0f / skinheight; + for (i = 0;i < numst;i++) + { + j = (unsigned short) LittleShort(inst[i*2+0]); + k = (unsigned short) LittleShort(inst[i*2+1]); + if (j >= skinwidth || k >= skinheight) + { + Mem_Free(stverts); + Host_Error("Mod_MD2_LoadGeometry: invalid skin coordinate (%i %i) on vert %i of model %s\n", j, k, i, loadmodel->name); + } + stverts[i*2+0] = j * s; + stverts[i*2+1] = k * t; + } + + md2verthash = Mem_Alloc(tempmempool, 256 * sizeof(hash)); + md2verthashdata = Mem_Alloc(tempmempool, loadmodel->numtris * 3 * sizeof(*hash)); // swap the triangle list + num = 0; + loadmodel->mdlmd2data_indices = Mem_Alloc(loadmodel->mempool, loadmodel->numtris * sizeof(int[3])); for (i = 0;i < loadmodel->numtris;i++) { for (j = 0;j < 3;j++) { - loadmodel->md2data_tris[i].index_xyz[j] = LittleShort (in[i].index_xyz[j]); - loadmodel->md2data_tris[i].index_st[j] = LittleShort (in[i].index_st[j]); - if (loadmodel->md2data_tris[i].index_xyz[j] >= loadmodel->md2num_xyz) - Host_Error ("%s has invalid vertex indices", loadmodel->name); - if (loadmodel->md2data_tris[i].index_st[j] >= loadmodel->md2num_st) - Host_Error ("%s has invalid vertex indices", loadmodel->name); + xyz = (unsigned short) LittleShort (intri[i].index_xyz[j]); + st = (unsigned short) LittleShort (intri[i].index_st[j]); + if (xyz >= numxyz || st >= numst) + { + Mem_Free(md2verthash); + Mem_Free(md2verthashdata); + Mem_Free(stverts); + if (xyz >= numxyz) + Host_Error("Mod_MD2_LoadGeometry: invalid xyz index (%i) on triangle %i of model %s\n", xyz, i, loadmodel->name); + if (st >= numst) + Host_Error("Mod_MD2_LoadGeometry: invalid st index (%i) on triangle %i of model %s\n", st, i, loadmodel->name); + } + s = stverts[st*2+0]; + t = stverts[st*2+1]; + hashindex = (xyz * 17 + st) & 255; + for (hash = md2verthash[hashindex];hash;hash = hash->next) + if (hash->xyz == xyz && hash->st[0] == s && hash->st[1] == t) + break; + if (hash == NULL) + { + hash = md2verthashdata + num++; + hash->xyz = xyz; + hash->st[0] = s; + hash->st[1] = t; + hash->next = md2verthash[hashindex]; + md2verthash[hashindex] = hash; + } + loadmodel->mdlmd2data_indices[i*3+j] = (hash - md2verthashdata); } } -} -*/ -void Mod_MD2_LoadFrames(void *start) -{ - int i, j; - long datapointer; - md2frame_t *pinframe; + Mem_Free(stverts); + + loadmodel->numverts = num; + vertremap = Mem_Alloc(loadmodel->mempool, num * sizeof(int)); + loadmodel->mdlmd2data_texcoords = Mem_Alloc(loadmodel->mempool, num * sizeof(float[2])); + for (i = 0;i < num;i++) + { + hash = md2verthashdata + i; + vertremap[i] = hash->xyz; + loadmodel->mdlmd2data_texcoords[i*2+0] = hash->st[0]; + loadmodel->mdlmd2data_texcoords[i*2+1] = hash->st[1]; + } + + Mem_Free(md2verthash); + Mem_Free(md2verthashdata); + + // load frames // LordHavoc: doing proper bbox for model aliasbboxmin[0] = aliasbboxmin[1] = aliasbboxmin[2] = 1000000000; aliasbboxmax[0] = aliasbboxmax[1] = aliasbboxmax[2] = -1000000000; modelyawradius = 0; modelradius = 0; - datapointer = (long) start; -// load the frames + datapointer = (base + LittleLong(pinmodel->ofs_frames)); + // load the frames loadmodel->animscenes = Mem_Alloc(loadmodel->mempool, loadmodel->numframes * sizeof(animscene_t)); loadmodel->mdlmd2data_frames = Mem_Alloc(loadmodel->mempool, loadmodel->numframes * sizeof(md2frame_t)); loadmodel->mdlmd2data_pose = Mem_Alloc(loadmodel->mempool, loadmodel->numverts * loadmodel->numframes * sizeof(trivertx_t)); @@ -663,8 +734,8 @@ void Mod_MD2_LoadFrames(void *start) loadmodel->mdlmd2data_frames[i].scale[j] = LittleFloat(pinframe->scale[j]); loadmodel->mdlmd2data_frames[i].translate[j] = LittleFloat(pinframe->translate[j]); } - Mod_MD2_ConvertVerts (loadmodel->numverts, loadmodel->mdlmd2data_frames[i].scale, loadmodel->mdlmd2data_frames[i].translate, (void *)datapointer, &loadmodel->mdlmd2data_pose[i * loadmodel->numverts]); - datapointer += loadmodel->numverts * sizeof(trivertx_t); + Mod_MD2_ConvertVerts (loadmodel->mdlmd2data_frames[i].scale, loadmodel->mdlmd2data_frames[i].translate, (void *)datapointer, &loadmodel->mdlmd2data_pose[i * loadmodel->numverts], vertremap); + datapointer += numxyz * sizeof(trivertx_t); strcpy(loadmodel->animscenes[i].name, loadmodel->mdlmd2data_frames[i].name); loadmodel->animscenes[i].firstframe = i; @@ -673,6 +744,8 @@ void Mod_MD2_LoadFrames(void *start) loadmodel->animscenes[i].loop = true; } + Mem_Free(vertremap); + // LordHavoc: model bbox modelyawradius = sqrt(modelyawradius); modelradius = sqrt(modelradius); @@ -689,29 +762,6 @@ void Mod_MD2_LoadFrames(void *start) loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2]; } -void Mod_MD2_LoadGLCmds(int *in, int numglcmds) -{ - int i; - // load the draw list - loadmodel->md2data_glcmds = Mem_Alloc(loadmodel->mempool, numglcmds * sizeof(int)); - for (i = 0;i < numglcmds;i++) - loadmodel->md2data_glcmds[i] = LittleLong(in[i]); -} - -void Mod_LoadQ2AliasModel (model_t *mod, void *buffer) -{ - md2_t *pinmodel; - int numglcmds; - long base; - pinmodel = buffer; - base = (long) buffer; - Mod_MD2_ReadHeader(pinmodel, &numglcmds); - Mod_MD2_LoadSkins((void*)(base + LittleLong(pinmodel->ofs_skins))); -// Mod_MD2_LoadTriangles((void*)(base + LittleLong(pinmodel->ofs_tris))); - Mod_MD2_LoadFrames((void*)(base + LittleLong(pinmodel->ofs_frames))); - Mod_MD2_LoadGLCmds((void*)(base + LittleLong(pinmodel->ofs_glcmds)), numglcmds); -} - static void zymswapintblock(int *m, int size) { size /= 4; diff --git a/model_alias.h b/model_alias.h index 935bd546..664c7e30 100644 --- a/model_alias.h +++ b/model_alias.h @@ -155,9 +155,9 @@ typedef struct int ofs_end; // end of file } md2_t; -#define ALIASTYPE_MDL 1 -#define ALIASTYPE_MD2 2 -#define ALIASTYPE_ZYM 3 +// LordHavoc: Q1 and Q2 models are converted to the same internal format +#define ALIASTYPE_MDLMD2 1 +#define ALIASTYPE_ZYM 2 extern void Mod_LoadAliasModel (struct model_s *mod, void *buffer); extern void Mod_LoadQ2AliasModel (struct model_s *mod, void *buffer); diff --git a/model_shared.h b/model_shared.h index 1fe9adcc..6c2a336e 100644 --- a/model_shared.h +++ b/model_shared.h @@ -180,14 +180,9 @@ typedef struct model_s animscene_t *animscenes; // [numframes] - // Q2 model information -// md2triangle_t *md2data_tris; - // FIXME: redesign to use triangle mesh - int *md2data_glcmds; - - float *mdldata_texcoords; - int *mdldata_indices; - + // Q1 and Q2 models are the same after loading + int *mdlmd2data_indices; + float *mdlmd2data_texcoords; md2frame_t *mdlmd2data_frames; trivertx_t *mdlmd2data_pose; diff --git a/r_light.c b/r_light.c index b67dc484..2f8625d9 100644 --- a/r_light.c +++ b/r_light.c @@ -918,7 +918,7 @@ void R_LightModel(int numverts) VectorCopy(color, avc); avc[3] = a; avc += 4; - av += 3; + av += 4; avn += 3; } } -- 2.39.2