From 902f14e9a4773dd27a338562511f418763b903f7 Mon Sep 17 00:00:00 2001 From: havoc Date: Wed, 11 May 2005 18:22:48 +0000 Subject: [PATCH 1/1] the merging of alias and bsp model rendering begins... purely cosmetic changes in this first step merged model_alias_t into model_t and removed alias prefixes from those fields merged model_brush_t surface and texture stuff into model_t (num_surfaces, num_textures, etc) made alias model code use model_t data_surfaces instead of alias meshes git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@5270 d7cf8633-e32d-0410-b094-e92efae38249 --- gl_models.c | 56 ++- gl_rmain.c | 1196 +++++++++++++++++++++++++++++++++++++++++++++++ gl_rsurf.c | 1210 +----------------------------------------------- model_alias.c | 387 +++++++++------- model_alias.h | 43 +- model_brush.c | 110 ++--- model_brush.h | 110 +---- model_shared.c | 2 +- model_shared.h | 175 +++++-- portals.c | 2 +- pr_cmds.c | 6 +- prvm_cmds.c | 6 +- r_shadow.c | 4 +- render.h | 10 +- 14 files changed, 1681 insertions(+), 1636 deletions(-) diff --git a/gl_models.c b/gl_models.c index 850e90df..6bd61f43 100644 --- a/gl_models.c +++ b/gl_models.c @@ -3,7 +3,7 @@ #include "r_shadow.h" static texture_t r_aliasnotexture; -static texture_t *R_FetchAliasSkin(const entity_render_t *ent, const aliasmesh_t *mesh) +static texture_t *R_FetchAliasSkin(const entity_render_t *ent, const surfmesh_t *mesh) { model_t *model = ent->model; if (model->numskins) @@ -36,7 +36,8 @@ static void R_DrawAliasModelCallback (const void *calldata1, int calldata2) qbyte *bcolor; rmeshstate_t m; const entity_render_t *ent = calldata1; - aliasmesh_t *mesh = ent->model->alias.aliasdata_meshes + calldata2; + msurface_t *surface = ent->model->data_surfaces + calldata2; + surfmesh_t *mesh = surface->groupmesh; texture_t *texture; R_Mesh_Matrix(&ent->matrix); @@ -106,8 +107,8 @@ static void R_DrawAliasModelCallback (const void *calldata1, int calldata2) colorscale = 1.0f; if (ent->frameblend[0].frame == 0 && ent->frameblend[0].lerp == 1) { - vertex3f = mesh->data_basevertex3f; - normal3f = mesh->data_basenormal3f; + vertex3f = mesh->data_vertex3f; + normal3f = mesh->data_normal3f; } else { @@ -120,7 +121,7 @@ static void R_DrawAliasModelCallback (const void *calldata1, int calldata2) memset(&m, 0, sizeof(m)); m.pointer_vertex = vertex3f; - m.pointer_texcoord[0] = mesh->data_texcoord2f; + m.pointer_texcoord[0] = mesh->data_texcoordtexture2f; if (gl_combine.integer) { colorscale *= 0.25f; @@ -148,7 +149,7 @@ static void R_DrawAliasModelCallback (const void *calldata1, int calldata2) { doglow = false; m.tex[1] = R_GetTexture(texture->skin.glow); - m.pointer_texcoord[1] = mesh->data_texcoord2f; + m.pointer_texcoord[1] = mesh->data_texcoordtexture2f; m.texcombinergb[1] = GL_ADD; } R_Mesh_State(&m); @@ -249,26 +250,29 @@ static void R_DrawAliasModelCallback (const void *calldata1, int calldata2) void R_Model_Alias_Draw(entity_render_t *ent) { - int meshnum; - aliasmesh_t *mesh; + int surfacenum; + msurface_t *surface; + surfmesh_t *mesh; if (ent->alpha < (1.0f / 64.0f)) return; // basically completely transparent c_models++; - for (meshnum = 0, mesh = ent->model->alias.aliasdata_meshes;meshnum < ent->model->alias.aliasnum_meshes;meshnum++, mesh++) + for (surfacenum = 0, surface = ent->model->data_surfaces;surfacenum < ent->model->num_surfaces;surfacenum++, surface++) { + mesh = surface->groupmesh; if (ent->effects & EF_ADDITIVE || ent->alpha != 1.0 || R_FetchAliasSkin(ent, mesh)->skin.fog) - R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_vieworigin : ent->origin, R_DrawAliasModelCallback, ent, meshnum); + R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_vieworigin : ent->origin, R_DrawAliasModelCallback, ent, surfacenum); else - R_DrawAliasModelCallback(ent, meshnum); + R_DrawAliasModelCallback(ent, surfacenum); } } void R_Model_Alias_DrawShadowVolume(entity_render_t *ent, vec3_t relativelightorigin, float lightradius, int numsurfaces, const int *surfacelist, const vec3_t lightmins, const vec3_t lightmaxs) { - int meshnum; - aliasmesh_t *mesh; + int surfacenum; + msurface_t *surface; + surfmesh_t *mesh; texture_t *texture; float projectdistance, *vertex3f; if (!(ent->flags & RENDER_SHADOW)) @@ -279,13 +283,14 @@ void R_Model_Alias_DrawShadowVolume(entity_render_t *ent, vec3_t relativelightor projectdistance = lightradius + ent->model->radius;// - sqrt(DotProduct(relativelightorigin, relativelightorigin)); if (projectdistance > 0.1) { - for (meshnum = 0, mesh = ent->model->alias.aliasdata_meshes;meshnum < ent->model->alias.aliasnum_meshes;meshnum++, mesh++) + for (surfacenum = 0, surface = ent->model->data_surfaces;surfacenum < ent->model->num_surfaces;surfacenum++, surface++) { + mesh = surface->groupmesh; texture = R_FetchAliasSkin(ent, mesh); if (texture->skin.fog) continue; if (ent->frameblend[0].frame == 0 && ent->frameblend[0].lerp == 1) - vertex3f = mesh->data_basevertex3f; + vertex3f = mesh->data_vertex3f; else { vertex3f = varray_vertex3f; @@ -301,12 +306,14 @@ void R_Model_Alias_DrawShadowVolume(entity_render_t *ent, vec3_t relativelightor void R_Model_Alias_DrawLight(entity_render_t *ent, float *lightcolor, int numsurfaces, const int *surfacelist) { - int c, meshnum; + int c; float fog, ifog, lightcolorbase[3], lightcolorpants[3], lightcolorshirt[3]; float *vertex3f, *svector3f, *tvector3f, *normal3f; vec3_t diff; qbyte *bcolor; - aliasmesh_t *mesh; + int surfacenum; + msurface_t *surface; + surfmesh_t *mesh; texture_t *texture; fog = 0; @@ -356,18 +363,19 @@ void R_Model_Alias_DrawLight(entity_render_t *ent, float *lightcolor, int numsur } } - for (meshnum = 0, mesh = ent->model->alias.aliasdata_meshes;meshnum < ent->model->alias.aliasnum_meshes;meshnum++, mesh++) + for (surfacenum = 0, surface = ent->model->data_surfaces;surfacenum < ent->model->num_surfaces;surfacenum++, surface++) { + mesh = surface->groupmesh; texture = R_FetchAliasSkin(ent, mesh); // FIXME: transparent skins need to be lit during the transparent render if (texture->skin.fog) continue; if (ent->frameblend[0].frame == 0 && ent->frameblend[0].lerp == 1) { - vertex3f = mesh->data_basevertex3f; - svector3f = mesh->data_basesvector3f; - tvector3f = mesh->data_basetvector3f; - normal3f = mesh->data_basenormal3f; + vertex3f = mesh->data_vertex3f; + svector3f = mesh->data_svector3f; + tvector3f = mesh->data_tvector3f; + normal3f = mesh->data_normal3f; } else { @@ -376,10 +384,10 @@ void R_Model_Alias_DrawLight(entity_render_t *ent, float *lightcolor, int numsur tvector3f = varray_tvector3f; normal3f = varray_normal3f; Mod_Alias_GetMesh_Vertex3f(ent->model, ent->frameblend, mesh, vertex3f); - Mod_BuildTextureVectorsAndNormals(0, mesh->num_vertices, mesh->num_triangles, vertex3f, mesh->data_texcoord2f, mesh->data_element3i, svector3f, tvector3f, normal3f); + Mod_BuildTextureVectorsAndNormals(0, mesh->num_vertices, mesh->num_triangles, vertex3f, mesh->data_texcoordtexture2f, mesh->data_element3i, svector3f, tvector3f, normal3f); } c_alias_polys += mesh->num_triangles; - R_Shadow_RenderLighting(0, mesh->num_vertices, mesh->num_triangles, mesh->data_element3i, vertex3f, svector3f, tvector3f, normal3f, mesh->data_texcoord2f, lightcolorbase, lightcolorpants, lightcolorshirt, (ent->colormap >= 0 || !texture->skin.merged) ? texture->skin.base : texture->skin.merged, ent->colormap >= 0 ? texture->skin.pants : 0, ent->colormap >= 0 ? texture->skin.shirt : 0, texture->skin.nmap, texture->skin.gloss); + R_Shadow_RenderLighting(0, mesh->num_vertices, mesh->num_triangles, mesh->data_element3i, vertex3f, svector3f, tvector3f, normal3f, mesh->data_texcoordtexture2f, lightcolorbase, lightcolorpants, lightcolorshirt, (ent->colormap >= 0 || !texture->skin.merged) ? texture->skin.base : texture->skin.merged, ent->colormap >= 0 ? texture->skin.pants : 0, ent->colormap >= 0 ? texture->skin.shirt : 0, texture->skin.nmap, texture->skin.gloss); } } diff --git a/gl_rmain.c b/gl_rmain.c index f82c64bc..834017ca 100644 --- a/gl_rmain.c +++ b/gl_rmain.c @@ -107,6 +107,8 @@ cvar_t r_bloom_power = {CVAR_SAVE, "r_bloom_power", "4"}; cvar_t developer_texturelogging = {0, "developer_texturelogging", "1"}; +cvar_t gl_lightmaps = {0, "gl_lightmaps", "0"}; + rtexturepool_t *r_main_texturepool; rtexture_t *r_bloom_texture_screen; rtexture_t *r_bloom_texture_bloom; @@ -512,6 +514,7 @@ void GL_Main_Init(void) Cvar_RegisterVariable(&r_bloom_resolution); Cvar_RegisterVariable(&r_bloom_power); Cvar_RegisterVariable(&developer_texturelogging); + Cvar_RegisterVariable(&gl_lightmaps); if (gamemode == GAME_NEHAHRA || gamemode == GAME_NEXUIZ || gamemode == GAME_TENEBRAE) Cvar_SetValue("r_fullbrights", 0); R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap); @@ -1007,6 +1010,8 @@ static void R_BlendView(void) void R_RenderScene(void); +matrix4x4_t r_waterscrollmatrix; + /* ================ R_RenderView @@ -1083,6 +1088,8 @@ void R_RenderScene(void) GL_SetupView_Orientation_FromEntity(&r_view_matrix); + Matrix4x4_CreateTranslate(&r_waterscrollmatrix, sin(r_refdef.time) * 0.025 * r_waterscroll.value, sin(r_refdef.time * 0.8f) * 0.025 * r_waterscroll.value, 0); + R_SkyStartFrame(); R_WorldVisibility(); @@ -1444,4 +1451,1193 @@ void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *plane } } +void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t) +{ + // we don't need to set currentframe if t->animated is false because + // it was already set up by the texture loader for non-animating + if (t->animated) + { + t->currentframe = t->anim_frames[ent->frame != 0][(t->anim_total[ent->frame != 0] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[ent->frame != 0]) : 0]; + t = t->currentframe; + } + t->currentmaterialflags = t->basematerialflags; + t->currentalpha = ent->alpha; + if (t->basematerialflags & MATERIALFLAG_WATERALPHA) + t->currentalpha *= r_wateralpha.value; + if (!(ent->flags & RENDER_LIGHT)) + t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT; + if (ent->effects & EF_ADDITIVE) + t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_TRANSPARENT; + else if (t->currentalpha < 1) + t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_TRANSPARENT; +} + +void R_UpdateAllTextureInfo(entity_render_t *ent) +{ + int i; + if (ent->model) + for (i = 0;i < ent->model->num_textures;i++) + R_UpdateTextureInfo(ent, ent->model->data_textures + i); +} + +static void RSurf_DeformVertices(const entity_render_t *ent, const texture_t *texture, const msurface_t *surface, const vec3_t modelorg) +{ + int i, j; + float center[3], forward[3], right[3], up[3], v[4][3]; + matrix4x4_t matrix1, imatrix1; + if (texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE2) + { + // a single autosprite surface can contain multiple sprites... + VectorClear(forward); + VectorClear(right); + VectorSet(up, 0, 0, 1); + for (j = 0;j < surface->num_vertices - 3;j += 4) + { + VectorClear(center); + for (i = 0;i < 4;i++) + VectorAdd(center, (surface->groupmesh->data_vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center); + VectorScale(center, 0.25f, center); + // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out? + Matrix4x4_FromVectors(&matrix1, (surface->groupmesh->data_normal3f + 3 * surface->num_firstvertex) + j*3, (surface->groupmesh->data_svector3f + 3 * surface->num_firstvertex) + j*3, (surface->groupmesh->data_tvector3f + 3 * surface->num_firstvertex) + j*3, center); + Matrix4x4_Invert_Simple(&imatrix1, &matrix1); + for (i = 0;i < 4;i++) + Matrix4x4_Transform(&imatrix1, (surface->groupmesh->data_vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]); + forward[0] = modelorg[0] - center[0]; + forward[1] = modelorg[1] - center[1]; + VectorNormalize(forward); + right[0] = forward[1]; + right[1] = -forward[0]; + for (i = 0;i < 4;i++) + VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, varray_vertex3f + (surface->num_firstvertex+i+j) * 3); + } + } + else if (texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE) + { + Matrix4x4_Transform(&ent->inversematrix, r_viewforward, forward); + Matrix4x4_Transform(&ent->inversematrix, r_viewright, right); + Matrix4x4_Transform(&ent->inversematrix, r_viewup, up); + // a single autosprite surface can contain multiple sprites... + for (j = 0;j < surface->num_vertices - 3;j += 4) + { + VectorClear(center); + for (i = 0;i < 4;i++) + VectorAdd(center, (surface->groupmesh->data_vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center); + VectorScale(center, 0.25f, center); + // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out? + Matrix4x4_FromVectors(&matrix1, (surface->groupmesh->data_normal3f + 3 * surface->num_firstvertex) + j*3, (surface->groupmesh->data_svector3f + 3 * surface->num_firstvertex) + j*3, (surface->groupmesh->data_tvector3f + 3 * surface->num_firstvertex) + j*3, center); + Matrix4x4_Invert_Simple(&imatrix1, &matrix1); + for (i = 0;i < 4;i++) + Matrix4x4_Transform(&imatrix1, (surface->groupmesh->data_vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]); + for (i = 0;i < 4;i++) + VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, varray_vertex3f + (surface->num_firstvertex+i+j) * 3); + } + } + else + memcpy((varray_vertex3f + 3 * surface->num_firstvertex), (surface->groupmesh->data_vertex3f + 3 * surface->num_firstvertex), sizeof(float[3]) * surface->num_vertices); +} + +// any sort of deformvertices call is *VERY* rare, so this must be optimized +// to skip deformvertices quickly! +#if 1 +#define RSurf_GetVertexPointer(ent, texture, surface, modelorg) ((texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2)) ? (RSurf_DeformVertices(ent, texture, surface, modelorg), varray_vertex3f) : surface->groupmesh->data_vertex3f) +#else +static float *RSurf_GetVertexPointer(const entity_render_t *ent, const texture_t *texture, const msurface_t *surface, const vec3_t modelorg) +{ + if (texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2)) + { + RSurf_DeformVertices(ent, texture, surface, modelorg); + return varray_vertex3f; + } + else + return surface->groupmesh->data_vertex3f; +} +#endif + +static void R_DrawTextureSurfaceList(const entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg) +{ + int i; + int texturesurfaceindex; + const float *v, *vertex3f; + float *c; + float diff[3]; + float f, r, g, b, a, base, colorscale; + const msurface_t *surface; + qboolean dolightmap; + qboolean dobase; + qboolean doambient; + qboolean dodetail; + qboolean doglow; + qboolean dofogpass; + qboolean fogallpasses; + qboolean waterscrolling; + surfmesh_t *groupmesh; + rtexture_t *lightmaptexture; + rmeshstate_t m; + texture = texture->currentframe; + if (texture->currentmaterialflags & MATERIALFLAG_NODRAW) + return; + c_faces += texturenumsurfaces; + // gl_lightmaps debugging mode skips normal texturing + if (gl_lightmaps.integer) + { + GL_BlendFunc(GL_ONE, GL_ZERO); + GL_DepthMask(true); + GL_DepthTest(true); + qglDisable(GL_CULL_FACE); + GL_Color(1, 1, 1, 1); + memset(&m, 0, sizeof(m)); + R_Mesh_State(&m); + for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++) + { + surface = texturesurfacelist[texturesurfaceindex]; + R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture)); + R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f); + R_Mesh_ColorPointer(surface->lightmaptexture ? NULL : surface->groupmesh->data_lightmapcolor4f); + R_Mesh_VertexPointer(surface->groupmesh->data_vertex3f); + GL_LockArrays(surface->num_firstvertex, surface->num_vertices); + R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle)); + GL_LockArrays(0, 0); + } + qglEnable(GL_CULL_FACE); + return; + } + GL_DepthTest(!(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST)); + GL_DepthMask(!(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT)); + if (texture->currentmaterialflags & MATERIALFLAG_ADD) + GL_BlendFunc(GL_SRC_ALPHA, GL_ONE); + else if (texture->currentmaterialflags & MATERIALFLAG_ALPHA) + GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + else + GL_BlendFunc(GL_ONE, GL_ZERO); + // water waterscrolling in texture matrix + waterscrolling = (texture->currentmaterialflags & MATERIALFLAG_WATER) && r_waterscroll.value != 0; + if (texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) + qglDisable(GL_CULL_FACE); + if (texture->currentmaterialflags & MATERIALFLAG_SKY) + { + if (skyrendernow) + { + skyrendernow = false; + if (skyrendermasked) + R_Sky(); + } + // LordHavoc: HalfLife maps have freaky skypolys... + //if (!ent->model->brush.ishlbsp) + { + R_Mesh_Matrix(&ent->matrix); + GL_Color(fogcolor[0], fogcolor[1], fogcolor[2], 1); + if (skyrendermasked) + { + // depth-only (masking) + GL_ColorMask(0,0,0,0); + // just to make sure that braindead drivers don't draw anything + // despite that colormask... + GL_BlendFunc(GL_ZERO, GL_ONE); + } + else + { + // fog sky + GL_BlendFunc(GL_ONE, GL_ZERO); + } + GL_DepthMask(true); + GL_DepthTest(true); + memset(&m, 0, sizeof(m)); + R_Mesh_State(&m); + for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++) + { + surface = texturesurfacelist[texturesurfaceindex]; + R_Mesh_VertexPointer(surface->groupmesh->data_vertex3f); + GL_LockArrays(surface->num_firstvertex, surface->num_vertices); + R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle)); + GL_LockArrays(0, 0); + } + GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1); + } + } + else if ((texture->currentmaterialflags & MATERIALFLAG_WATER) && r_watershader.value && gl_textureshader && !texture->skin.glow && !fogenabled && ent->colormod[0] == 1 && ent->colormod[1] == 1 && ent->colormod[2] == 1) + { + // NVIDIA Geforce3 distortion texture shader on water + float args[4] = {0.05f,0,0,0.04f}; + memset(&m, 0, sizeof(m)); + m.tex[0] = R_GetTexture(r_texture_distorttexture[(int)(r_refdef.time * 16)&63]); + m.tex[1] = R_GetTexture(texture->skin.base); + m.texcombinergb[0] = GL_REPLACE; + m.texcombinergb[1] = GL_REPLACE; + Matrix4x4_CreateFromQuakeEntity(&m.texmatrix[0], 0, 0, 0, 0, 0, 0, r_watershader.value); + m.texmatrix[1] = r_waterscrollmatrix; + R_Mesh_State(&m); + + GL_Color(1, 1, 1, texture->currentalpha); + GL_ActiveTexture(0); + qglTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D); + GL_ActiveTexture(1); + qglTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_OFFSET_TEXTURE_2D_NV); + qglTexEnvi(GL_TEXTURE_SHADER_NV, GL_PREVIOUS_TEXTURE_INPUT_NV, GL_TEXTURE0_ARB); + qglTexEnvfv(GL_TEXTURE_SHADER_NV, GL_OFFSET_TEXTURE_MATRIX_NV, &args[0]); + qglEnable(GL_TEXTURE_SHADER_NV); + + for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++) + { + surface = texturesurfacelist[texturesurfaceindex]; + R_Mesh_VertexPointer(RSurf_GetVertexPointer(ent, texture, surface, modelorg)); + R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f); + R_Mesh_TexCoordPointer(1, 2, surface->groupmesh->data_texcoordtexture2f); + GL_LockArrays(surface->num_firstvertex, surface->num_vertices); + R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle)); + GL_LockArrays(0, 0); + } + + qglDisable(GL_TEXTURE_SHADER_NV); + qglTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D); + GL_ActiveTexture(0); + } + else if (texture->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL)) + { + // normal surface (wall or water) + dobase = true; + dolightmap = !(texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT); + doambient = r_ambient.value >= (1/64.0f); + dodetail = r_detailtextures.integer && texture->skin.detail != NULL && !(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT); + doglow = texture->skin.glow != NULL; + dofogpass = fogenabled && !(texture->currentmaterialflags & MATERIALFLAG_ADD); + fogallpasses = fogenabled && !(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT); + if (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT) + { + if (dobase && dolightmap && gl_combine.integer) + { + dobase = false; + memset(&m, 0, sizeof(m)); + m.tex[1] = R_GetTexture(texture->skin.base); + if (waterscrolling) + m.texmatrix[1] = r_waterscrollmatrix; + m.texrgbscale[1] = 2; + m.pointer_color = varray_color4f; + R_Mesh_State(&m); + colorscale = 1; + r = ent->colormod[0] * colorscale; + g = ent->colormod[1] * colorscale; + b = ent->colormod[2] * colorscale; + a = texture->currentalpha; + base = r_ambient.value * (1.0f / 64.0f); + // q3bsp has no lightmap updates, so the lightstylevalue that + // would normally be baked into the lightmaptexture must be + // applied to the color + if (ent->model->brushq1.lightdata) + { + float scale = d_lightstylevalue[0] * (1.0f / 128.0f); + r *= scale; + g *= scale; + b *= scale; + } + for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++) + { + surface = texturesurfacelist[texturesurfaceindex]; + vertex3f = RSurf_GetVertexPointer(ent, texture, surface, modelorg); + R_Mesh_VertexPointer(vertex3f); + R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f); + R_Mesh_TexCoordPointer(1, 2, surface->groupmesh->data_texcoordtexture2f); + if (surface->lightmaptexture) + { + R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture)); + if (fogallpasses) + { + R_Mesh_ColorPointer(varray_color4f); + for (i = 0, v = (vertex3f + 3 * surface->num_firstvertex), c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4) + { + VectorSubtract(v, modelorg, diff); + f = 1 - exp(fogdensity/DotProduct(diff, diff)); + c[0] = f * r; + c[1] = f * g; + c[2] = f * b; + c[3] = a; + } + } + else + { + R_Mesh_ColorPointer(NULL); + GL_Color(r, g, b, a); + } + } + else + { + R_Mesh_TexBind(0, R_GetTexture(r_texture_white)); + R_Mesh_ColorPointer(varray_color4f); + if (!surface->lightmaptexture) + { + for (i = 0, c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, c += 4) + { + c[0] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+0] * r; + c[1] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+1] * g; + c[2] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+2] * b; + c[3] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+3] * a; + } + if (fogallpasses) + { + for (i = 0, v = (vertex3f + 3 * surface->num_firstvertex), c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4) + { + VectorSubtract(v, modelorg, diff); + f = 1 - exp(fogdensity/DotProduct(diff, diff)); + VectorScale(c, f, c); + } + } + } + else + { + R_Mesh_ColorPointer(NULL); + GL_Color(0, 0, 0, a); + } + } + GL_LockArrays(surface->num_firstvertex, surface->num_vertices); + R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle)); + GL_LockArrays(0, 0); + } + } + if (dobase) + { + dobase = false; + memset(&m, 0, sizeof(m)); + m.tex[0] = R_GetTexture(texture->skin.base); + if (waterscrolling) + m.texmatrix[0] = r_waterscrollmatrix; + m.pointer_color = varray_color4f; + colorscale = 1; + if (gl_combine.integer) + { + m.texrgbscale[0] = 4; + colorscale *= 0.25f; + } + R_Mesh_State(&m); + r = ent->colormod[0] * colorscale; + g = ent->colormod[1] * colorscale; + b = ent->colormod[2] * colorscale; + a = texture->currentalpha; + if (dolightmap) + { + // q3bsp has no lightmap updates, so the lightstylevalue that + // would normally be baked into the lightmaptexture must be + // applied to the color + if (!ent->model->brushq1.lightdata) + { + float scale = d_lightstylevalue[0] * (1.0f / 128.0f); + r *= scale; + g *= scale; + b *= scale; + } + for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++) + { + surface = texturesurfacelist[texturesurfaceindex]; + vertex3f = RSurf_GetVertexPointer(ent, texture, surface, modelorg); + R_Mesh_VertexPointer(vertex3f); + R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f); + for (i = 0, v = (vertex3f + 3 * surface->num_firstvertex), c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4) + { + c[0] = 0; + c[1] = 0; + c[2] = 0; + if (!surface->lightmapinfo) + VectorCopy((surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex) + i*4, c); + else //if (surface->lightmapinfo) + { + const qbyte *lm = surface->lightmapinfo->samples + (surface->groupmesh->data_lightmapoffsets + surface->num_firstvertex)[i]; + float scale = d_lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f); + VectorMA(c, scale, lm, c); + if (surface->lightmapinfo->styles[1] != 255) + { + int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3; + lm += size3; + scale = d_lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f); + VectorMA(c, scale, lm, c); + if (surface->lightmapinfo->styles[2] != 255) + { + lm += size3; + scale = d_lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f); + VectorMA(c, scale, lm, c); + if (surface->lightmapinfo->styles[3] != 255) + { + lm += size3; + scale = d_lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f); + VectorMA(c, scale, lm, c); + } + } + } + } + c[0] *= r; + c[1] *= g; + c[2] *= b; + if (fogallpasses) + { + VectorSubtract(v, modelorg, diff); + f = 1 - exp(fogdensity/DotProduct(diff, diff)); + VectorScale(c, f, c); + } + if (!surface->lightmapinfo && (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT)) + c[3] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+3] * a; + else + c[3] = a; + } + GL_LockArrays(surface->num_firstvertex, surface->num_vertices); + R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle)); + GL_LockArrays(0, 0); + } + } + else + { + if (fogallpasses) + { + for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++) + { + surface = texturesurfacelist[texturesurfaceindex]; + vertex3f = RSurf_GetVertexPointer(ent, texture, surface, modelorg); + R_Mesh_VertexPointer(vertex3f); + R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f); + if (!surface->lightmapinfo && (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT)) + { + R_Mesh_ColorPointer(varray_color4f); + for (i = 0, v = (vertex3f + 3 * surface->num_firstvertex), c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4) + { + VectorSubtract(v, modelorg, diff); + f = 1 - exp(fogdensity/DotProduct(diff, diff)); + c[0] = r * f; + c[1] = g * f; + c[2] = b * f; + c[3] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+3] * a; + } + } + else + { + R_Mesh_ColorPointer(varray_color4f); + for (i = 0, v = (vertex3f + 3 * surface->num_firstvertex), c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4) + { + VectorSubtract(v, modelorg, diff); + f = 1 - exp(fogdensity/DotProduct(diff, diff)); + c[0] = r * f; + c[1] = g * f; + c[2] = b * f; + c[3] = a; + } + } + GL_LockArrays(surface->num_firstvertex, surface->num_vertices); + R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle)); + GL_LockArrays(0, 0); + } + } + else + { + for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++) + { + surface = texturesurfacelist[texturesurfaceindex]; + vertex3f = RSurf_GetVertexPointer(ent, texture, surface, modelorg); + R_Mesh_VertexPointer(vertex3f); + R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f); + if (!surface->lightmaptexture && (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT)) + { + R_Mesh_ColorPointer(varray_color4f); + for (i = 0, v = (vertex3f + 3 * surface->num_firstvertex), c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4) + { + c[0] = r; + c[1] = g; + c[2] = b; + c[3] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+3] * a; + } + } + else + { + R_Mesh_ColorPointer(NULL); + GL_Color(r, g, b, a); + } + GL_LockArrays(surface->num_firstvertex, surface->num_vertices); + R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle)); + GL_LockArrays(0, 0); + } + } + } + } + } + else + { + if (!dolightmap && dobase) + { + dolightmap = false; + dobase = false; + GL_Color(ent->colormod[0], ent->colormod[1], ent->colormod[2], 1); + memset(&m, 0, sizeof(m)); + m.tex[0] = R_GetTexture(texture->skin.base); + if (waterscrolling) + m.texmatrix[0] = r_waterscrollmatrix; + R_Mesh_State(&m); + for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++) + { + surface = texturesurfacelist[texturesurfaceindex]; + R_Mesh_VertexPointer(RSurf_GetVertexPointer(ent, texture, surface, modelorg)); + R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f); + GL_LockArrays(surface->num_firstvertex, surface->num_vertices); + R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle)); + GL_LockArrays(0, 0); + } + } + if (r_lightmapintensity <= 0 && dolightmap && dobase) + { + dolightmap = false; + dobase = false; + GL_Color(0, 0, 0, 1); + memset(&m, 0, sizeof(m)); + R_Mesh_State(&m); + for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++) + { + surface = texturesurfacelist[texturesurfaceindex]; + R_Mesh_VertexPointer(RSurf_GetVertexPointer(ent, texture, surface, modelorg)); + GL_LockArrays(surface->num_firstvertex, surface->num_vertices); + R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle)); + GL_LockArrays(0, 0); + } + } + if (r_textureunits.integer >= 2 && gl_combine.integer && dolightmap && dobase) + { + // dualtexture combine + GL_BlendFunc(GL_ONE, GL_ZERO); + GL_DepthMask(true); + dolightmap = false; + dobase = false; + memset(&m, 0, sizeof(m)); + m.tex[1] = R_GetTexture(texture->skin.base); + if (waterscrolling) + m.texmatrix[1] = r_waterscrollmatrix; + m.texrgbscale[1] = 2; + R_Mesh_State(&m); + r = ent->colormod[0] * r_lightmapintensity; + g = ent->colormod[1] * r_lightmapintensity; + b = ent->colormod[2] * r_lightmapintensity; + GL_Color(r, g, b, 1); + if (texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2)) + { + R_Mesh_VertexPointer(varray_vertex3f); + if (r == 1 && g == 1 && b == 1) + { + for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++) + { + surface = texturesurfacelist[texturesurfaceindex]; + RSurf_DeformVertices(ent, texture, surface, modelorg); + R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f); + R_Mesh_TexCoordPointer(1, 2, surface->groupmesh->data_texcoordtexture2f); + if (surface->lightmaptexture) + { + R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture)); + R_Mesh_ColorPointer(NULL); + } + else //if (r == 1 && g == 1 && b == 1) + { + R_Mesh_TexBind(0, R_GetTexture(r_texture_white)); + R_Mesh_ColorPointer(surface->groupmesh->data_lightmapcolor4f); + } + GL_LockArrays(surface->num_firstvertex, surface->num_vertices); + R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle)); + GL_LockArrays(0, 0); + } + } + else + { + for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++) + { + surface = texturesurfacelist[texturesurfaceindex]; + RSurf_DeformVertices(ent, texture, surface, modelorg); + R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f); + R_Mesh_TexCoordPointer(1, 2, surface->groupmesh->data_texcoordtexture2f); + if (surface->lightmaptexture) + { + R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture)); + R_Mesh_ColorPointer(NULL); + } + else + { + R_Mesh_TexBind(0, R_GetTexture(r_texture_white)); + R_Mesh_ColorPointer(varray_color4f); + for (i = 0, c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, c += 4) + { + c[0] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+0] * r; + c[1] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+1] * g; + c[2] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+2] * b; + c[3] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+3]; + } + } + GL_LockArrays(surface->num_firstvertex, surface->num_vertices); + R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle)); + GL_LockArrays(0, 0); + } + } + } + else + { + if (r == 1 && g == 1 && b == 1) + { +#if 0 + // experimental direct state calls for measuring + // R_Mesh_ call overhead, do not use! + R_Mesh_VertexPointer(varray_vertex3f); + R_Mesh_TexCoordPointer(0, 2, varray_texcoord2f[0]); + R_Mesh_TexCoordPointer(1, 2, varray_texcoord2f[1]); + R_Mesh_TexBind(0, R_GetTexture(r_texture_white)); + R_Mesh_ColorPointer(varray_color4f); + for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++) + { + surface = texturesurfacelist[texturesurfaceindex]; + qglVertexPointer(3, GL_FLOAT, sizeof(float[3]), surface->groupmesh->data_vertex3f); + qglClientActiveTexture(GL_TEXTURE0_ARB); + qglTexCoordPointer(2, GL_FLOAT, sizeof(float[2]), surface->groupmesh->data_texcoordlightmap2f); + qglClientActiveTexture(GL_TEXTURE1_ARB); + qglTexCoordPointer(2, GL_FLOAT, sizeof(float[2]), surface->groupmesh->data_texcoordtexture2f); + if (surface->lightmaptexture) + { + R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture)); + qglDisableClientState(GL_COLOR_ARRAY); + qglColor4f(r, g, b, 1); + } + else //if (r == 1 && g == 1 && b == 1) + { + R_Mesh_TexBind(0, R_GetTexture(r_texture_white)); + qglEnableClientState(GL_COLOR_ARRAY); + qglColorPointer(4, GL_FLOAT, sizeof(float[4]), surface->groupmesh->data_lightmapcolor4f); + } + qglLockArraysEXT(0, surface->num_vertices); + qglDrawRangeElements(GL_TRIANGLES, surface->num_firstvertex, surface->num_firstvertex + surface->num_vertices, surface->num_triangles * 3, GL_UNSIGNED_INT, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle)); + qglUnlockArraysEXT(); + } +#else + groupmesh = NULL; + lightmaptexture = NULL; + for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++) + { + surface = texturesurfacelist[texturesurfaceindex]; + if (groupmesh != surface->groupmesh) + { + groupmesh = surface->groupmesh; + R_Mesh_VertexPointer(groupmesh->data_vertex3f); + R_Mesh_TexCoordPointer(0, 2, groupmesh->data_texcoordlightmap2f); + R_Mesh_TexCoordPointer(1, 2, groupmesh->data_texcoordtexture2f); + if (!lightmaptexture) + R_Mesh_ColorPointer(groupmesh->data_lightmapcolor4f); + } + if (lightmaptexture != surface->lightmaptexture) + { + lightmaptexture = surface->lightmaptexture; + if (lightmaptexture) + { + R_Mesh_TexBind(0, R_GetTexture(lightmaptexture)); + R_Mesh_ColorPointer(NULL); + } + else //if (r == 1 && g == 1 && b == 1) + { + R_Mesh_TexBind(0, R_GetTexture(r_texture_white)); + R_Mesh_ColorPointer(surface->groupmesh->data_lightmapcolor4f); + } + } + GL_LockArrays(surface->num_firstvertex, surface->num_vertices); + R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle)); + GL_LockArrays(0, 0); + } +#endif + } + else + { + for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++) + { + surface = texturesurfacelist[texturesurfaceindex]; + R_Mesh_VertexPointer(surface->groupmesh->data_vertex3f); + R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f); + R_Mesh_TexCoordPointer(1, 2, surface->groupmesh->data_texcoordtexture2f); + if (surface->lightmaptexture) + { + R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture)); + R_Mesh_ColorPointer(NULL); + } + else + { + R_Mesh_TexBind(0, R_GetTexture(r_texture_white)); + R_Mesh_ColorPointer(varray_color4f); + for (i = 0, c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, c += 4) + { + c[0] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+0] * r; + c[1] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+1] * g; + c[2] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+2] * b; + c[3] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+3]; + } + } + GL_LockArrays(surface->num_firstvertex, surface->num_vertices); + R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle)); + GL_LockArrays(0, 0); + } + } + } + } + // single texture + if (dolightmap) + { + GL_BlendFunc(GL_ONE, GL_ZERO); + GL_DepthMask(true); + GL_Color(1, 1, 1, 1); + memset(&m, 0, sizeof(m)); + R_Mesh_State(&m); + if (texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2)) + { + R_Mesh_VertexPointer(varray_vertex3f); + for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++) + { + surface = texturesurfacelist[texturesurfaceindex]; + RSurf_DeformVertices(ent, texture, surface, modelorg); + R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f); + if (surface->lightmaptexture) + { + R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture)); + R_Mesh_ColorPointer(NULL); + } + else //if (r == 1 && g == 1 && b == 1) + { + R_Mesh_TexBind(0, R_GetTexture(r_texture_white)); + R_Mesh_ColorPointer(surface->groupmesh->data_lightmapcolor4f); + } + GL_LockArrays(surface->num_firstvertex, surface->num_vertices); + R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle)); + GL_LockArrays(0, 0); + } + } + else + { + groupmesh = NULL; + lightmaptexture = NULL; + for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++) + { + surface = texturesurfacelist[texturesurfaceindex]; + if (groupmesh != surface->groupmesh) + { + groupmesh = surface->groupmesh; + R_Mesh_VertexPointer(groupmesh->data_vertex3f); + R_Mesh_TexCoordPointer(0, 2, groupmesh->data_texcoordlightmap2f); + if (!lightmaptexture) + R_Mesh_ColorPointer(groupmesh->data_lightmapcolor4f); + } + if (lightmaptexture != surface->lightmaptexture) + { + lightmaptexture = surface->lightmaptexture; + if (lightmaptexture) + { + R_Mesh_TexBind(0, R_GetTexture(lightmaptexture)); + R_Mesh_ColorPointer(NULL); + } + else //if (r == 1 && g == 1 && b == 1) + { + R_Mesh_TexBind(0, R_GetTexture(r_texture_white)); + R_Mesh_ColorPointer(surface->groupmesh->data_lightmapcolor4f); + } + } + GL_LockArrays(surface->num_firstvertex, surface->num_vertices); + R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle)); + GL_LockArrays(0, 0); + } + } + } + if (dobase) + { + GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR); + GL_DepthMask(false); + GL_Color(r_lightmapintensity * ent->colormod[0], r_lightmapintensity * ent->colormod[1], r_lightmapintensity * ent->colormod[2], 1); + memset(&m, 0, sizeof(m)); + m.tex[0] = R_GetTexture(texture->skin.base); + if (waterscrolling) + m.texmatrix[0] = r_waterscrollmatrix; + R_Mesh_State(&m); + if (texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2)) + { + R_Mesh_VertexPointer(varray_vertex3f); + for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++) + { + surface = texturesurfacelist[texturesurfaceindex]; + RSurf_DeformVertices(ent, texture, surface, modelorg); + R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f); + GL_LockArrays(surface->num_firstvertex, surface->num_vertices); + R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle)); + GL_LockArrays(0, 0); + } + } + else + { + groupmesh = NULL; + for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++) + { + surface = texturesurfacelist[texturesurfaceindex]; + if (groupmesh != surface->groupmesh) + { + groupmesh = surface->groupmesh; + R_Mesh_VertexPointer(groupmesh->data_vertex3f); + R_Mesh_TexCoordPointer(0, 2, groupmesh->data_texcoordtexture2f); + } + GL_LockArrays(surface->num_firstvertex, surface->num_vertices); + R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle)); + GL_LockArrays(0, 0); + } + } + } + } + if (doambient) + { + doambient = false; + GL_BlendFunc(GL_SRC_ALPHA, GL_ONE); + GL_DepthMask(false); + memset(&m, 0, sizeof(m)); + m.tex[0] = R_GetTexture(texture->skin.base); + if (waterscrolling) + m.texmatrix[0] = r_waterscrollmatrix; + m.pointer_color = varray_color4f; + colorscale = 1; + if (gl_combine.integer) + { + m.texrgbscale[0] = 4; + colorscale *= 0.25f; + } + R_Mesh_State(&m); + base = r_ambient.value * (1.0f / 64.0f); + r = ent->colormod[0] * colorscale * base; + g = ent->colormod[1] * colorscale * base; + b = ent->colormod[2] * colorscale * base; + a = texture->currentalpha; + for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++) + { + surface = texturesurfacelist[texturesurfaceindex]; + vertex3f = RSurf_GetVertexPointer(ent, texture, surface, modelorg); + R_Mesh_VertexPointer(vertex3f); + R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f); + for (i = 0, v = (vertex3f + 3 * surface->num_firstvertex), c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4) + { + c[0] = r; + c[1] = g; + c[2] = b; + if (fogallpasses) + { + VectorSubtract(v, modelorg, diff); + f = 1 - exp(fogdensity/DotProduct(diff, diff)); + VectorScale(c, f, c); + } + if (!surface->lightmaptexture && surface->groupmesh->data_lightmapcolor4f && (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT)) + c[3] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+3] * a; + else + c[3] = a; + } + GL_LockArrays(surface->num_firstvertex, surface->num_vertices); + R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle)); + GL_LockArrays(0, 0); + } + } + if (dodetail) + { + GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR); + GL_DepthMask(false); + GL_Color(1, 1, 1, 1); + memset(&m, 0, sizeof(m)); + m.tex[0] = R_GetTexture(texture->skin.detail); + R_Mesh_State(&m); + for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++) + { + surface = texturesurfacelist[texturesurfaceindex]; + R_Mesh_VertexPointer(RSurf_GetVertexPointer(ent, texture, surface, modelorg)); + R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoorddetail2f); + GL_LockArrays(surface->num_firstvertex, surface->num_vertices); + R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle)); + GL_LockArrays(0, 0); + } + } + if (doglow) + { + // if glow was not already done using multitexture, do it now. + GL_BlendFunc(GL_SRC_ALPHA, GL_ONE); + GL_DepthMask(false); + memset(&m, 0, sizeof(m)); + m.tex[0] = R_GetTexture(texture->skin.glow); + if (waterscrolling) + m.texmatrix[0] = r_waterscrollmatrix; + m.pointer_color = varray_color4f; + R_Mesh_State(&m); + colorscale = 1; + r = ent->colormod[0] * colorscale; + g = ent->colormod[1] * colorscale; + b = ent->colormod[2] * colorscale; + a = texture->currentalpha; + if (fogallpasses) + { + for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++) + { + surface = texturesurfacelist[texturesurfaceindex]; + vertex3f = RSurf_GetVertexPointer(ent, texture, surface, modelorg); + R_Mesh_VertexPointer(vertex3f); + R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f); + R_Mesh_ColorPointer(varray_color4f); + if (!surface->lightmaptexture && surface->groupmesh->data_lightmapcolor4f && (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT)) + { + for (i = 0, v = (vertex3f + 3 * surface->num_firstvertex), c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4) + { + VectorSubtract(v, modelorg, diff); + f = 1 - exp(fogdensity/DotProduct(diff, diff)); + c[0] = f * r; + c[1] = f * g; + c[2] = f * b; + c[3] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+3] * a; + } + } + else + { + for (i = 0, v = (vertex3f + 3 * surface->num_firstvertex), c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4) + { + VectorSubtract(v, modelorg, diff); + f = 1 - exp(fogdensity/DotProduct(diff, diff)); + c[0] = f * r; + c[1] = f * g; + c[2] = f * b; + c[3] = a; + } + } + GL_LockArrays(surface->num_firstvertex, surface->num_vertices); + R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle)); + GL_LockArrays(0, 0); + } + } + else + { + for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++) + { + surface = texturesurfacelist[texturesurfaceindex]; + vertex3f = RSurf_GetVertexPointer(ent, texture, surface, modelorg); + R_Mesh_VertexPointer(vertex3f); + R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f); + if (!surface->lightmaptexture && surface->groupmesh->data_lightmapcolor4f && (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT)) + { + R_Mesh_ColorPointer(varray_color4f); + for (i = 0, v = (vertex3f + 3 * surface->num_firstvertex), c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4) + { + c[0] = r; + c[1] = g; + c[2] = b; + c[3] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+3] * a; + } + } + else + { + R_Mesh_ColorPointer(NULL); + GL_Color(r, g, b, a); + } + GL_LockArrays(surface->num_firstvertex, surface->num_vertices); + R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle)); + GL_LockArrays(0, 0); + } + } + } + if (dofogpass) + { + // if this is opaque use alpha blend which will darken the earlier + // passes cheaply. + // + // if this is an alpha blended material, all the earlier passes + // were darkened by fog already, so we only need to add the fog + // color ontop through the fog mask texture + // + // if this is an additive blended material, all the earlier passes + // were darkened by fog already, and we should not add fog color + // (because the background was not darkened, there is no fog color + // that was lost behind it). + if (!fogallpasses) + GL_BlendFunc(GL_SRC_ALPHA, GL_ONE); + else + GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + GL_DepthMask(false); + memset(&m, 0, sizeof(m)); + m.tex[0] = R_GetTexture(texture->skin.fog); + if (waterscrolling) + m.texmatrix[0] = r_waterscrollmatrix; + R_Mesh_State(&m); + r = fogcolor[0]; + g = fogcolor[1]; + b = fogcolor[2]; + a = texture->currentalpha; + for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++) + { + surface = texturesurfacelist[texturesurfaceindex]; + vertex3f = RSurf_GetVertexPointer(ent, texture, surface, modelorg); + R_Mesh_VertexPointer(vertex3f); + R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f); + R_Mesh_ColorPointer(varray_color4f); + //RSurf_FogPassColors_Vertex3f_Color4f((surface->groupmesh->data_vertex3f + 3 * surface->num_firstvertex), varray_color4f, fogcolor[0], fogcolor[1], fogcolor[2], texture->currentalpha, 1, surface->num_vertices, modelorg); + if (!surface->lightmaptexture && surface->groupmesh->data_lightmapcolor4f && (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT)) + { + for (i = 0, v = (vertex3f + 3 * surface->num_firstvertex), c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4) + { + VectorSubtract(v, modelorg, diff); + f = exp(fogdensity/DotProduct(diff, diff)); + c[0] = r; + c[1] = g; + c[2] = b; + c[3] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+3] * f * a; + } + } + else + { + for (i = 0, v = (vertex3f + 3 * surface->num_firstvertex), c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4) + { + VectorSubtract(v, modelorg, diff); + f = exp(fogdensity/DotProduct(diff, diff)); + c[0] = r; + c[1] = g; + c[2] = b; + c[3] = f * a; + } + } + GL_LockArrays(surface->num_firstvertex, surface->num_vertices); + R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle)); + GL_LockArrays(0, 0); + } + } + } + if (texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) + qglEnable(GL_CULL_FACE); +} + +static void RSurfShader_Transparent_Callback(const void *calldata1, int calldata2) +{ + const entity_render_t *ent = calldata1; + const msurface_t *surface = ent->model->data_surfaces + calldata2; + vec3_t modelorg; + texture_t *texture; + + texture = surface->texture; + if (texture->basematerialflags & MATERIALFLAG_SKY) + return; // transparent sky is too difficult + R_UpdateTextureInfo(ent, texture); + + R_Mesh_Matrix(&ent->matrix); + Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg); + R_DrawTextureSurfaceList(ent, texture->currentframe, 1, &surface, modelorg); +} + +void R_QueueTextureSurfaceList(entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg) +{ + int texturesurfaceindex; + const msurface_t *surface; + vec3_t tempcenter, center; + if (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT) + { + // drawing sky transparently would be too difficult + if (!(texture->currentmaterialflags & MATERIALFLAG_SKY)) + { + for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++) + { + surface = texturesurfacelist[texturesurfaceindex]; + tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f; + tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f; + tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f; + Matrix4x4_Transform(&ent->matrix, tempcenter, center); + R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_vieworigin : center, RSurfShader_Transparent_Callback, ent, surface - ent->model->data_surfaces); + } + } + } + else + R_DrawTextureSurfaceList(ent, texture, texturenumsurfaces, texturesurfacelist, modelorg); +} + +extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface); +void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces) +{ + int i, j, f, flagsmask; + msurface_t *surface, **surfacechain; + texture_t *t, *texture; + model_t *model = ent->model; + vec3_t modelorg; + const int maxsurfacelist = 1024; + int numsurfacelist = 0; + const msurface_t *surfacelist[1024]; + if (model == NULL) + return; + R_Mesh_Matrix(&ent->matrix); + Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg); + + // update light styles + if (!skysurfaces && model->brushq1.light_styleupdatechains) + { + for (i = 0;i < model->brushq1.light_styles;i++) + { + if (model->brushq1.light_stylevalue[i] != d_lightstylevalue[model->brushq1.light_style[i]]) + { + model->brushq1.light_stylevalue[i] = d_lightstylevalue[model->brushq1.light_style[i]]; + if ((surfacechain = model->brushq1.light_styleupdatechains[i])) + for (;(surface = *surfacechain);surfacechain++) + surface->cached_dlight = true; + } + } + } + + R_UpdateAllTextureInfo(ent); + flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL); + f = 0; + t = NULL; + texture = NULL; + numsurfacelist = 0; + if (ent == r_refdef.worldentity) + { + for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++) + { + if (!r_worldsurfacevisible[j]) + continue; + if (t != surface->texture) + { + if (numsurfacelist) + { + R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg); + numsurfacelist = 0; + } + t = surface->texture; + f = t->currentmaterialflags & flagsmask; + texture = t->currentframe; + } + if (f && surface->num_triangles) + { + // if lightmap parameters changed, rebuild lightmap texture + if (surface->cached_dlight && surface->lightmapinfo->samples) + R_BuildLightMap(ent, surface); + // add face to draw list + surfacelist[numsurfacelist++] = surface; + if (numsurfacelist >= maxsurfacelist) + { + R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg); + numsurfacelist = 0; + } + } + } + } + else + { + for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++) + { + if (t != surface->texture) + { + if (numsurfacelist) + { + R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg); + numsurfacelist = 0; + } + t = surface->texture; + f = t->currentmaterialflags & flagsmask; + texture = t->currentframe; + } + if (f && surface->num_triangles) + { + // if lightmap parameters changed, rebuild lightmap texture + if (surface->cached_dlight && surface->lightmapinfo->samples) + R_BuildLightMap(ent, surface); + // add face to draw list + surfacelist[numsurfacelist++] = surface; + if (numsurfacelist >= maxsurfacelist) + { + R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg); + numsurfacelist = 0; + } + } + } + } + if (numsurfacelist) + R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg); +} diff --git a/gl_rsurf.c b/gl_rsurf.c index 3f61cf9d..839cf24a 100644 --- a/gl_rsurf.c +++ b/gl_rsurf.c @@ -33,7 +33,6 @@ cvar_t r_surfaceworldnode = {0, "r_surfaceworldnode", "0"}; cvar_t r_drawcollisionbrushes_polygonfactor = {0, "r_drawcollisionbrushes_polygonfactor", "-1"}; cvar_t r_drawcollisionbrushes_polygonoffset = {0, "r_drawcollisionbrushes_polygonoffset", "0"}; cvar_t r_q3bsp_renderskydepth = {0, "r_q3bsp_renderskydepth", "0"}; -cvar_t gl_lightmaps = {0, "gl_lightmaps", "0"}; // flag arrays used for visibility checking on world model // (all other entities have no per-surface/per-leaf visibility checks) @@ -41,7 +40,7 @@ cvar_t gl_lightmaps = {0, "gl_lightmaps", "0"}; qbyte r_pvsbits[(32768+7)>>3]; // TODO: dynamic resize according to r_refdef.worldmodel->brush.num_leafs qbyte r_worldleafvisible[32768]; -// TODO: dynamic resize according to r_refdef.worldmodel->brush.num_surfaces +// TODO: dynamic resize according to r_refdef.worldmodel->num_surfaces qbyte r_worldsurfacevisible[262144]; /* @@ -51,7 +50,7 @@ R_BuildLightMap Combine and scale multiple lightmaps into the 8.8 format in blocklights =============== */ -static void R_BuildLightMap (const entity_render_t *ent, msurface_t *surface) +void R_BuildLightMap (const entity_render_t *ent, msurface_t *surface) { int smax, tmax, i, j, size, size3, maps, stride, l; unsigned int *bl, scale; @@ -169,7 +168,7 @@ loc0: impact[2] = origin[2] - node->plane->normal[2] * ndist; } - for (surface = model->brush.data_surfaces + node->firstsurface, endsurface = surface + node->numsurfaces;surface < endsurface;surface++) + for (surface = model->data_surfaces + node->firstsurface, endsurface = surface + node->numsurfaces;surface < endsurface;surface++) { if (surface->lightmapinfo->stainsamples) { @@ -296,1198 +295,6 @@ void R_Stain (const vec3_t origin, float radius, int cr1, int cg1, int cb1, int ============================================================= */ -static void RSurf_DeformVertices(const entity_render_t *ent, const texture_t *texture, const msurface_t *surface, const vec3_t modelorg) -{ - int i, j; - float center[3], forward[3], right[3], up[3], v[4][3]; - matrix4x4_t matrix1, imatrix1; - if (texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE2) - { - // a single autosprite surface can contain multiple sprites... - VectorClear(forward); - VectorClear(right); - VectorSet(up, 0, 0, 1); - for (j = 0;j < surface->num_vertices - 3;j += 4) - { - VectorClear(center); - for (i = 0;i < 4;i++) - VectorAdd(center, (surface->groupmesh->data_vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center); - VectorScale(center, 0.25f, center); - // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out? - Matrix4x4_FromVectors(&matrix1, (surface->groupmesh->data_normal3f + 3 * surface->num_firstvertex) + j*3, (surface->groupmesh->data_svector3f + 3 * surface->num_firstvertex) + j*3, (surface->groupmesh->data_tvector3f + 3 * surface->num_firstvertex) + j*3, center); - Matrix4x4_Invert_Simple(&imatrix1, &matrix1); - for (i = 0;i < 4;i++) - Matrix4x4_Transform(&imatrix1, (surface->groupmesh->data_vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]); - forward[0] = modelorg[0] - center[0]; - forward[1] = modelorg[1] - center[1]; - VectorNormalize(forward); - right[0] = forward[1]; - right[1] = -forward[0]; - for (i = 0;i < 4;i++) - VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, varray_vertex3f + (surface->num_firstvertex+i+j) * 3); - } - } - else if (texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE) - { - Matrix4x4_Transform(&ent->inversematrix, r_viewforward, forward); - Matrix4x4_Transform(&ent->inversematrix, r_viewright, right); - Matrix4x4_Transform(&ent->inversematrix, r_viewup, up); - // a single autosprite surface can contain multiple sprites... - for (j = 0;j < surface->num_vertices - 3;j += 4) - { - VectorClear(center); - for (i = 0;i < 4;i++) - VectorAdd(center, (surface->groupmesh->data_vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center); - VectorScale(center, 0.25f, center); - // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out? - Matrix4x4_FromVectors(&matrix1, (surface->groupmesh->data_normal3f + 3 * surface->num_firstvertex) + j*3, (surface->groupmesh->data_svector3f + 3 * surface->num_firstvertex) + j*3, (surface->groupmesh->data_tvector3f + 3 * surface->num_firstvertex) + j*3, center); - Matrix4x4_Invert_Simple(&imatrix1, &matrix1); - for (i = 0;i < 4;i++) - Matrix4x4_Transform(&imatrix1, (surface->groupmesh->data_vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]); - for (i = 0;i < 4;i++) - VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, varray_vertex3f + (surface->num_firstvertex+i+j) * 3); - } - } - else - memcpy((varray_vertex3f + 3 * surface->num_firstvertex), (surface->groupmesh->data_vertex3f + 3 * surface->num_firstvertex), sizeof(float[3]) * surface->num_vertices); -} - -// any sort of deformvertices call is *VERY* rare, so this must be optimized -// to skip deformvertices quickly! -#if 1 -#define RSurf_GetVertexPointer(ent, texture, surface, modelorg) ((texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2)) ? (RSurf_DeformVertices(ent, texture, surface, modelorg), varray_vertex3f) : surface->groupmesh->data_vertex3f) -#else -static float *RSurf_GetVertexPointer(const entity_render_t *ent, const texture_t *texture, const msurface_t *surface, const vec3_t modelorg) -{ - if (texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2)) - { - RSurf_DeformVertices(ent, texture, surface, modelorg); - return varray_vertex3f; - } - else - return surface->groupmesh->data_vertex3f; -} -#endif - -void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t) -{ - // we don't need to set currentframe if t->animated is false because - // it was already set up by the texture loader for non-animating - if (t->animated) - { - t->currentframe = t->anim_frames[ent->frame != 0][(t->anim_total[ent->frame != 0] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[ent->frame != 0]) : 0]; - t = t->currentframe; - } - t->currentmaterialflags = t->basematerialflags; - t->currentalpha = ent->alpha; - if (t->basematerialflags & MATERIALFLAG_WATERALPHA) - t->currentalpha *= r_wateralpha.value; - if (!(ent->flags & RENDER_LIGHT)) - t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT; - if (ent->effects & EF_ADDITIVE) - t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_TRANSPARENT; - else if (t->currentalpha < 1) - t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_TRANSPARENT; -} - -matrix4x4_t r_surf_waterscrollmatrix; - -void R_UpdateAllTextureInfo(entity_render_t *ent) -{ - int i; - Matrix4x4_CreateTranslate(&r_surf_waterscrollmatrix, sin(r_refdef.time) * 0.025 * r_waterscroll.value, sin(r_refdef.time * 0.8f) * 0.025 * r_waterscroll.value, 0); - if (ent->model) - for (i = 0;i < ent->model->brush.num_textures;i++) - R_UpdateTextureInfo(ent, ent->model->brush.data_textures + i); -} - -static void R_DrawSurfaceList(const entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg) -{ - int i; - int texturesurfaceindex; - const float *v, *vertex3f; - float *c; - float diff[3]; - float f, r, g, b, a, base, colorscale; - const msurface_t *surface; - qboolean dolightmap; - qboolean dobase; - qboolean doambient; - qboolean dodetail; - qboolean doglow; - qboolean dofogpass; - qboolean fogallpasses; - qboolean waterscrolling; - surfmesh_t *groupmesh; - rtexture_t *lightmaptexture; - rmeshstate_t m; - texture = texture->currentframe; - if (texture->currentmaterialflags & MATERIALFLAG_NODRAW) - return; - c_faces += texturenumsurfaces; - // gl_lightmaps debugging mode skips normal texturing - if (gl_lightmaps.integer) - { - GL_BlendFunc(GL_ONE, GL_ZERO); - GL_DepthMask(true); - GL_DepthTest(true); - qglDisable(GL_CULL_FACE); - GL_Color(1, 1, 1, 1); - memset(&m, 0, sizeof(m)); - R_Mesh_State(&m); - for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++) - { - surface = texturesurfacelist[texturesurfaceindex]; - R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture)); - R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f); - R_Mesh_ColorPointer(surface->lightmaptexture ? NULL : surface->groupmesh->data_lightmapcolor4f); - R_Mesh_VertexPointer(surface->groupmesh->data_vertex3f); - GL_LockArrays(surface->num_firstvertex, surface->num_vertices); - R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle)); - GL_LockArrays(0, 0); - } - qglEnable(GL_CULL_FACE); - return; - } - GL_DepthTest(!(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST)); - GL_DepthMask(!(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT)); - if (texture->currentmaterialflags & MATERIALFLAG_ADD) - GL_BlendFunc(GL_SRC_ALPHA, GL_ONE); - else if (texture->currentmaterialflags & MATERIALFLAG_ALPHA) - GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - else - GL_BlendFunc(GL_ONE, GL_ZERO); - // water waterscrolling in texture matrix - waterscrolling = (texture->currentmaterialflags & MATERIALFLAG_WATER) && r_waterscroll.value != 0; - if (texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) - qglDisable(GL_CULL_FACE); - if (texture->currentmaterialflags & MATERIALFLAG_SKY) - { - if (skyrendernow) - { - skyrendernow = false; - if (skyrendermasked) - R_Sky(); - } - // LordHavoc: HalfLife maps have freaky skypolys... - //if (!ent->model->brush.ishlbsp) - { - R_Mesh_Matrix(&ent->matrix); - GL_Color(fogcolor[0], fogcolor[1], fogcolor[2], 1); - if (skyrendermasked) - { - // depth-only (masking) - GL_ColorMask(0,0,0,0); - // just to make sure that braindead drivers don't draw anything - // despite that colormask... - GL_BlendFunc(GL_ZERO, GL_ONE); - } - else - { - // fog sky - GL_BlendFunc(GL_ONE, GL_ZERO); - } - GL_DepthMask(true); - GL_DepthTest(true); - memset(&m, 0, sizeof(m)); - R_Mesh_State(&m); - for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++) - { - surface = texturesurfacelist[texturesurfaceindex]; - R_Mesh_VertexPointer(surface->groupmesh->data_vertex3f); - GL_LockArrays(surface->num_firstvertex, surface->num_vertices); - R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle)); - GL_LockArrays(0, 0); - } - GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1); - } - } - else if ((texture->currentmaterialflags & MATERIALFLAG_WATER) && r_watershader.value && gl_textureshader && !texture->skin.glow && !fogenabled && ent->colormod[0] == 1 && ent->colormod[1] == 1 && ent->colormod[2] == 1) - { - // NVIDIA Geforce3 distortion texture shader on water - float args[4] = {0.05f,0,0,0.04f}; - memset(&m, 0, sizeof(m)); - m.tex[0] = R_GetTexture(r_texture_distorttexture[(int)(r_refdef.time * 16)&63]); - m.tex[1] = R_GetTexture(texture->skin.base); - m.texcombinergb[0] = GL_REPLACE; - m.texcombinergb[1] = GL_REPLACE; - Matrix4x4_CreateFromQuakeEntity(&m.texmatrix[0], 0, 0, 0, 0, 0, 0, r_watershader.value); - m.texmatrix[1] = r_surf_waterscrollmatrix; - R_Mesh_State(&m); - - GL_Color(1, 1, 1, texture->currentalpha); - GL_ActiveTexture(0); - qglTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D); - GL_ActiveTexture(1); - qglTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_OFFSET_TEXTURE_2D_NV); - qglTexEnvi(GL_TEXTURE_SHADER_NV, GL_PREVIOUS_TEXTURE_INPUT_NV, GL_TEXTURE0_ARB); - qglTexEnvfv(GL_TEXTURE_SHADER_NV, GL_OFFSET_TEXTURE_MATRIX_NV, &args[0]); - qglEnable(GL_TEXTURE_SHADER_NV); - - for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++) - { - surface = texturesurfacelist[texturesurfaceindex]; - R_Mesh_VertexPointer(RSurf_GetVertexPointer(ent, texture, surface, modelorg)); - R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f); - R_Mesh_TexCoordPointer(1, 2, surface->groupmesh->data_texcoordtexture2f); - GL_LockArrays(surface->num_firstvertex, surface->num_vertices); - R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle)); - GL_LockArrays(0, 0); - } - - qglDisable(GL_TEXTURE_SHADER_NV); - qglTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D); - GL_ActiveTexture(0); - } - else if (texture->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL)) - { - // normal surface (wall or water) - dobase = true; - dolightmap = !(texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT); - doambient = r_ambient.value >= (1/64.0f); - dodetail = r_detailtextures.integer && texture->skin.detail != NULL && !(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT); - doglow = texture->skin.glow != NULL; - dofogpass = fogenabled && !(texture->currentmaterialflags & MATERIALFLAG_ADD); - fogallpasses = fogenabled && !(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT); - if (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT) - { - if (dobase && dolightmap && gl_combine.integer) - { - dobase = false; - memset(&m, 0, sizeof(m)); - m.tex[1] = R_GetTexture(texture->skin.base); - if (waterscrolling) - m.texmatrix[1] = r_surf_waterscrollmatrix; - m.texrgbscale[1] = 2; - m.pointer_color = varray_color4f; - R_Mesh_State(&m); - colorscale = 1; - r = ent->colormod[0] * colorscale; - g = ent->colormod[1] * colorscale; - b = ent->colormod[2] * colorscale; - a = texture->currentalpha; - base = r_ambient.value * (1.0f / 64.0f); - // q3bsp has no lightmap updates, so the lightstylevalue that - // would normally be baked into the lightmaptexture must be - // applied to the color - if (ent->model->brushq1.lightdata) - { - float scale = d_lightstylevalue[0] * (1.0f / 128.0f); - r *= scale; - g *= scale; - b *= scale; - } - for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++) - { - surface = texturesurfacelist[texturesurfaceindex]; - vertex3f = RSurf_GetVertexPointer(ent, texture, surface, modelorg); - R_Mesh_VertexPointer(vertex3f); - R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f); - R_Mesh_TexCoordPointer(1, 2, surface->groupmesh->data_texcoordtexture2f); - if (surface->lightmaptexture) - { - R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture)); - if (fogallpasses) - { - R_Mesh_ColorPointer(varray_color4f); - for (i = 0, v = (vertex3f + 3 * surface->num_firstvertex), c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4) - { - VectorSubtract(v, modelorg, diff); - f = 1 - exp(fogdensity/DotProduct(diff, diff)); - c[0] = f * r; - c[1] = f * g; - c[2] = f * b; - c[3] = a; - } - } - else - { - R_Mesh_ColorPointer(NULL); - GL_Color(r, g, b, a); - } - } - else - { - R_Mesh_TexBind(0, R_GetTexture(r_texture_white)); - R_Mesh_ColorPointer(varray_color4f); - if (!surface->lightmaptexture) - { - for (i = 0, c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, c += 4) - { - c[0] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+0] * r; - c[1] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+1] * g; - c[2] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+2] * b; - c[3] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+3] * a; - } - if (fogallpasses) - { - for (i = 0, v = (vertex3f + 3 * surface->num_firstvertex), c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4) - { - VectorSubtract(v, modelorg, diff); - f = 1 - exp(fogdensity/DotProduct(diff, diff)); - VectorScale(c, f, c); - } - } - } - else - { - R_Mesh_ColorPointer(NULL); - GL_Color(0, 0, 0, a); - } - } - GL_LockArrays(surface->num_firstvertex, surface->num_vertices); - R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle)); - GL_LockArrays(0, 0); - } - } - if (dobase) - { - dobase = false; - memset(&m, 0, sizeof(m)); - m.tex[0] = R_GetTexture(texture->skin.base); - if (waterscrolling) - m.texmatrix[0] = r_surf_waterscrollmatrix; - m.pointer_color = varray_color4f; - colorscale = 1; - if (gl_combine.integer) - { - m.texrgbscale[0] = 4; - colorscale *= 0.25f; - } - R_Mesh_State(&m); - r = ent->colormod[0] * colorscale; - g = ent->colormod[1] * colorscale; - b = ent->colormod[2] * colorscale; - a = texture->currentalpha; - if (dolightmap) - { - // q3bsp has no lightmap updates, so the lightstylevalue that - // would normally be baked into the lightmaptexture must be - // applied to the color - if (!ent->model->brushq1.lightdata) - { - float scale = d_lightstylevalue[0] * (1.0f / 128.0f); - r *= scale; - g *= scale; - b *= scale; - } - for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++) - { - surface = texturesurfacelist[texturesurfaceindex]; - vertex3f = RSurf_GetVertexPointer(ent, texture, surface, modelorg); - R_Mesh_VertexPointer(vertex3f); - R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f); - for (i = 0, v = (vertex3f + 3 * surface->num_firstvertex), c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4) - { - c[0] = 0; - c[1] = 0; - c[2] = 0; - if (!surface->lightmapinfo) - VectorCopy((surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex) + i*4, c); - else //if (surface->lightmapinfo) - { - const qbyte *lm = surface->lightmapinfo->samples + (surface->groupmesh->data_lightmapoffsets + surface->num_firstvertex)[i]; - float scale = d_lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f); - VectorMA(c, scale, lm, c); - if (surface->lightmapinfo->styles[1] != 255) - { - int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3; - lm += size3; - scale = d_lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f); - VectorMA(c, scale, lm, c); - if (surface->lightmapinfo->styles[2] != 255) - { - lm += size3; - scale = d_lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f); - VectorMA(c, scale, lm, c); - if (surface->lightmapinfo->styles[3] != 255) - { - lm += size3; - scale = d_lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f); - VectorMA(c, scale, lm, c); - } - } - } - } - c[0] *= r; - c[1] *= g; - c[2] *= b; - if (fogallpasses) - { - VectorSubtract(v, modelorg, diff); - f = 1 - exp(fogdensity/DotProduct(diff, diff)); - VectorScale(c, f, c); - } - if (!surface->lightmapinfo && (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT)) - c[3] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+3] * a; - else - c[3] = a; - } - GL_LockArrays(surface->num_firstvertex, surface->num_vertices); - R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle)); - GL_LockArrays(0, 0); - } - } - else - { - if (fogallpasses) - { - for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++) - { - surface = texturesurfacelist[texturesurfaceindex]; - vertex3f = RSurf_GetVertexPointer(ent, texture, surface, modelorg); - R_Mesh_VertexPointer(vertex3f); - R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f); - if (!surface->lightmapinfo && (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT)) - { - R_Mesh_ColorPointer(varray_color4f); - for (i = 0, v = (vertex3f + 3 * surface->num_firstvertex), c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4) - { - VectorSubtract(v, modelorg, diff); - f = 1 - exp(fogdensity/DotProduct(diff, diff)); - c[0] = r * f; - c[1] = g * f; - c[2] = b * f; - c[3] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+3] * a; - } - } - else - { - R_Mesh_ColorPointer(varray_color4f); - for (i = 0, v = (vertex3f + 3 * surface->num_firstvertex), c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4) - { - VectorSubtract(v, modelorg, diff); - f = 1 - exp(fogdensity/DotProduct(diff, diff)); - c[0] = r * f; - c[1] = g * f; - c[2] = b * f; - c[3] = a; - } - } - GL_LockArrays(surface->num_firstvertex, surface->num_vertices); - R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle)); - GL_LockArrays(0, 0); - } - } - else - { - for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++) - { - surface = texturesurfacelist[texturesurfaceindex]; - vertex3f = RSurf_GetVertexPointer(ent, texture, surface, modelorg); - R_Mesh_VertexPointer(vertex3f); - R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f); - if (!surface->lightmaptexture && (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT)) - { - R_Mesh_ColorPointer(varray_color4f); - for (i = 0, v = (vertex3f + 3 * surface->num_firstvertex), c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4) - { - c[0] = r; - c[1] = g; - c[2] = b; - c[3] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+3] * a; - } - } - else - { - R_Mesh_ColorPointer(NULL); - GL_Color(r, g, b, a); - } - GL_LockArrays(surface->num_firstvertex, surface->num_vertices); - R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle)); - GL_LockArrays(0, 0); - } - } - } - } - } - else - { - if (!dolightmap && dobase) - { - dolightmap = false; - dobase = false; - GL_Color(ent->colormod[0], ent->colormod[1], ent->colormod[2], 1); - memset(&m, 0, sizeof(m)); - m.tex[0] = R_GetTexture(texture->skin.base); - if (waterscrolling) - m.texmatrix[0] = r_surf_waterscrollmatrix; - R_Mesh_State(&m); - for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++) - { - surface = texturesurfacelist[texturesurfaceindex]; - R_Mesh_VertexPointer(RSurf_GetVertexPointer(ent, texture, surface, modelorg)); - R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f); - GL_LockArrays(surface->num_firstvertex, surface->num_vertices); - R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle)); - GL_LockArrays(0, 0); - } - } - if (r_lightmapintensity <= 0 && dolightmap && dobase) - { - dolightmap = false; - dobase = false; - GL_Color(0, 0, 0, 1); - memset(&m, 0, sizeof(m)); - R_Mesh_State(&m); - for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++) - { - surface = texturesurfacelist[texturesurfaceindex]; - R_Mesh_VertexPointer(RSurf_GetVertexPointer(ent, texture, surface, modelorg)); - GL_LockArrays(surface->num_firstvertex, surface->num_vertices); - R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle)); - GL_LockArrays(0, 0); - } - } - if (r_textureunits.integer >= 2 && gl_combine.integer && dolightmap && dobase) - { - // dualtexture combine - GL_BlendFunc(GL_ONE, GL_ZERO); - GL_DepthMask(true); - dolightmap = false; - dobase = false; - memset(&m, 0, sizeof(m)); - m.tex[1] = R_GetTexture(texture->skin.base); - if (waterscrolling) - m.texmatrix[1] = r_surf_waterscrollmatrix; - m.texrgbscale[1] = 2; - R_Mesh_State(&m); - r = ent->colormod[0] * r_lightmapintensity; - g = ent->colormod[1] * r_lightmapintensity; - b = ent->colormod[2] * r_lightmapintensity; - GL_Color(r, g, b, 1); - if (texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2)) - { - R_Mesh_VertexPointer(varray_vertex3f); - if (r == 1 && g == 1 && b == 1) - { - for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++) - { - surface = texturesurfacelist[texturesurfaceindex]; - RSurf_DeformVertices(ent, texture, surface, modelorg); - R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f); - R_Mesh_TexCoordPointer(1, 2, surface->groupmesh->data_texcoordtexture2f); - if (surface->lightmaptexture) - { - R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture)); - R_Mesh_ColorPointer(NULL); - } - else //if (r == 1 && g == 1 && b == 1) - { - R_Mesh_TexBind(0, R_GetTexture(r_texture_white)); - R_Mesh_ColorPointer(surface->groupmesh->data_lightmapcolor4f); - } - GL_LockArrays(surface->num_firstvertex, surface->num_vertices); - R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle)); - GL_LockArrays(0, 0); - } - } - else - { - for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++) - { - surface = texturesurfacelist[texturesurfaceindex]; - RSurf_DeformVertices(ent, texture, surface, modelorg); - R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f); - R_Mesh_TexCoordPointer(1, 2, surface->groupmesh->data_texcoordtexture2f); - if (surface->lightmaptexture) - { - R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture)); - R_Mesh_ColorPointer(NULL); - } - else - { - R_Mesh_TexBind(0, R_GetTexture(r_texture_white)); - R_Mesh_ColorPointer(varray_color4f); - for (i = 0, c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, c += 4) - { - c[0] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+0] * r; - c[1] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+1] * g; - c[2] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+2] * b; - c[3] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+3]; - } - } - GL_LockArrays(surface->num_firstvertex, surface->num_vertices); - R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle)); - GL_LockArrays(0, 0); - } - } - } - else - { - if (r == 1 && g == 1 && b == 1) - { -#if 0 - // experimental direct state calls for measuring - // R_Mesh_ call overhead, do not use! - R_Mesh_VertexPointer(varray_vertex3f); - R_Mesh_TexCoordPointer(0, 2, varray_texcoord2f[0]); - R_Mesh_TexCoordPointer(1, 2, varray_texcoord2f[1]); - R_Mesh_TexBind(0, R_GetTexture(r_texture_white)); - R_Mesh_ColorPointer(varray_color4f); - for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++) - { - surface = texturesurfacelist[texturesurfaceindex]; - qglVertexPointer(3, GL_FLOAT, sizeof(float[3]), surface->groupmesh->data_vertex3f); - qglClientActiveTexture(GL_TEXTURE0_ARB); - qglTexCoordPointer(2, GL_FLOAT, sizeof(float[2]), surface->groupmesh->data_texcoordlightmap2f); - qglClientActiveTexture(GL_TEXTURE1_ARB); - qglTexCoordPointer(2, GL_FLOAT, sizeof(float[2]), surface->groupmesh->data_texcoordtexture2f); - if (surface->lightmaptexture) - { - R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture)); - qglDisableClientState(GL_COLOR_ARRAY); - qglColor4f(r, g, b, 1); - } - else //if (r == 1 && g == 1 && b == 1) - { - R_Mesh_TexBind(0, R_GetTexture(r_texture_white)); - qglEnableClientState(GL_COLOR_ARRAY); - qglColorPointer(4, GL_FLOAT, sizeof(float[4]), surface->groupmesh->data_lightmapcolor4f); - } - qglLockArraysEXT(0, surface->num_vertices); - qglDrawRangeElements(GL_TRIANGLES, surface->num_firstvertex, surface->num_firstvertex + surface->num_vertices, surface->num_triangles * 3, GL_UNSIGNED_INT, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle)); - qglUnlockArraysEXT(); - } -#else - groupmesh = NULL; - lightmaptexture = NULL; - for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++) - { - surface = texturesurfacelist[texturesurfaceindex]; - if (groupmesh != surface->groupmesh) - { - groupmesh = surface->groupmesh; - R_Mesh_VertexPointer(groupmesh->data_vertex3f); - R_Mesh_TexCoordPointer(0, 2, groupmesh->data_texcoordlightmap2f); - R_Mesh_TexCoordPointer(1, 2, groupmesh->data_texcoordtexture2f); - if (!lightmaptexture) - R_Mesh_ColorPointer(groupmesh->data_lightmapcolor4f); - } - if (lightmaptexture != surface->lightmaptexture) - { - lightmaptexture = surface->lightmaptexture; - if (lightmaptexture) - { - R_Mesh_TexBind(0, R_GetTexture(lightmaptexture)); - R_Mesh_ColorPointer(NULL); - } - else //if (r == 1 && g == 1 && b == 1) - { - R_Mesh_TexBind(0, R_GetTexture(r_texture_white)); - R_Mesh_ColorPointer(surface->groupmesh->data_lightmapcolor4f); - } - } - GL_LockArrays(surface->num_firstvertex, surface->num_vertices); - R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle)); - GL_LockArrays(0, 0); - } -#endif - } - else - { - for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++) - { - surface = texturesurfacelist[texturesurfaceindex]; - R_Mesh_VertexPointer(surface->groupmesh->data_vertex3f); - R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f); - R_Mesh_TexCoordPointer(1, 2, surface->groupmesh->data_texcoordtexture2f); - if (surface->lightmaptexture) - { - R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture)); - R_Mesh_ColorPointer(NULL); - } - else - { - R_Mesh_TexBind(0, R_GetTexture(r_texture_white)); - R_Mesh_ColorPointer(varray_color4f); - for (i = 0, c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, c += 4) - { - c[0] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+0] * r; - c[1] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+1] * g; - c[2] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+2] * b; - c[3] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+3]; - } - } - GL_LockArrays(surface->num_firstvertex, surface->num_vertices); - R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle)); - GL_LockArrays(0, 0); - } - } - } - } - // single texture - if (dolightmap) - { - GL_BlendFunc(GL_ONE, GL_ZERO); - GL_DepthMask(true); - GL_Color(1, 1, 1, 1); - memset(&m, 0, sizeof(m)); - R_Mesh_State(&m); - if (texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2)) - { - R_Mesh_VertexPointer(varray_vertex3f); - for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++) - { - surface = texturesurfacelist[texturesurfaceindex]; - RSurf_DeformVertices(ent, texture, surface, modelorg); - R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f); - if (surface->lightmaptexture) - { - R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture)); - R_Mesh_ColorPointer(NULL); - } - else //if (r == 1 && g == 1 && b == 1) - { - R_Mesh_TexBind(0, R_GetTexture(r_texture_white)); - R_Mesh_ColorPointer(surface->groupmesh->data_lightmapcolor4f); - } - GL_LockArrays(surface->num_firstvertex, surface->num_vertices); - R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle)); - GL_LockArrays(0, 0); - } - } - else - { - groupmesh = NULL; - lightmaptexture = NULL; - for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++) - { - surface = texturesurfacelist[texturesurfaceindex]; - if (groupmesh != surface->groupmesh) - { - groupmesh = surface->groupmesh; - R_Mesh_VertexPointer(groupmesh->data_vertex3f); - R_Mesh_TexCoordPointer(0, 2, groupmesh->data_texcoordlightmap2f); - if (!lightmaptexture) - R_Mesh_ColorPointer(groupmesh->data_lightmapcolor4f); - } - if (lightmaptexture != surface->lightmaptexture) - { - lightmaptexture = surface->lightmaptexture; - if (lightmaptexture) - { - R_Mesh_TexBind(0, R_GetTexture(lightmaptexture)); - R_Mesh_ColorPointer(NULL); - } - else //if (r == 1 && g == 1 && b == 1) - { - R_Mesh_TexBind(0, R_GetTexture(r_texture_white)); - R_Mesh_ColorPointer(surface->groupmesh->data_lightmapcolor4f); - } - } - GL_LockArrays(surface->num_firstvertex, surface->num_vertices); - R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle)); - GL_LockArrays(0, 0); - } - } - } - if (dobase) - { - GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR); - GL_DepthMask(false); - GL_Color(r_lightmapintensity * ent->colormod[0], r_lightmapintensity * ent->colormod[1], r_lightmapintensity * ent->colormod[2], 1); - memset(&m, 0, sizeof(m)); - m.tex[0] = R_GetTexture(texture->skin.base); - if (waterscrolling) - m.texmatrix[0] = r_surf_waterscrollmatrix; - R_Mesh_State(&m); - if (texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2)) - { - R_Mesh_VertexPointer(varray_vertex3f); - for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++) - { - surface = texturesurfacelist[texturesurfaceindex]; - RSurf_DeformVertices(ent, texture, surface, modelorg); - R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f); - GL_LockArrays(surface->num_firstvertex, surface->num_vertices); - R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle)); - GL_LockArrays(0, 0); - } - } - else - { - groupmesh = NULL; - for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++) - { - surface = texturesurfacelist[texturesurfaceindex]; - if (groupmesh != surface->groupmesh) - { - groupmesh = surface->groupmesh; - R_Mesh_VertexPointer(groupmesh->data_vertex3f); - R_Mesh_TexCoordPointer(0, 2, groupmesh->data_texcoordtexture2f); - } - GL_LockArrays(surface->num_firstvertex, surface->num_vertices); - R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle)); - GL_LockArrays(0, 0); - } - } - } - } - if (doambient) - { - doambient = false; - GL_BlendFunc(GL_SRC_ALPHA, GL_ONE); - GL_DepthMask(false); - memset(&m, 0, sizeof(m)); - m.tex[0] = R_GetTexture(texture->skin.base); - if (waterscrolling) - m.texmatrix[0] = r_surf_waterscrollmatrix; - m.pointer_color = varray_color4f; - colorscale = 1; - if (gl_combine.integer) - { - m.texrgbscale[0] = 4; - colorscale *= 0.25f; - } - R_Mesh_State(&m); - base = r_ambient.value * (1.0f / 64.0f); - r = ent->colormod[0] * colorscale * base; - g = ent->colormod[1] * colorscale * base; - b = ent->colormod[2] * colorscale * base; - a = texture->currentalpha; - for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++) - { - surface = texturesurfacelist[texturesurfaceindex]; - vertex3f = RSurf_GetVertexPointer(ent, texture, surface, modelorg); - R_Mesh_VertexPointer(vertex3f); - R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f); - for (i = 0, v = (vertex3f + 3 * surface->num_firstvertex), c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4) - { - c[0] = r; - c[1] = g; - c[2] = b; - if (fogallpasses) - { - VectorSubtract(v, modelorg, diff); - f = 1 - exp(fogdensity/DotProduct(diff, diff)); - VectorScale(c, f, c); - } - if (!surface->lightmaptexture && surface->groupmesh->data_lightmapcolor4f && (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT)) - c[3] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+3] * a; - else - c[3] = a; - } - GL_LockArrays(surface->num_firstvertex, surface->num_vertices); - R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle)); - GL_LockArrays(0, 0); - } - } - if (dodetail) - { - GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR); - GL_DepthMask(false); - GL_Color(1, 1, 1, 1); - memset(&m, 0, sizeof(m)); - m.tex[0] = R_GetTexture(texture->skin.detail); - R_Mesh_State(&m); - for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++) - { - surface = texturesurfacelist[texturesurfaceindex]; - R_Mesh_VertexPointer(RSurf_GetVertexPointer(ent, texture, surface, modelorg)); - R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoorddetail2f); - GL_LockArrays(surface->num_firstvertex, surface->num_vertices); - R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle)); - GL_LockArrays(0, 0); - } - } - if (doglow) - { - // if glow was not already done using multitexture, do it now. - GL_BlendFunc(GL_SRC_ALPHA, GL_ONE); - GL_DepthMask(false); - memset(&m, 0, sizeof(m)); - m.tex[0] = R_GetTexture(texture->skin.glow); - if (waterscrolling) - m.texmatrix[0] = r_surf_waterscrollmatrix; - m.pointer_color = varray_color4f; - R_Mesh_State(&m); - colorscale = 1; - r = ent->colormod[0] * colorscale; - g = ent->colormod[1] * colorscale; - b = ent->colormod[2] * colorscale; - a = texture->currentalpha; - if (fogallpasses) - { - for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++) - { - surface = texturesurfacelist[texturesurfaceindex]; - vertex3f = RSurf_GetVertexPointer(ent, texture, surface, modelorg); - R_Mesh_VertexPointer(vertex3f); - R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f); - R_Mesh_ColorPointer(varray_color4f); - if (!surface->lightmaptexture && surface->groupmesh->data_lightmapcolor4f && (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT)) - { - for (i = 0, v = (vertex3f + 3 * surface->num_firstvertex), c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4) - { - VectorSubtract(v, modelorg, diff); - f = 1 - exp(fogdensity/DotProduct(diff, diff)); - c[0] = f * r; - c[1] = f * g; - c[2] = f * b; - c[3] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+3] * a; - } - } - else - { - for (i = 0, v = (vertex3f + 3 * surface->num_firstvertex), c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4) - { - VectorSubtract(v, modelorg, diff); - f = 1 - exp(fogdensity/DotProduct(diff, diff)); - c[0] = f * r; - c[1] = f * g; - c[2] = f * b; - c[3] = a; - } - } - GL_LockArrays(surface->num_firstvertex, surface->num_vertices); - R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle)); - GL_LockArrays(0, 0); - } - } - else - { - for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++) - { - surface = texturesurfacelist[texturesurfaceindex]; - vertex3f = RSurf_GetVertexPointer(ent, texture, surface, modelorg); - R_Mesh_VertexPointer(vertex3f); - R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f); - if (!surface->lightmaptexture && surface->groupmesh->data_lightmapcolor4f && (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT)) - { - R_Mesh_ColorPointer(varray_color4f); - for (i = 0, v = (vertex3f + 3 * surface->num_firstvertex), c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4) - { - c[0] = r; - c[1] = g; - c[2] = b; - c[3] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+3] * a; - } - } - else - { - R_Mesh_ColorPointer(NULL); - GL_Color(r, g, b, a); - } - GL_LockArrays(surface->num_firstvertex, surface->num_vertices); - R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle)); - GL_LockArrays(0, 0); - } - } - } - if (dofogpass) - { - // if this is opaque use alpha blend which will darken the earlier - // passes cheaply. - // - // if this is an alpha blended material, all the earlier passes - // were darkened by fog already, so we only need to add the fog - // color ontop through the fog mask texture - // - // if this is an additive blended material, all the earlier passes - // were darkened by fog already, and we should not add fog color - // (because the background was not darkened, there is no fog color - // that was lost behind it). - if (!fogallpasses) - GL_BlendFunc(GL_SRC_ALPHA, GL_ONE); - else - GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - GL_DepthMask(false); - memset(&m, 0, sizeof(m)); - m.tex[0] = R_GetTexture(texture->skin.fog); - if (waterscrolling) - m.texmatrix[0] = r_surf_waterscrollmatrix; - R_Mesh_State(&m); - r = fogcolor[0]; - g = fogcolor[1]; - b = fogcolor[2]; - a = texture->currentalpha; - for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++) - { - surface = texturesurfacelist[texturesurfaceindex]; - vertex3f = RSurf_GetVertexPointer(ent, texture, surface, modelorg); - R_Mesh_VertexPointer(vertex3f); - R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f); - R_Mesh_ColorPointer(varray_color4f); - //RSurf_FogPassColors_Vertex3f_Color4f((surface->groupmesh->data_vertex3f + 3 * surface->num_firstvertex), varray_color4f, fogcolor[0], fogcolor[1], fogcolor[2], texture->currentalpha, 1, surface->num_vertices, modelorg); - if (!surface->lightmaptexture && surface->groupmesh->data_lightmapcolor4f && (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT)) - { - for (i = 0, v = (vertex3f + 3 * surface->num_firstvertex), c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4) - { - VectorSubtract(v, modelorg, diff); - f = exp(fogdensity/DotProduct(diff, diff)); - c[0] = r; - c[1] = g; - c[2] = b; - c[3] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+3] * f * a; - } - } - else - { - for (i = 0, v = (vertex3f + 3 * surface->num_firstvertex), c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4) - { - VectorSubtract(v, modelorg, diff); - f = exp(fogdensity/DotProduct(diff, diff)); - c[0] = r; - c[1] = g; - c[2] = b; - c[3] = f * a; - } - } - GL_LockArrays(surface->num_firstvertex, surface->num_vertices); - R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle)); - GL_LockArrays(0, 0); - } - } - } - if (texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) - qglEnable(GL_CULL_FACE); -} - -static void RSurfShader_Transparent_Callback(const void *calldata1, int calldata2) -{ - const entity_render_t *ent = calldata1; - const msurface_t *surface = ent->model->brush.data_surfaces + calldata2; - vec3_t modelorg; - texture_t *texture; - - texture = surface->texture; - if (texture->basematerialflags & MATERIALFLAG_SKY) - return; // transparent sky is too difficult - R_UpdateTextureInfo(ent, texture); - - R_Mesh_Matrix(&ent->matrix); - Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg); - R_DrawSurfaceList(ent, texture, 1, &surface, modelorg); -} - -void R_QueueSurfaceList(entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg) -{ - int texturesurfaceindex; - const msurface_t *surface; - vec3_t tempcenter, center; - if (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT) - { - // drawing sky transparently would be too difficult - if (!(texture->currentmaterialflags & MATERIALFLAG_SKY)) - { - for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++) - { - surface = texturesurfacelist[texturesurfaceindex]; - tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f; - tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f; - tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f; - Matrix4x4_Transform(&ent->matrix, tempcenter, center); - R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_vieworigin : center, RSurfShader_Transparent_Callback, ent, surface - ent->model->brush.data_surfaces); - } - } - } - else - R_DrawSurfaceList(ent, texture, texturenumsurfaces, texturesurfacelist, modelorg); -} - -void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces) -{ - int i, j, f, flagsmask; - msurface_t *surface, **surfacechain; - texture_t *t, *texture; - model_t *model = ent->model; - vec3_t modelorg; - const int maxsurfacelist = 1024; - int numsurfacelist = 0; - const msurface_t *surfacelist[1024]; - if (model == NULL) - return; - R_Mesh_Matrix(&ent->matrix); - Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg); - - // update light styles - if (!skysurfaces && model->brushq1.light_styleupdatechains) - { - for (i = 0;i < model->brushq1.light_styles;i++) - { - if (model->brushq1.light_stylevalue[i] != d_lightstylevalue[model->brushq1.light_style[i]]) - { - model->brushq1.light_stylevalue[i] = d_lightstylevalue[model->brushq1.light_style[i]]; - if ((surfacechain = model->brushq1.light_styleupdatechains[i])) - for (;(surface = *surfacechain);surfacechain++) - surface->cached_dlight = true; - } - } - } - - R_UpdateAllTextureInfo(ent); - flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL); - f = 0; - t = NULL; - texture = NULL; - numsurfacelist = 0; - if (ent == r_refdef.worldentity) - { - for (i = 0, j = model->firstmodelsurface, surface = model->brush.data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++) - { - if (!r_worldsurfacevisible[j]) - continue; - if (t != surface->texture) - { - if (numsurfacelist) - { - R_QueueSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg); - numsurfacelist = 0; - } - t = surface->texture; - f = t->currentmaterialflags & flagsmask; - texture = t->currentframe; - } - if (f && surface->num_triangles) - { - // if lightmap parameters changed, rebuild lightmap texture - if (surface->cached_dlight && surface->lightmapinfo->samples) - R_BuildLightMap(ent, surface); - // add face to draw list - surfacelist[numsurfacelist++] = surface; - if (numsurfacelist >= maxsurfacelist) - { - R_QueueSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg); - numsurfacelist = 0; - } - } - } - } - else - { - for (i = 0, j = model->firstmodelsurface, surface = model->brush.data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++) - { - if (t != surface->texture) - { - if (numsurfacelist) - { - R_QueueSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg); - numsurfacelist = 0; - } - t = surface->texture; - f = t->currentmaterialflags & flagsmask; - texture = t->currentframe; - } - if (f && surface->num_triangles) - { - // if lightmap parameters changed, rebuild lightmap texture - if (surface->cached_dlight && surface->lightmapinfo->samples) - R_BuildLightMap(ent, surface); - // add face to draw list - surfacelist[numsurfacelist++] = surface; - if (numsurfacelist >= maxsurfacelist) - { - R_QueueSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg); - numsurfacelist = 0; - } - } - } - } - if (numsurfacelist) - R_QueueSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg); -} - static void R_DrawPortal_Callback(const void *calldata1, int calldata2) { int i; @@ -1600,7 +407,7 @@ void R_WorldVisibility(void) model->brush.FatPVS(model, r_vieworigin, 2, r_pvsbits, sizeof(r_pvsbits)); // clear the visible surface and leaf flags arrays - memset(r_worldsurfacevisible, 0, model->brush.num_surfaces); + memset(r_worldsurfacevisible, 0, model->num_surfaces); memset(r_worldleafvisible, 0, model->brush.num_leafs); // if the user prefers surfaceworldnode (testing?) or the viewleaf could @@ -1689,7 +496,7 @@ void R_Q1BSP_Draw(entity_render_t *ent) for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++) if (brush->colbrushf && brush->colbrushf->numtriangles) R_DrawCollisionBrush(brush->colbrushf); - for (i = 0, surface = model->brush.data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++) + for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++) if (surface->num_collisiontriangles) R_DrawCollisionSurface(ent, surface); qglPolygonOffset(0, 0); @@ -1760,7 +567,7 @@ void R_Q1BSP_RecursiveGetLightInfo(r_q1bsp_getlightinfo_t *info, mnode_t *node) int surfaceindex = leaf->firstleafsurface[leafsurfaceindex]; if (!CHECKPVSBIT(info->outsurfacepvs, surfaceindex)) { - msurface_t *surface = info->model->brush.data_surfaces + surfaceindex; + msurface_t *surface = info->model->data_surfaces + surfaceindex; if (BoxesOverlap(info->lightmins, info->lightmaxs, surface->mins, surface->maxs)) if ((surface->texture->currentmaterialflags & (MATERIALFLAG_WALL | MATERIALFLAG_NODRAW | MATERIALFLAG_TRANSPARENT)) == MATERIALFLAG_WALL) { @@ -1861,7 +668,7 @@ void R_Q1BSP_DrawShadowVolume(entity_render_t *ent, vec3_t relativelightorigin, R_UpdateAllTextureInfo(ent); for (surfacelistindex = 0;surfacelistindex < numsurfaces;surfacelistindex++) { - surface = model->brush.data_surfaces + surfacelist[surfacelistindex]; + surface = model->data_surfaces + surfacelist[surfacelistindex]; if ((surface->texture->currentmaterialflags & (MATERIALFLAG_NODRAW | MATERIALFLAG_TRANSPARENT | MATERIALFLAG_WALL)) != MATERIALFLAG_WALL) continue; if (surface->texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) @@ -1885,7 +692,7 @@ void R_Q1BSP_DrawLight(entity_render_t *ent, float *lightcolor, int numsurfaces, R_UpdateAllTextureInfo(ent); for (surfacelistindex = 0;surfacelistindex < numsurfaces;surfacelistindex++) { - surface = model->brush.data_surfaces + surfacelist[surfacelistindex]; + surface = model->data_surfaces + surfacelist[surfacelistindex]; if (surface->texture->basematerialflags & MATERIALFLAG_NODRAW || !surface->num_triangles) continue; if (r_shadow_compilingrtlight) @@ -1957,7 +764,6 @@ void GL_Surf_Init(void) Cvar_RegisterVariable(&r_drawcollisionbrushes_polygonfactor); Cvar_RegisterVariable(&r_drawcollisionbrushes_polygonoffset); Cvar_RegisterVariable(&r_q3bsp_renderskydepth); - Cvar_RegisterVariable(&gl_lightmaps); //R_RegisterModule("GL_Surf", gl_surf_start, gl_surf_shutdown, gl_surf_newmap); } diff --git a/model_alias.c b/model_alias.c index 2fb1a359..8334f3ec 100644 --- a/model_alias.c +++ b/model_alias.c @@ -26,27 +26,27 @@ void Mod_AliasInit (void) { } -void Mod_Alias_GetMesh_Vertex3f(const model_t *model, const frameblend_t *frameblend, const aliasmesh_t *mesh, float *out3f) +void Mod_Alias_GetMesh_Vertex3f(const model_t *model, const frameblend_t *frameblend, const surfmesh_t *mesh, float *out3f) { if (mesh->num_vertexboneweights) { int i, k, blends; - aliasvertexboneweight_t *v; + surfmeshvertexboneweight_t *v; float *out, *matrix, m[12], bonepose[256][12]; // vertex weighted skeletal // interpolate matrices and concatenate them to their parents - for (i = 0;i < model->alias.aliasnum_bones;i++) + for (i = 0;i < model->num_bones;i++) { for (k = 0;k < 12;k++) m[k] = 0; for (blends = 0;blends < 4 && frameblend[blends].lerp > 0;blends++) { - matrix = model->alias.aliasdata_poses + (frameblend[blends].frame * model->alias.aliasnum_bones + i) * 12; + matrix = model->data_poses + (frameblend[blends].frame * model->num_bones + i) * 12; for (k = 0;k < 12;k++) m[k] += matrix[k] * frameblend[blends].lerp; } - if (model->alias.aliasdata_bones[i].parent >= 0) - R_ConcatTransforms(bonepose[model->alias.aliasdata_bones[i].parent], m, bonepose[i]); + if (model->data_bones[i].parent >= 0) + R_ConcatTransforms(bonepose[model->data_bones[i].parent], m, bonepose[i]); else for (k = 0;k < 12;k++) bonepose[i][k] = m[k]; @@ -107,19 +107,19 @@ int Mod_Alias_GetTagMatrix(const model_t *model, int poseframe, int tagindex, ma const float *boneframe; float tempbonematrix[12], bonematrix[12]; Matrix4x4_CreateIdentity(outmatrix); - if (model->alias.aliasnum_bones) + if (model->num_bones) { - if (tagindex < 0 || tagindex >= model->alias.aliasnum_bones) + if (tagindex < 0 || tagindex >= model->num_bones) return 4; - if (poseframe >= model->alias.aliasnum_poses) + if (poseframe >= model->num_poses) return 6; - boneframe = model->alias.aliasdata_poses + poseframe * model->alias.aliasnum_bones * 12; + boneframe = model->data_poses + poseframe * model->num_bones * 12; memcpy(bonematrix, boneframe + tagindex * 12, sizeof(float[12])); - while (model->alias.aliasdata_bones[tagindex].parent >= 0) + while (model->data_bones[tagindex].parent >= 0) { memcpy(tempbonematrix, bonematrix, sizeof(float[12])); - R_ConcatTransforms(boneframe + model->alias.aliasdata_bones[tagindex].parent * 12, tempbonematrix, bonematrix); - tagindex = model->alias.aliasdata_bones[tagindex].parent; + R_ConcatTransforms(boneframe + model->data_bones[tagindex].parent * 12, tempbonematrix, bonematrix); + tagindex = model->data_bones[tagindex].parent; } outmatrix->m[0][0] = bonematrix[0]; outmatrix->m[0][1] = bonematrix[1]; @@ -138,13 +138,13 @@ int Mod_Alias_GetTagMatrix(const model_t *model, int poseframe, int tagindex, ma outmatrix->m[3][2] = 0; outmatrix->m[3][3] = 1; } - else if (model->alias.aliasnum_tags) + else if (model->num_tags) { - if (tagindex < 0 || tagindex >= model->alias.aliasnum_tags) + if (tagindex < 0 || tagindex >= model->num_tags) return 4; - if (poseframe >= model->alias.aliasnum_tagframes) + if (poseframe >= model->num_tagframes) return 6; - *outmatrix = model->alias.aliasdata_tags[poseframe * model->alias.aliasnum_tags + tagindex].matrix; + *outmatrix = model->data_tags[poseframe * model->num_tags + tagindex].matrix; } return 0; } @@ -156,32 +156,35 @@ int Mod_Alias_GetTagIndexForName(const model_t *model, unsigned int skin, const for (i = 0;i < model->data_overridetagnamesforskin[skin].num_overridetagnames;i++) if (!strcasecmp(tagname, model->data_overridetagnamesforskin[skin].data_overridetagnames[i].name)) return i + 1; - if (model->alias.aliasnum_bones) - for (i = 0;i < model->alias.aliasnum_bones;i++) - if (!strcasecmp(tagname, model->alias.aliasdata_bones[i].name)) + if (model->num_bones) + for (i = 0;i < model->num_bones;i++) + if (!strcasecmp(tagname, model->data_bones[i].name)) return i + 1; - if (model->alias.aliasnum_tags) - for (i = 0;i < model->alias.aliasnum_tags;i++) - if (!strcasecmp(tagname, model->alias.aliasdata_tags[i].name)) + if (model->num_tags) + for (i = 0;i < model->num_tags;i++) + if (!strcasecmp(tagname, model->data_tags[i].name)) return i + 1; return 0; } -static void Mod_Alias_Mesh_CompileFrameZero(aliasmesh_t *mesh) +static void Mod_Alias_Mesh_CompileFrameZero(surfmesh_t *mesh) { frameblend_t frameblend[4] = {{0, 1}, {0, 0}, {0, 0}, {0, 0}}; - mesh->data_basevertex3f = Mem_Alloc(loadmodel->mempool, mesh->num_vertices * sizeof(float[3][4])); - mesh->data_basesvector3f = mesh->data_basevertex3f + mesh->num_vertices * 3; - mesh->data_basetvector3f = mesh->data_basevertex3f + mesh->num_vertices * 6; - mesh->data_basenormal3f = mesh->data_basevertex3f + mesh->num_vertices * 9; - Mod_Alias_GetMesh_Vertex3f(loadmodel, frameblend, mesh, mesh->data_basevertex3f); - Mod_BuildTextureVectorsAndNormals(0, mesh->num_vertices, mesh->num_triangles, mesh->data_basevertex3f, mesh->data_texcoord2f, mesh->data_element3i, mesh->data_basesvector3f, mesh->data_basetvector3f, mesh->data_basenormal3f); + mesh->data_vertex3f = Mem_Alloc(loadmodel->mempool, mesh->num_vertices * sizeof(float[3][4])); + mesh->data_svector3f = mesh->data_vertex3f + mesh->num_vertices * 3; + mesh->data_tvector3f = mesh->data_vertex3f + mesh->num_vertices * 6; + mesh->data_normal3f = mesh->data_vertex3f + mesh->num_vertices * 9; + Mod_Alias_GetMesh_Vertex3f(loadmodel, frameblend, mesh, mesh->data_vertex3f); + Mod_BuildTextureVectorsAndNormals(0, mesh->num_vertices, mesh->num_triangles, mesh->data_vertex3f, mesh->data_texcoordtexture2f, mesh->data_element3i, mesh->data_svector3f, mesh->data_tvector3f, mesh->data_normal3f); } static void Mod_MDLMD2MD3_TraceBox(model_t *model, int frame, trace_t *trace, const vec3_t boxstartmins, const vec3_t boxstartmaxs, const vec3_t boxendmins, const vec3_t boxendmaxs, int hitsupercontentsmask) { - int i, framenum; + int i, framenum, linetrace; + float *vertex3f; float segmentmins[3], segmentmaxs[3]; + msurface_t *surface; + surfmesh_t *mesh; colbrushf_t *thisbrush_start, *thisbrush_end; matrix4x4_t startmatrix, endmatrix; memset(trace, 0, sizeof(*trace)); @@ -194,37 +197,32 @@ static void Mod_MDLMD2MD3_TraceBox(model_t *model, int frame, trace_t *trace, co segmentmaxs[0] = max(boxstartmaxs[0], boxendmaxs[0]); segmentmaxs[1] = max(boxstartmaxs[1], boxendmaxs[1]); segmentmaxs[2] = max(boxstartmaxs[2], boxendmaxs[2]); - if (VectorCompare(boxstartmins, boxstartmaxs) && VectorCompare(boxendmins, boxendmaxs)) - { - // line trace - for (i = 0;i < model->alias.aliasnum_meshes;i++) - { - framenum = frame; - if (framenum < 0 || framenum > model->alias.aliasdata_meshes[i].num_morphframes) - framenum = 0; - if (model->alias.aliasdata_meshes[i].data_morphvertex3f) - Collision_TraceLineTriangleMeshFloat(trace, boxstartmins, boxendmins, model->alias.aliasdata_meshes[i].num_triangles, model->alias.aliasdata_meshes[i].data_element3i, model->alias.aliasdata_meshes[i].data_morphvertex3f + framenum * model->alias.aliasdata_meshes[i].num_vertices * 3, SUPERCONTENTS_SOLID, segmentmins, segmentmaxs); - //else - // FIXME!!! this needs to handle skeletal! - } - } - else + linetrace = VectorCompare(boxstartmins, boxstartmaxs) && VectorCompare(boxendmins, boxendmaxs); + if (!linetrace) { // box trace, performed as brush trace Matrix4x4_CreateIdentity(&startmatrix); Matrix4x4_CreateIdentity(&endmatrix); thisbrush_start = Collision_BrushForBox(&startmatrix, boxstartmins, boxstartmaxs); thisbrush_end = Collision_BrushForBox(&endmatrix, boxendmins, boxendmaxs); - for (i = 0;i < model->alias.aliasnum_meshes;i++) + } + for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++) + { + mesh = surface->groupmesh; + framenum = frame; + if (framenum < 0 || framenum > mesh->num_morphframes) + framenum = 0; + if (mesh->data_morphvertex3f) + vertex3f = mesh->data_morphvertex3f + framenum * mesh->num_vertices * 3; + else { - framenum = frame; - if (framenum < 0 || framenum > model->alias.aliasdata_meshes[i].num_morphframes) - framenum = 0; - if (model->alias.aliasdata_meshes[i].data_morphvertex3f) - Collision_TraceBrushTriangleMeshFloat(trace, thisbrush_start, thisbrush_end, model->alias.aliasdata_meshes[i].num_triangles, model->alias.aliasdata_meshes[i].data_element3i, model->alias.aliasdata_meshes[i].data_morphvertex3f + framenum * model->alias.aliasdata_meshes[i].num_vertices * 3, SUPERCONTENTS_SOLID, segmentmins, segmentmaxs); - //else - // FIXME!!! this needs to handle skeletal! + vertex3f = varray_vertex3f; + continue; // FIXME!!! this needs to handle skeletal! } + if (linetrace) + Collision_TraceLineTriangleMeshFloat(trace, boxstartmins, boxendmins, mesh->num_triangles, mesh->data_element3i, vertex3f, SUPERCONTENTS_SOLID, segmentmins, segmentmaxs); + else + Collision_TraceBrushTriangleMeshFloat(trace, thisbrush_start, thisbrush_end, mesh->num_triangles, mesh->data_element3i, vertex3f, SUPERCONTENTS_SOLID, segmentmins, segmentmaxs); } } @@ -232,14 +230,15 @@ static void Mod_CalcAliasModelBBoxes (void) { int vnum, meshnum; float dist, yawradius, radius; - aliasmesh_t *mesh; + surfmesh_t *mesh; float *v; VectorClear(loadmodel->normalmins); VectorClear(loadmodel->normalmaxs); yawradius = 0; radius = 0; - for (meshnum = 0, mesh = loadmodel->alias.aliasdata_meshes;meshnum < loadmodel->alias.aliasnum_meshes;meshnum++, mesh++) + for (meshnum = 0;meshnum < loadmodel->num_surfaces;meshnum++) { + mesh = loadmodel->meshlist[meshnum]; for (vnum = 0, v = mesh->data_morphvertex3f;vnum < mesh->num_vertices * mesh->num_morphframes;vnum++, v += 3) { if (loadmodel->normalmins[0] > v[0]) loadmodel->normalmins[0] = v[0]; @@ -343,7 +342,7 @@ static void Mod_MDL_LoadFrames (qbyte* datapointer, int inverts, vec3_t scale, v { pinframe = (daliasframe_t *)datapointer; datapointer += sizeof(daliasframe_t); - Mod_ConvertAliasVerts(inverts, scale, translate, (trivertx_t *)datapointer, loadmodel->alias.aliasdata_meshes->data_morphvertex3f + pose * loadmodel->alias.aliasdata_meshes->num_vertices * 3, vertremap); + Mod_ConvertAliasVerts(inverts, scale, translate, (trivertx_t *)datapointer, loadmodel->meshlist[0]->data_morphvertex3f + pose * loadmodel->meshlist[0]->num_vertices * 3, vertremap); datapointer += sizeof(trivertx_t) * inverts; pose++; } @@ -422,6 +421,8 @@ void Mod_IDP0_Load(model_t *mod, void *buffer) { int i, j, version, totalskins, skinwidth, skinheight, groupframes, groupskins, numverts; float scales, scalet, scale[3], translate[3], interval; + msurface_t *surface; + qbyte *data; mdl_t *pinmodel; stvert_t *pinstverts; dtriangle_t *pintriangles; @@ -455,8 +456,13 @@ void Mod_IDP0_Load(model_t *mod, void *buffer) loadmodel->DrawLight = R_Model_Alias_DrawLight; loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox; - loadmodel->alias.aliasnum_meshes = 1; - loadmodel->alias.aliasdata_meshes = Mem_Alloc(loadmodel->mempool, sizeof(aliasmesh_t)); + loadmodel->num_surfaces = 1; + loadmodel->nummeshes = loadmodel->num_surfaces; + data = Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->nummeshes * sizeof(surfmesh_t *) + loadmodel->nummeshes * sizeof(surfmesh_t)); + loadmodel->data_surfaces = (void *)data;data += loadmodel->num_surfaces * sizeof(msurface_t); + loadmodel->meshlist = (void *)data;data += loadmodel->num_surfaces * sizeof(surfmesh_t *); + for (i = 0;i < loadmodel->num_surfaces;i++) + loadmodel->meshlist[i] = (void *)data;data += sizeof(surfmesh_t); loadmodel->numskins = LittleLong(pinmodel->numskins); BOUNDI(loadmodel->numskins,0,65536); @@ -466,8 +472,8 @@ void Mod_IDP0_Load(model_t *mod, void *buffer) BOUNDI(skinheight,0,65536); numverts = LittleLong(pinmodel->numverts); BOUNDI(numverts,0,65536); - loadmodel->alias.aliasdata_meshes->num_triangles = LittleLong(pinmodel->numtris); - BOUNDI(loadmodel->alias.aliasdata_meshes->num_triangles,0,65536); + loadmodel->meshlist[0]->num_triangles = LittleLong(pinmodel->numtris); + BOUNDI(loadmodel->meshlist[0]->num_triangles,0,65536); loadmodel->numframes = LittleLong(pinmodel->numframes); BOUNDI(loadmodel->numframes,0,65536); loadmodel->synctype = LittleLong (pinmodel->synctype); @@ -507,10 +513,10 @@ void Mod_IDP0_Load(model_t *mod, void *buffer) datapointer += sizeof(stvert_t) * numverts; pintriangles = (dtriangle_t *)datapointer; - datapointer += sizeof(dtriangle_t) * loadmodel->alias.aliasdata_meshes->num_triangles; + datapointer += sizeof(dtriangle_t) * loadmodel->meshlist[0]->num_triangles; startframes = datapointer; - loadmodel->alias.aliasdata_meshes->num_morphframes = 0; + loadmodel->meshlist[0]->num_morphframes = 0; for (i = 0;i < loadmodel->numframes;i++) { pinframetype = (daliasframetype_t *)datapointer; @@ -529,7 +535,7 @@ void Mod_IDP0_Load(model_t *mod, void *buffer) { datapointer += sizeof(daliasframe_t); datapointer += sizeof(trivertx_t) * numverts; - loadmodel->alias.aliasdata_meshes->num_morphframes++; + loadmodel->meshlist[0]->num_morphframes++; } } @@ -551,60 +557,60 @@ void Mod_IDP0_Load(model_t *mod, void *buffer) } // load triangle data - loadmodel->alias.aliasdata_meshes->data_element3i = Mem_Alloc(loadmodel->mempool, sizeof(int[3]) * loadmodel->alias.aliasdata_meshes->num_triangles); + loadmodel->meshlist[0]->data_element3i = Mem_Alloc(loadmodel->mempool, sizeof(int[3]) * loadmodel->meshlist[0]->num_triangles); // read the triangle elements - for (i = 0;i < loadmodel->alias.aliasdata_meshes->num_triangles;i++) + for (i = 0;i < loadmodel->meshlist[0]->num_triangles;i++) for (j = 0;j < 3;j++) - loadmodel->alias.aliasdata_meshes->data_element3i[i*3+j] = LittleLong(pintriangles[i].vertindex[j]); + loadmodel->meshlist[0]->data_element3i[i*3+j] = LittleLong(pintriangles[i].vertindex[j]); // validate (note numverts is used because this is the original data) - Mod_ValidateElements(loadmodel->alias.aliasdata_meshes->data_element3i, loadmodel->alias.aliasdata_meshes->num_triangles, numverts, __FILE__, __LINE__); + Mod_ValidateElements(loadmodel->meshlist[0]->data_element3i, loadmodel->meshlist[0]->num_triangles, numverts, __FILE__, __LINE__); // now butcher the elements according to vertonseam and tri->facesfront // and then compact the vertex set to remove duplicates - for (i = 0;i < loadmodel->alias.aliasdata_meshes->num_triangles;i++) + for (i = 0;i < loadmodel->meshlist[0]->num_triangles;i++) if (!LittleLong(pintriangles[i].facesfront)) // backface for (j = 0;j < 3;j++) - if (vertonseam[loadmodel->alias.aliasdata_meshes->data_element3i[i*3+j]]) - loadmodel->alias.aliasdata_meshes->data_element3i[i*3+j] += numverts; + if (vertonseam[loadmodel->meshlist[0]->data_element3i[i*3+j]]) + loadmodel->meshlist[0]->data_element3i[i*3+j] += numverts; // count the usage // (this uses vertremap to count usage to save some memory) for (i = 0;i < numverts*2;i++) vertremap[i] = 0; - for (i = 0;i < loadmodel->alias.aliasdata_meshes->num_triangles*3;i++) - vertremap[loadmodel->alias.aliasdata_meshes->data_element3i[i]]++; + for (i = 0;i < loadmodel->meshlist[0]->num_triangles*3;i++) + vertremap[loadmodel->meshlist[0]->data_element3i[i]]++; // build remapping table and compact array - loadmodel->alias.aliasdata_meshes->num_vertices = 0; + loadmodel->meshlist[0]->num_vertices = 0; for (i = 0;i < numverts*2;i++) { if (vertremap[i]) { - vertremap[i] = loadmodel->alias.aliasdata_meshes->num_vertices; - vertst[loadmodel->alias.aliasdata_meshes->num_vertices*2+0] = vertst[i*2+0]; - vertst[loadmodel->alias.aliasdata_meshes->num_vertices*2+1] = vertst[i*2+1]; - loadmodel->alias.aliasdata_meshes->num_vertices++; + vertremap[i] = loadmodel->meshlist[0]->num_vertices; + vertst[loadmodel->meshlist[0]->num_vertices*2+0] = vertst[i*2+0]; + vertst[loadmodel->meshlist[0]->num_vertices*2+1] = vertst[i*2+1]; + loadmodel->meshlist[0]->num_vertices++; } else vertremap[i] = -1; // not used at all } // remap the elements to the new vertex set - for (i = 0;i < loadmodel->alias.aliasdata_meshes->num_triangles * 3;i++) - loadmodel->alias.aliasdata_meshes->data_element3i[i] = vertremap[loadmodel->alias.aliasdata_meshes->data_element3i[i]]; + for (i = 0;i < loadmodel->meshlist[0]->num_triangles * 3;i++) + loadmodel->meshlist[0]->data_element3i[i] = vertremap[loadmodel->meshlist[0]->data_element3i[i]]; // store the texture coordinates - loadmodel->alias.aliasdata_meshes->data_texcoord2f = Mem_Alloc(loadmodel->mempool, sizeof(float[2]) * loadmodel->alias.aliasdata_meshes->num_vertices); - for (i = 0;i < loadmodel->alias.aliasdata_meshes->num_vertices;i++) + loadmodel->meshlist[0]->data_texcoordtexture2f = Mem_Alloc(loadmodel->mempool, sizeof(float[2]) * loadmodel->meshlist[0]->num_vertices); + for (i = 0;i < loadmodel->meshlist[0]->num_vertices;i++) { - loadmodel->alias.aliasdata_meshes->data_texcoord2f[i*2+0] = vertst[i*2+0]; - loadmodel->alias.aliasdata_meshes->data_texcoord2f[i*2+1] = vertst[i*2+1]; + loadmodel->meshlist[0]->data_texcoordtexture2f[i*2+0] = vertst[i*2+0]; + loadmodel->meshlist[0]->data_texcoordtexture2f[i*2+1] = vertst[i*2+1]; } // load the frames loadmodel->animscenes = Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes); - loadmodel->alias.aliasdata_meshes->data_morphvertex3f = Mem_Alloc(loadmodel->mempool, sizeof(float[3]) * loadmodel->alias.aliasdata_meshes->num_morphframes * loadmodel->alias.aliasdata_meshes->num_vertices); - loadmodel->alias.aliasdata_meshes->data_neighbor3i = Mem_Alloc(loadmodel->mempool, loadmodel->alias.aliasdata_meshes->num_triangles * sizeof(int[3])); + loadmodel->meshlist[0]->data_morphvertex3f = Mem_Alloc(loadmodel->mempool, sizeof(float[3]) * loadmodel->meshlist[0]->num_morphframes * loadmodel->meshlist[0]->num_vertices); + loadmodel->meshlist[0]->data_neighbor3i = Mem_Alloc(loadmodel->mempool, loadmodel->meshlist[0]->num_triangles * sizeof(int[3])); Mod_MDL_LoadFrames (startframes, numverts, scale, translate, vertremap); - Mod_BuildTriangleNeighbors(loadmodel->alias.aliasdata_meshes->data_neighbor3i, loadmodel->alias.aliasdata_meshes->data_element3i, loadmodel->alias.aliasdata_meshes->num_triangles); + Mod_BuildTriangleNeighbors(loadmodel->meshlist[0]->data_neighbor3i, loadmodel->meshlist[0]->data_element3i, loadmodel->meshlist[0]->num_triangles); Mod_CalcAliasModelBBoxes(); - Mod_Alias_Mesh_CompileFrameZero(loadmodel->alias.aliasdata_meshes); + Mod_Alias_Mesh_CompileFrameZero(loadmodel->meshlist[0]); Mem_Free(vertst); Mem_Free(vertremap); @@ -612,9 +618,9 @@ void Mod_IDP0_Load(model_t *mod, void *buffer) // load the skins if ((skinfiles = Mod_LoadSkinFiles())) { - loadmodel->alias.aliasdata_meshes->num_skins = totalskins = loadmodel->numskins; - loadmodel->alias.aliasdata_meshes->data_skins = Mem_Alloc(loadmodel->mempool, loadmodel->alias.aliasdata_meshes->num_skins * sizeof(texture_t)); - Mod_BuildAliasSkinsFromSkinFiles(loadmodel->alias.aliasdata_meshes->data_skins, skinfiles, "default", ""); + loadmodel->meshlist[0]->num_skins = totalskins = loadmodel->numskins; + loadmodel->meshlist[0]->data_skins = Mem_Alloc(loadmodel->mempool, loadmodel->meshlist[0]->num_skins * sizeof(texture_t)); + Mod_BuildAliasSkinsFromSkinFiles(loadmodel->meshlist[0]->data_skins, skinfiles, "default", ""); Mod_FreeSkinFiles(skinfiles); loadmodel->skinscenes = Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins); for (i = 0;i < loadmodel->numskins;i++) @@ -627,8 +633,8 @@ void Mod_IDP0_Load(model_t *mod, void *buffer) } else { - loadmodel->alias.aliasdata_meshes->num_skins = totalskins; - loadmodel->alias.aliasdata_meshes->data_skins = Mem_Alloc(loadmodel->mempool, loadmodel->alias.aliasdata_meshes->num_skins * sizeof(texture_t)); + loadmodel->meshlist[0]->num_skins = totalskins; + loadmodel->meshlist[0]->data_skins = Mem_Alloc(loadmodel->mempool, loadmodel->meshlist[0]->num_skins * sizeof(texture_t)); loadmodel->skinscenes = Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t)); totalskins = 0; datapointer = startskins; @@ -674,7 +680,7 @@ void Mod_IDP0_Load(model_t *mod, void *buffer) sprintf (name, "%s_%i", loadmodel->name, i); if (!Mod_LoadSkinFrame(&tempskinframe, name, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_CLAMP | TEXF_ALPHA | TEXF_PICMIP, true, false, true)) Mod_LoadSkinFrame_Internal(&tempskinframe, name, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_CLAMP | TEXF_ALPHA | TEXF_PICMIP, true, false, r_fullbrights.integer, (qbyte *)datapointer, skinwidth, skinheight); - Mod_BuildAliasSkinFromSkinFrame(loadmodel->alias.aliasdata_meshes->data_skins + totalskins, &tempskinframe); + Mod_BuildAliasSkinFromSkinFrame(loadmodel->meshlist[0]->data_skins + totalskins, &tempskinframe); datapointer += skinwidth * skinheight; totalskins++; } @@ -689,13 +695,13 @@ void Mod_IDP0_Load(model_t *mod, void *buffer) memcpy(loadmodel->skinscenes, tempskinscenes, loadmodel->numskins * sizeof(animscene_t)); Mem_Free(tempskinscenes); - tempaliasskins = loadmodel->alias.aliasdata_meshes->data_skins; - loadmodel->alias.aliasdata_meshes->data_skins = Mem_Alloc(loadmodel->mempool, (totalskins + 1) * sizeof(texture_t)); - memcpy(loadmodel->alias.aliasdata_meshes->data_skins, tempaliasskins, totalskins * sizeof(texture_t)); + tempaliasskins = loadmodel->meshlist[0]->data_skins; + loadmodel->meshlist[0]->data_skins = Mem_Alloc(loadmodel->mempool, (totalskins + 1) * sizeof(texture_t)); + memcpy(loadmodel->meshlist[0]->data_skins, tempaliasskins, totalskins * sizeof(texture_t)); Mem_Free(tempaliasskins); // store the info about the new skin - Mod_BuildAliasSkinFromSkinFrame(loadmodel->alias.aliasdata_meshes->data_skins + totalskins, &tempskinframe); + Mod_BuildAliasSkinFromSkinFrame(loadmodel->meshlist[0]->data_skins + totalskins, &tempskinframe); strcpy(loadmodel->skinscenes[loadmodel->numskins].name, name); loadmodel->skinscenes[loadmodel->numskins].firstframe = totalskins; loadmodel->skinscenes[loadmodel->numskins].framecount = 1; @@ -703,11 +709,20 @@ void Mod_IDP0_Load(model_t *mod, void *buffer) loadmodel->skinscenes[loadmodel->numskins].loop = true; //increase skin counts - loadmodel->alias.aliasdata_meshes->num_skins++; + loadmodel->meshlist[0]->num_skins++; loadmodel->numskins++; totalskins++; } } + + surface = loadmodel->data_surfaces; + surface->groupmesh = loadmodel->meshlist[0]; + // FIXME: need to store data_skins in msurface_t, not surfmesh_t + surface->texture = surface->groupmesh->data_skins; + surface->num_firsttriangle = 0; + surface->num_triangles = surface->groupmesh->num_triangles; + surface->num_firstvertex = 0; + surface->num_vertices = surface->groupmesh->num_vertices; } static void Mod_MD2_ConvertVerts (vec3_t scale, vec3_t translate, trivertx_t *v, float *out3f, int numverts, int *vertremap) @@ -727,6 +742,8 @@ void Mod_IDP2_Load(model_t *mod, void *buffer) { int i, j, k, hashindex, num, numxyz, numst, xyz, st, skinwidth, skinheight, *vertremap, version, end, numverts; float *stverts, s, t, scale[3], translate[3]; + qbyte *data; + msurface_t *surface; md2_t *pinmodel; qbyte *base, *datapointer; md2frame_t *pinframe; @@ -779,15 +796,20 @@ void Mod_IDP2_Load(model_t *mod, void *buffer) if (LittleLong(pinmodel->ofs_glcmds) <= 0 || LittleLong(pinmodel->ofs_glcmds) >= end) Host_Error ("%s is not a valid model", loadmodel->name); - loadmodel->alias.aliasnum_meshes = 1; - loadmodel->alias.aliasdata_meshes = Mem_Alloc(loadmodel->mempool, sizeof(aliasmesh_t)); + loadmodel->num_surfaces = 1; + loadmodel->nummeshes = loadmodel->num_surfaces; + data = Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->nummeshes * sizeof(surfmesh_t *) + loadmodel->nummeshes * sizeof(surfmesh_t)); + loadmodel->data_surfaces = (void *)data;data += loadmodel->num_surfaces * sizeof(msurface_t); + loadmodel->meshlist = (void *)data;data += loadmodel->num_surfaces * sizeof(surfmesh_t *); + for (i = 0;i < loadmodel->num_surfaces;i++) + loadmodel->meshlist[i] = (void *)data;data += sizeof(surfmesh_t); loadmodel->numskins = LittleLong(pinmodel->num_skins); numxyz = LittleLong(pinmodel->num_xyz); numst = LittleLong(pinmodel->num_st); - loadmodel->alias.aliasdata_meshes->num_triangles = LittleLong(pinmodel->num_tris); + loadmodel->meshlist[0]->num_triangles = LittleLong(pinmodel->num_tris); loadmodel->numframes = LittleLong(pinmodel->num_frames); - loadmodel->alias.aliasdata_meshes->num_morphframes = loadmodel->numframes; + loadmodel->meshlist[0]->num_morphframes = loadmodel->numframes; loadmodel->animscenes = Mem_Alloc(loadmodel->mempool, loadmodel->numframes * sizeof(animscene_t)); loadmodel->flags = 0; // there are no MD2 flags @@ -797,24 +819,24 @@ void Mod_IDP2_Load(model_t *mod, void *buffer) inskin = (void*)(base + LittleLong(pinmodel->ofs_skins)); if ((skinfiles = Mod_LoadSkinFiles())) { - loadmodel->alias.aliasdata_meshes->num_skins = loadmodel->numskins; - loadmodel->alias.aliasdata_meshes->data_skins = Mem_Alloc(loadmodel->mempool, loadmodel->alias.aliasdata_meshes->num_skins * sizeof(texture_t)); - Mod_BuildAliasSkinsFromSkinFiles(loadmodel->alias.aliasdata_meshes->data_skins, skinfiles, "default", ""); + loadmodel->meshlist[0]->num_skins = loadmodel->numskins; + loadmodel->meshlist[0]->data_skins = Mem_Alloc(loadmodel->mempool, loadmodel->meshlist[0]->num_skins * sizeof(texture_t)); + Mod_BuildAliasSkinsFromSkinFiles(loadmodel->meshlist[0]->data_skins, skinfiles, "default", ""); Mod_FreeSkinFiles(skinfiles); } else if (loadmodel->numskins) { // skins found (most likely not a player model) - loadmodel->alias.aliasdata_meshes->num_skins = loadmodel->numskins; - loadmodel->alias.aliasdata_meshes->data_skins = Mem_Alloc(loadmodel->mempool, loadmodel->alias.aliasdata_meshes->num_skins * sizeof(texture_t)); + loadmodel->meshlist[0]->num_skins = loadmodel->numskins; + loadmodel->meshlist[0]->data_skins = Mem_Alloc(loadmodel->mempool, loadmodel->meshlist[0]->num_skins * sizeof(texture_t)); for (i = 0;i < loadmodel->numskins;i++, inskin += MD2_SKINNAME) { if (Mod_LoadSkinFrame(&tempskinframe, inskin, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_CLAMP | TEXF_PRECACHE | TEXF_PICMIP, true, false, true)) - Mod_BuildAliasSkinFromSkinFrame(loadmodel->alias.aliasdata_meshes->data_skins + i, &tempskinframe); + Mod_BuildAliasSkinFromSkinFrame(loadmodel->meshlist[0]->data_skins + i, &tempskinframe); else { Con_Printf("%s is missing skin \"%s\"\n", loadmodel->name, inskin); - Mod_BuildAliasSkinFromSkinFrame(loadmodel->alias.aliasdata_meshes->data_skins + i, NULL); + Mod_BuildAliasSkinFromSkinFrame(loadmodel->meshlist[0]->data_skins + i, NULL); } } } @@ -822,9 +844,9 @@ void Mod_IDP2_Load(model_t *mod, void *buffer) { // no skins (most likely a player model) loadmodel->numskins = 1; - loadmodel->alias.aliasdata_meshes->num_skins = loadmodel->numskins; - loadmodel->alias.aliasdata_meshes->data_skins = Mem_Alloc(loadmodel->mempool, loadmodel->alias.aliasdata_meshes->num_skins * sizeof(texture_t)); - Mod_BuildAliasSkinFromSkinFrame(loadmodel->alias.aliasdata_meshes->data_skins, NULL); + loadmodel->meshlist[0]->num_skins = loadmodel->numskins; + loadmodel->meshlist[0]->data_skins = Mem_Alloc(loadmodel->mempool, loadmodel->meshlist[0]->num_skins * sizeof(texture_t)); + Mod_BuildAliasSkinFromSkinFrame(loadmodel->meshlist[0]->data_skins, NULL); } loadmodel->skinscenes = Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins); @@ -860,11 +882,11 @@ void Mod_IDP2_Load(model_t *mod, void *buffer) } md2verthash = Mem_Alloc(tempmempool, 256 * sizeof(hash)); - md2verthashdata = Mem_Alloc(tempmempool, loadmodel->alias.aliasdata_meshes->num_triangles * 3 * sizeof(*hash)); + md2verthashdata = Mem_Alloc(tempmempool, loadmodel->meshlist[0]->num_triangles * 3 * sizeof(*hash)); // swap the triangle list num = 0; - loadmodel->alias.aliasdata_meshes->data_element3i = Mem_Alloc(loadmodel->mempool, loadmodel->alias.aliasdata_meshes->num_triangles * sizeof(int[3])); - for (i = 0;i < loadmodel->alias.aliasdata_meshes->num_triangles;i++) + loadmodel->meshlist[0]->data_element3i = Mem_Alloc(loadmodel->mempool, loadmodel->meshlist[0]->num_triangles * sizeof(int[3])); + for (i = 0;i < loadmodel->meshlist[0]->num_triangles;i++) { for (j = 0;j < 3;j++) { @@ -895,22 +917,22 @@ void Mod_IDP2_Load(model_t *mod, void *buffer) hash->next = md2verthash[hashindex]; md2verthash[hashindex] = hash; } - loadmodel->alias.aliasdata_meshes->data_element3i[i*3+j] = (hash - md2verthashdata); + loadmodel->meshlist[0]->data_element3i[i*3+j] = (hash - md2verthashdata); } } Mem_Free(stverts); numverts = num; - loadmodel->alias.aliasdata_meshes->num_vertices = numverts; + loadmodel->meshlist[0]->num_vertices = numverts; vertremap = Mem_Alloc(loadmodel->mempool, num * sizeof(int)); - loadmodel->alias.aliasdata_meshes->data_texcoord2f = Mem_Alloc(loadmodel->mempool, num * sizeof(float[2])); + loadmodel->meshlist[0]->data_texcoordtexture2f = Mem_Alloc(loadmodel->mempool, num * sizeof(float[2])); for (i = 0;i < num;i++) { hash = md2verthashdata + i; vertremap[i] = hash->xyz; - loadmodel->alias.aliasdata_meshes->data_texcoord2f[i*2+0] = hash->st[0]; - loadmodel->alias.aliasdata_meshes->data_texcoord2f[i*2+1] = hash->st[1]; + loadmodel->meshlist[0]->data_texcoordtexture2f[i*2+0] = hash->st[0]; + loadmodel->meshlist[0]->data_texcoordtexture2f[i*2+1] = hash->st[1]; } Mem_Free(md2verthash); @@ -918,8 +940,8 @@ void Mod_IDP2_Load(model_t *mod, void *buffer) // load the frames datapointer = (base + LittleLong(pinmodel->ofs_frames)); - loadmodel->alias.aliasdata_meshes->data_morphvertex3f = Mem_Alloc(loadmodel->mempool, numverts * loadmodel->alias.aliasdata_meshes->num_morphframes * sizeof(float[3])); - for (i = 0;i < loadmodel->alias.aliasdata_meshes->num_morphframes;i++) + loadmodel->meshlist[0]->data_morphvertex3f = Mem_Alloc(loadmodel->mempool, numverts * loadmodel->meshlist[0]->num_morphframes * sizeof(float[3])); + for (i = 0;i < loadmodel->meshlist[0]->num_morphframes;i++) { pinframe = (md2frame_t *)datapointer; datapointer += sizeof(md2frame_t); @@ -928,7 +950,7 @@ void Mod_IDP2_Load(model_t *mod, void *buffer) scale[j] = LittleFloat(pinframe->scale[j]); translate[j] = LittleFloat(pinframe->translate[j]); } - Mod_MD2_ConvertVerts(scale, translate, (void *)datapointer, loadmodel->alias.aliasdata_meshes->data_morphvertex3f + i * numverts * 3, numverts, vertremap); + Mod_MD2_ConvertVerts(scale, translate, (void *)datapointer, loadmodel->meshlist[0]->data_morphvertex3f + i * numverts * 3, numverts, vertremap); datapointer += numxyz * sizeof(trivertx_t); strcpy(loadmodel->animscenes[i].name, pinframe->name); @@ -940,20 +962,31 @@ void Mod_IDP2_Load(model_t *mod, void *buffer) Mem_Free(vertremap); - loadmodel->alias.aliasdata_meshes->data_neighbor3i = Mem_Alloc(loadmodel->mempool, loadmodel->alias.aliasdata_meshes->num_triangles * sizeof(int[3])); - Mod_BuildTriangleNeighbors(loadmodel->alias.aliasdata_meshes->data_neighbor3i, loadmodel->alias.aliasdata_meshes->data_element3i, loadmodel->alias.aliasdata_meshes->num_triangles); + loadmodel->meshlist[0]->data_neighbor3i = Mem_Alloc(loadmodel->mempool, loadmodel->meshlist[0]->num_triangles * sizeof(int[3])); + Mod_BuildTriangleNeighbors(loadmodel->meshlist[0]->data_neighbor3i, loadmodel->meshlist[0]->data_element3i, loadmodel->meshlist[0]->num_triangles); Mod_CalcAliasModelBBoxes(); - Mod_Alias_Mesh_CompileFrameZero(loadmodel->alias.aliasdata_meshes); + Mod_Alias_Mesh_CompileFrameZero(loadmodel->meshlist[0]); + + surface = loadmodel->data_surfaces; + surface->groupmesh = loadmodel->meshlist[0]; + // FIXME: need to store data_skins in msurface_t, not surfmesh_t + surface->texture = surface->groupmesh->data_skins; + surface->num_firsttriangle = 0; + surface->num_triangles = surface->groupmesh->num_triangles; + surface->num_firstvertex = 0; + surface->num_vertices = surface->groupmesh->num_vertices; } void Mod_IDP3_Load(model_t *mod, void *buffer) { int i, j, k, version; + qbyte *data; + msurface_t *surface; + surfmesh_t *mesh; md3modelheader_t *pinmodel; md3frameinfo_t *pinframe; md3mesh_t *pinmesh; md3tag_t *pintag; - aliasmesh_t *mesh; skinfile_t *skinfiles; pinmodel = buffer; @@ -980,7 +1013,7 @@ void Mod_IDP3_Load(model_t *mod, void *buffer) // set up some global info about the model loadmodel->numframes = LittleLong(pinmodel->num_frames); - loadmodel->alias.aliasnum_meshes = LittleLong(pinmodel->num_meshes); + loadmodel->num_surfaces = LittleLong(pinmodel->num_meshes); // make skinscenes for the skins (no groups) loadmodel->skinscenes = Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins); @@ -1004,29 +1037,34 @@ void Mod_IDP3_Load(model_t *mod, void *buffer) } // load tags - loadmodel->alias.aliasnum_tagframes = loadmodel->numframes; - loadmodel->alias.aliasnum_tags = LittleLong(pinmodel->num_tags); - loadmodel->alias.aliasdata_tags = Mem_Alloc(loadmodel->mempool, loadmodel->alias.aliasnum_tagframes * loadmodel->alias.aliasnum_tags * sizeof(aliastag_t)); - for (i = 0, pintag = (md3tag_t *)((qbyte *)pinmodel + LittleLong(pinmodel->lump_tags));i < loadmodel->alias.aliasnum_tagframes * loadmodel->alias.aliasnum_tags;i++, pintag++) + loadmodel->num_tagframes = loadmodel->numframes; + loadmodel->num_tags = LittleLong(pinmodel->num_tags); + loadmodel->data_tags = Mem_Alloc(loadmodel->mempool, loadmodel->num_tagframes * loadmodel->num_tags * sizeof(aliastag_t)); + for (i = 0, pintag = (md3tag_t *)((qbyte *)pinmodel + LittleLong(pinmodel->lump_tags));i < loadmodel->num_tagframes * loadmodel->num_tags;i++, pintag++) { - strcpy(loadmodel->alias.aliasdata_tags[i].name, pintag->name); - Matrix4x4_CreateIdentity(&loadmodel->alias.aliasdata_tags[i].matrix); + strcpy(loadmodel->data_tags[i].name, pintag->name); + Matrix4x4_CreateIdentity(&loadmodel->data_tags[i].matrix); for (j = 0;j < 3;j++) { for (k = 0;k < 3;k++) - loadmodel->alias.aliasdata_tags[i].matrix.m[j][k] = LittleFloat(pintag->rotationmatrix[k * 3 + j]); - loadmodel->alias.aliasdata_tags[i].matrix.m[j][3] = LittleFloat(pintag->origin[j]); + loadmodel->data_tags[i].matrix.m[j][k] = LittleFloat(pintag->rotationmatrix[k * 3 + j]); + loadmodel->data_tags[i].matrix.m[j][3] = LittleFloat(pintag->origin[j]); } - //Con_Printf("model \"%s\" frame #%i tag #%i \"%s\"\n", loadmodel->name, i / loadmodel->alias.aliasnum_tags, i % loadmodel->alias.aliasnum_tags, loadmodel->alias.aliasdata_tags[i].name); + //Con_Printf("model \"%s\" frame #%i tag #%i \"%s\"\n", loadmodel->name, i / loadmodel->num_tags, i % loadmodel->num_tags, loadmodel->data_tags[i].name); } // load meshes - loadmodel->alias.aliasdata_meshes = Mem_Alloc(loadmodel->mempool, loadmodel->alias.aliasnum_meshes * sizeof(aliasmesh_t)); - for (i = 0, pinmesh = (md3mesh_t *)((qbyte *)pinmodel + LittleLong(pinmodel->lump_meshes));i < loadmodel->alias.aliasnum_meshes;i++, pinmesh = (md3mesh_t *)((qbyte *)pinmesh + LittleLong(pinmesh->lump_end))) + loadmodel->nummeshes = loadmodel->num_surfaces; + data = Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->nummeshes * sizeof(surfmesh_t *) + loadmodel->nummeshes * sizeof(surfmesh_t)); + loadmodel->data_surfaces = (void *)data;data += loadmodel->num_surfaces * sizeof(msurface_t); + loadmodel->meshlist = (void *)data;data += loadmodel->num_surfaces * sizeof(surfmesh_t *); + for (i = 0;i < loadmodel->num_surfaces;i++) + mesh = loadmodel->meshlist[i] = (void *)data;data += sizeof(surfmesh_t); + for (i = 0, pinmesh = (md3mesh_t *)((qbyte *)pinmodel + LittleLong(pinmodel->lump_meshes));i < loadmodel->num_surfaces;i++, pinmesh = (md3mesh_t *)((qbyte *)pinmesh + LittleLong(pinmesh->lump_end))) { if (memcmp(pinmesh->identifier, "IDP3", 4)) Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)\n"); - mesh = loadmodel->alias.aliasdata_meshes + i; + mesh = loadmodel->meshlist[i]; mesh->num_skins = loadmodel->numskins; mesh->num_morphframes = LittleLong(pinmesh->num_frames); mesh->num_vertices = LittleLong(pinmesh->num_vertices); @@ -1034,14 +1072,14 @@ void Mod_IDP3_Load(model_t *mod, void *buffer) mesh->data_skins = Mem_Alloc(loadmodel->mempool, mesh->num_skins * sizeof(texture_t)); mesh->data_element3i = Mem_Alloc(loadmodel->mempool, mesh->num_triangles * sizeof(int[3])); mesh->data_neighbor3i = Mem_Alloc(loadmodel->mempool, mesh->num_triangles * sizeof(int[3])); - mesh->data_texcoord2f = Mem_Alloc(loadmodel->mempool, mesh->num_vertices * sizeof(float[2])); + mesh->data_texcoordtexture2f = Mem_Alloc(loadmodel->mempool, mesh->num_vertices * sizeof(float[2])); mesh->data_morphvertex3f = Mem_Alloc(loadmodel->mempool, mesh->num_vertices * mesh->num_morphframes * sizeof(float[3])); for (j = 0;j < mesh->num_triangles * 3;j++) mesh->data_element3i[j] = LittleLong(((int *)((qbyte *)pinmesh + LittleLong(pinmesh->lump_elements)))[j]); for (j = 0;j < mesh->num_vertices;j++) { - mesh->data_texcoord2f[j * 2 + 0] = LittleFloat(((float *)((qbyte *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 0]); - mesh->data_texcoord2f[j * 2 + 1] = LittleFloat(((float *)((qbyte *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 1]); + mesh->data_texcoordtexture2f[j * 2 + 0] = LittleFloat(((float *)((qbyte *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 0]); + mesh->data_texcoordtexture2f[j * 2 + 1] = LittleFloat(((float *)((qbyte *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 1]); } for (j = 0;j < mesh->num_vertices * mesh->num_morphframes;j++) { @@ -1059,6 +1097,15 @@ void Mod_IDP3_Load(model_t *mod, void *buffer) else for (j = 0;j < mesh->num_skins;j++) Mod_BuildAliasSkinFromSkinFrame(mesh->data_skins + j, NULL); + + surface = loadmodel->data_surfaces + i; + surface->groupmesh = mesh; + // FIXME: need to store data_skins in msurface_t, not surfmesh_t + surface->texture = mesh->data_skins; + surface->num_firsttriangle = 0; + surface->num_triangles = mesh->num_triangles; + surface->num_firstvertex = 0; + surface->num_vertices = mesh->num_vertices; } Mod_CalcAliasModelBBoxes(); Mod_FreeSkinFiles(skinfiles); @@ -1075,7 +1122,9 @@ void Mod_ZYMOTICMODEL_Load(model_t *mod, void *buffer) zymbone_t *bone; char *shadername; skinfile_t *skinfiles; - aliasmesh_t *mesh; + qbyte *data; + msurface_t *surface; + surfmesh_t *mesh; pinmodel = (void *)buffer; pbase = buffer; @@ -1129,7 +1178,7 @@ void Mod_ZYMOTICMODEL_Load(model_t *mod, void *buffer) pheader->lump_trizone.length = BigLong(pinmodel->lump_trizone.length); loadmodel->numframes = pheader->numscenes; - loadmodel->alias.aliasnum_meshes = pheader->numshaders; + loadmodel->num_surfaces = pheader->numshaders; skinfiles = Mod_LoadSkinFiles(); if (loadmodel->numskins < 1) @@ -1188,22 +1237,22 @@ void Mod_ZYMOTICMODEL_Load(model_t *mod, void *buffer) } //zymlump_t lump_poses; // float pose[numposes][numbones][3][4]; // animation data - loadmodel->alias.aliasnum_poses = pheader->lump_poses.length / sizeof(float[3][4]); - loadmodel->alias.aliasdata_poses = Mem_Alloc(loadmodel->mempool, pheader->lump_poses.length); + loadmodel->num_poses = pheader->lump_poses.length / sizeof(float[3][4]); + loadmodel->data_poses = Mem_Alloc(loadmodel->mempool, pheader->lump_poses.length); poses = (void *) (pheader->lump_poses.start + pbase); for (i = 0;i < pheader->lump_poses.length / 4;i++) - loadmodel->alias.aliasdata_poses[i] = BigFloat(poses[i]); + loadmodel->data_poses[i] = BigFloat(poses[i]); //zymlump_t lump_bones; // zymbone_t bone[numbones]; - loadmodel->alias.aliasnum_bones = pheader->numbones; - loadmodel->alias.aliasdata_bones = Mem_Alloc(loadmodel->mempool, pheader->numbones * sizeof(aliasbone_t)); + loadmodel->num_bones = pheader->numbones; + loadmodel->data_bones = Mem_Alloc(loadmodel->mempool, pheader->numbones * sizeof(aliasbone_t)); bone = (void *) (pheader->lump_bones.start + pbase); for (i = 0;i < pheader->numbones;i++) { - memcpy(loadmodel->alias.aliasdata_bones[i].name, bone[i].name, sizeof(bone[i].name)); - loadmodel->alias.aliasdata_bones[i].flags = BigLong(bone[i].flags); - loadmodel->alias.aliasdata_bones[i].parent = BigLong(bone[i].parent); - if (loadmodel->alias.aliasdata_bones[i].parent >= i) + memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name)); + loadmodel->data_bones[i].flags = BigLong(bone[i].flags); + loadmodel->data_bones[i].parent = BigLong(bone[i].parent); + if (loadmodel->data_bones[i].parent >= i) Host_Error("%s bone[%i].parent >= %i\n", loadmodel->name, i, i); } @@ -1242,7 +1291,12 @@ void Mod_ZYMOTICMODEL_Load(model_t *mod, void *buffer) //loadmodel->alias.zymdata_trizone = Mem_Alloc(loadmodel->mempool, pheader->numtris); //memcpy(loadmodel->alias.zymdata_trizone, (void *) (pheader->lump_trizone.start + pbase), pheader->numtris); - loadmodel->alias.aliasdata_meshes = Mem_Alloc(loadmodel->mempool, loadmodel->alias.aliasnum_meshes * sizeof(aliasmesh_t)); + loadmodel->nummeshes = loadmodel->num_surfaces; + data = Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->nummeshes * sizeof(surfmesh_t *) + loadmodel->nummeshes * sizeof(surfmesh_t)); + loadmodel->data_surfaces = (void *)data;data += loadmodel->num_surfaces * sizeof(msurface_t); + loadmodel->meshlist = (void *)data;data += loadmodel->num_surfaces * sizeof(surfmesh_t *); + for (i = 0;i < loadmodel->num_surfaces;i++) + mesh = loadmodel->meshlist[i] = (void *)data;data += sizeof(surfmesh_t); //zymlump_t lump_shaders; // char shadername[numshaders][32]; // shaders used on this model //zymlump_t lump_render; // int renderlist[rendersize]; // sorted by shader with run lengths (int count), shaders are sequentially used, each run can be used with glDrawElements (each triangle is 3 int indices) @@ -1252,14 +1306,14 @@ void Mod_ZYMOTICMODEL_Load(model_t *mod, void *buffer) Host_Error("%s renderlist is wrong size (%i bytes, should be %i bytes)\n", loadmodel->name, pheader->lump_render.length, count); renderlist = (void *) (pheader->lump_render.start + pbase); renderlistend = (void *) ((qbyte *) renderlist + pheader->lump_render.length); - for (i = 0;i < loadmodel->alias.aliasnum_meshes;i++) + for (i = 0;i < loadmodel->num_surfaces;i++) { if (renderlist >= renderlistend) Host_Error("%s corrupt renderlist (wrong size)\n", loadmodel->name); count = BigLong(*renderlist);renderlist++; if (renderlist + count * 3 > renderlistend || (i == pheader->numshaders - 1 && renderlist + count * 3 != renderlistend)) Host_Error("%s corrupt renderlist (wrong size)\n", loadmodel->name); - mesh = loadmodel->alias.aliasdata_meshes + i; + mesh = loadmodel->meshlist[i]; mesh->num_skins = loadmodel->numskins; mesh->num_triangles = count; mesh->data_skins = Mem_Alloc(loadmodel->mempool, mesh->num_skins * sizeof(texture_t)); @@ -1283,20 +1337,20 @@ void Mod_ZYMOTICMODEL_Load(model_t *mod, void *buffer) for (j = 0;j < mesh->num_triangles * 3;j++) mesh->data_element3i[j] = remapvertices[mesh->data_element3i[j]]; Mod_BuildTriangleNeighbors(mesh->data_neighbor3i, mesh->data_element3i, mesh->num_triangles); - mesh->data_texcoord2f = Mem_Alloc(loadmodel->mempool, mesh->num_vertices * sizeof(float[2])); + mesh->data_texcoordtexture2f = Mem_Alloc(loadmodel->mempool, mesh->num_vertices * sizeof(float[2])); for (j = 0;j < pheader->numverts;j++) { if (remapvertices[j] >= 0) { - mesh->data_texcoord2f[remapvertices[j]*2+0] = outtexcoord2f[j*2+0]; - mesh->data_texcoord2f[remapvertices[j]*2+1] = outtexcoord2f[j*2+1]; + mesh->data_texcoordtexture2f[remapvertices[j]*2+0] = outtexcoord2f[j*2+0]; + mesh->data_texcoordtexture2f[remapvertices[j]*2+1] = outtexcoord2f[j*2+1]; } } mesh->num_vertexboneweights = 0; for (j = 0;j < mesh->num_vertices;j++) if (remapvertices[j] >= 0) mesh->num_vertexboneweights += vertbonecounts[remapvertices[j]]; - mesh->data_vertexboneweights = Mem_Alloc(loadmodel->mempool, mesh->num_vertexboneweights * sizeof(aliasvertexboneweight_t)); + mesh->data_vertexboneweights = Mem_Alloc(loadmodel->mempool, mesh->num_vertexboneweights * sizeof(surfmeshvertexboneweight_t)); mesh->num_vertexboneweights = 0; // note this vertexboneweight ordering requires that the remapvertices array is sequential numbers (separated by -1 values for omitted vertices) l = 0; @@ -1333,6 +1387,15 @@ void Mod_ZYMOTICMODEL_Load(model_t *mod, void *buffer) else for (j = 0;j < mesh->num_skins;j++) Mod_BuildAliasSkinFromSkinFrame(mesh->data_skins + j, NULL); + + surface = loadmodel->data_surfaces + i; + surface->groupmesh = mesh; + // FIXME: need to store data_skins in msurface_t, not surfmesh_t + surface->texture = mesh->data_skins; + surface->num_firsttriangle = 0; + surface->num_triangles = mesh->num_triangles; + surface->num_firstvertex = 0; + surface->num_vertices = mesh->num_vertices; } Mem_Free(vertbonecounts); diff --git a/model_alias.h b/model_alias.h index 15c6d8a2..c3367f8d 100644 --- a/model_alias.h +++ b/model_alias.h @@ -213,47 +213,6 @@ typedef struct md3modelheader_s } md3modelheader_t; -typedef struct aliasvertexboneweight_s -{ - unsigned int vertexindex; - unsigned int boneindex; - float origin[3]; - float weight; -} -aliasvertexboneweight_t; - -typedef struct aliasmesh_s -{ - // skins to choose from (indexed by entity skin) - int num_skins; - texture_t *data_skins; - - // triangles comprising the mesh - int num_triangles; - int *data_element3i; - int *data_neighbor3i; - - // skin texcoords do not change - int num_vertices; - float *data_texcoord2f; - - // morph blending, these are zero if model is skeletal - int num_morphframes; - float *data_morphvertex3f; - - // base frame (frame zero typically) - // since most models do not animate, caching the base frame helps - float *data_basevertex3f; - float *data_basesvector3f; - float *data_basetvector3f; - float *data_basenormal3f; - - // skeletal blending, these are zero if model is morph - int num_vertexboneweights; - aliasvertexboneweight_t *data_vertexboneweights; -} -aliasmesh_t; - typedef struct aliastag_s { char name[MD3NAME]; @@ -270,7 +229,7 @@ typedef struct aliasbone_s aliasbone_t; struct frameblend_s; -void Mod_Alias_GetMesh_Vertex3f(const struct model_s *model, const struct frameblend_s *frameblend, const struct aliasmesh_s *mesh, float *out3f); +void Mod_Alias_GetMesh_Vertex3f(const struct model_s *model, const struct frameblend_s *frameblend, const struct surfmesh_s *mesh, float *out3f); int Mod_Alias_GetTagMatrix(const struct model_s *model, int poseframe, int tagindex, matrix4x4_t *outmatrix); int Mod_Alias_GetTagIndexForName(const struct model_s *model, unsigned int skin, const char *tagname); diff --git a/model_brush.c b/model_brush.c index fd378a2c..0a7b87c8 100644 --- a/model_brush.c +++ b/model_brush.c @@ -260,7 +260,7 @@ static void Mod_Q1BSP_FindNonSolidLocation_r_Leaf(findnonsolidlocationinfo_t *in msurface_t *surface; for (surfacenum = 0, mark = leaf->firstleafsurface;surfacenum < leaf->numleafsurfaces;surfacenum++, mark++) { - surface = info->model->brush.data_surfaces + *mark; + surface = info->model->data_surfaces + *mark; if (surface->texture->supercontents & SUPERCONTENTS_SOLID) { for (k = 0;k < surface->num_triangles;k++) @@ -827,7 +827,7 @@ loc0: int i, ds, dt; msurface_t *surface; - surface = r_refdef.worldmodel->brush.data_surfaces + node->firstsurface; + surface = r_refdef.worldmodel->data_surfaces + node->firstsurface; for (i = 0;i < node->numsurfaces;i++, surface++) { if (!(surface->texture->basematerialflags & MATERIALFLAG_WALL) || !surface->lightmapinfo->samples) @@ -1025,32 +1025,32 @@ static void Mod_Q1BSP_LoadTextures(lump_t *l) qbyte *data, *mtdata; char name[256]; - loadmodel->brush.data_textures = NULL; + loadmodel->data_textures = NULL; // add two slots for notexture walls and notexture liquids if (l->filelen) { m = (dmiptexlump_t *)(mod_base + l->fileofs); m->nummiptex = LittleLong (m->nummiptex); - loadmodel->brush.num_textures = m->nummiptex + 2; + loadmodel->num_textures = m->nummiptex + 2; } else { m = NULL; - loadmodel->brush.num_textures = 2; + loadmodel->num_textures = 2; } - loadmodel->brush.data_textures = Mem_Alloc(loadmodel->mempool, loadmodel->brush.num_textures * sizeof(texture_t)); + loadmodel->data_textures = Mem_Alloc(loadmodel->mempool, loadmodel->num_textures * sizeof(texture_t)); // fill out all slots with notexture - for (i = 0, tx = loadmodel->brush.data_textures;i < loadmodel->brush.num_textures;i++, tx++) + for (i = 0, tx = loadmodel->data_textures;i < loadmodel->num_textures;i++, tx++) { strcpy(tx->name, "NO TEXTURE FOUND"); tx->width = 16; tx->height = 16; tx->skin.base = r_texture_notexture; tx->basematerialflags = 0; - if (i == loadmodel->brush.num_textures - 1) + if (i == loadmodel->num_textures - 1) { tx->basematerialflags |= MATERIALFLAG_WATER | MATERIALFLAG_LIGHTBOTHSIDES; tx->supercontents = SUPERCONTENTS_WATER; @@ -1104,7 +1104,7 @@ static void Mod_Q1BSP_LoadTextures(lump_t *l) if (name[j] >= 'A' && name[j] <= 'Z') name[j] += 'a' - 'A'; - tx = loadmodel->brush.data_textures + i; + tx = loadmodel->data_textures + i; strcpy(tx->name, name); tx->width = mtwidth; tx->height = mtheight; @@ -1217,7 +1217,7 @@ static void Mod_Q1BSP_LoadTextures(lump_t *l) // sequence the animations for (i = 0;i < m->nummiptex;i++) { - tx = loadmodel->brush.data_textures + i; + tx = loadmodel->data_textures + i; if (!tx || tx->name[0] != '+' || tx->name[1] == 0 || tx->name[2] == 0) continue; if (tx->anim_total[0] || tx->anim_total[1]) @@ -1229,7 +1229,7 @@ static void Mod_Q1BSP_LoadTextures(lump_t *l) for (j = i;j < m->nummiptex;j++) { - tx2 = loadmodel->brush.data_textures + j; + tx2 = loadmodel->data_textures + j; if (!tx2 || tx2->name[0] != '+' || strcmp(tx2->name+2, tx->name+2)) continue; @@ -1627,25 +1627,25 @@ static void Mod_Q1BSP_LoadTexinfo(lump_t *l) out->flags = LittleLong(in->flags); out->texture = NULL; - if (loadmodel->brush.data_textures) + if (loadmodel->data_textures) { - if ((unsigned int) miptex >= (unsigned int) loadmodel->brush.num_textures) - Con_Printf("error in model \"%s\": invalid miptex index %i(of %i)\n", loadmodel->name, miptex, loadmodel->brush.num_textures); + if ((unsigned int) miptex >= (unsigned int) loadmodel->num_textures) + Con_Printf("error in model \"%s\": invalid miptex index %i(of %i)\n", loadmodel->name, miptex, loadmodel->num_textures); else - out->texture = loadmodel->brush.data_textures + miptex; + out->texture = loadmodel->data_textures + miptex; } if (out->flags & TEX_SPECIAL) { // if texture chosen is NULL or the shader needs a lightmap, // force to notexture water shader if (out->texture == NULL || out->texture->basematerialflags & MATERIALFLAG_WALL) - out->texture = loadmodel->brush.data_textures + (loadmodel->brush.num_textures - 1); + out->texture = loadmodel->data_textures + (loadmodel->num_textures - 1); } else { // if texture chosen is NULL, force to notexture if (out->texture == NULL) - out->texture = loadmodel->brush.data_textures + (loadmodel->brush.num_textures - 2); + out->texture = loadmodel->data_textures + (loadmodel->num_textures - 2); } } } @@ -1813,10 +1813,10 @@ static void Mod_Q1BSP_LoadFaces(lump_t *l) if (l->filelen % sizeof(*in)) Host_Error("Mod_Q1BSP_LoadFaces: funny lump size in %s",loadmodel->name); count = l->filelen / sizeof(*in); - loadmodel->brush.data_surfaces = Mem_Alloc(loadmodel->mempool, count*sizeof(msurface_t)); - loadmodel->brush.data_surfaces_lightmapinfo = Mem_Alloc(loadmodel->mempool, count*sizeof(msurface_lightmapinfo_t)); + loadmodel->data_surfaces = Mem_Alloc(loadmodel->mempool, count*sizeof(msurface_t)); + loadmodel->data_surfaces_lightmapinfo = Mem_Alloc(loadmodel->mempool, count*sizeof(msurface_lightmapinfo_t)); - loadmodel->brush.num_surfaces = count; + loadmodel->num_surfaces = count; totalverts = 0; totaltris = 0; @@ -1835,9 +1835,9 @@ static void Mod_Q1BSP_LoadFaces(lump_t *l) totalverts = 0; totaltris = 0; - for (surfacenum = 0, in = (void *)(mod_base + l->fileofs), surface = loadmodel->brush.data_surfaces;surfacenum < count;surfacenum++, in++, surface++) + for (surfacenum = 0, in = (void *)(mod_base + l->fileofs), surface = loadmodel->data_surfaces;surfacenum < count;surfacenum++, in++, surface++) { - surface->lightmapinfo = loadmodel->brush.data_surfaces_lightmapinfo + surfacenum; + surface->lightmapinfo = loadmodel->data_surfaces_lightmapinfo + surfacenum; // FIXME: validate edges, texinfo, etc? firstedge = LittleLong(in->firstedge); @@ -2237,7 +2237,7 @@ static void Mod_Q1BSP_LoadLeaffaces(lump_t *l) for (i = 0;i < loadmodel->brush.num_leafsurfaces;i++) { j = (unsigned) LittleShort(in[i]); - if (j >= loadmodel->brush.num_surfaces) + if (j >= loadmodel->num_surfaces) Host_Error("Mod_Q1BSP_LoadLeaffaces: bad surface number"); loadmodel->brush.data_leafsurfaces[i] = j; } @@ -2776,7 +2776,7 @@ static void Mod_Q1BSP_BuildLightmapUpdateChains(mempool_t *mempool, model_t *mod memset(stylecounts, 0, sizeof(stylecounts)); for (i = 0;i < model->nummodelsurfaces;i++) { - surface = model->brush.data_surfaces + model->firstmodelsurface + i; + surface = model->data_surfaces + model->firstmodelsurface + i; for (j = 0;j < MAXLIGHTMAPS;j++) stylecounts[surface->lightmapinfo->styles[j]]++; } @@ -2808,7 +2808,7 @@ static void Mod_Q1BSP_BuildLightmapUpdateChains(mempool_t *mempool, model_t *mod } for (i = 0;i < model->nummodelsurfaces;i++) { - surface = model->brush.data_surfaces + model->firstmodelsurface + i; + surface = model->data_surfaces + model->firstmodelsurface + i; for (j = 0;j < MAXLIGHTMAPS;j++) if (surface->lightmapinfo->styles[j] != 255) *model->brushq1.light_styleupdatechains[remapstyles[surface->lightmapinfo->styles[j]]]++ = surface; @@ -3006,13 +3006,13 @@ void Mod_Q1BSP_Load(model_t *mod, void *buffer) // make a single combined shadow mesh to allow optimized shadow volume creation numshadowmeshtriangles = 0; - for (j = 0, surface = loadmodel->brush.data_surfaces;j < loadmodel->brush.num_surfaces;j++, surface++) + for (j = 0, surface = loadmodel->data_surfaces;j < loadmodel->num_surfaces;j++, surface++) { surface->num_firstshadowmeshtriangle = numshadowmeshtriangles; numshadowmeshtriangles += surface->num_triangles; } loadmodel->brush.shadowmesh = Mod_ShadowMesh_Begin(loadmodel->mempool, numshadowmeshtriangles * 3, numshadowmeshtriangles, NULL, NULL, NULL, false, false, true); - for (j = 0, surface = loadmodel->brush.data_surfaces;j < loadmodel->brush.num_surfaces;j++, surface++) + for (j = 0, surface = loadmodel->data_surfaces;j < loadmodel->num_surfaces;j++, surface++) Mod_ShadowMesh_AddMesh(loadmodel->mempool, loadmodel->brush.shadowmesh, NULL, NULL, NULL, surface->groupmesh->data_vertex3f, NULL, NULL, NULL, NULL, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle)); loadmodel->brush.shadowmesh = Mod_ShadowMesh_Finish(loadmodel->mempool, loadmodel->brush.shadowmesh, false, true); Mod_BuildTriangleNeighbors(loadmodel->brush.shadowmesh->neighbor3i, loadmodel->brush.shadowmesh->element3i, loadmodel->brush.shadowmesh->numtriangles); @@ -3113,7 +3113,7 @@ void Mod_Q1BSP_Load(model_t *mod, void *buffer) mod->normalmaxs[0] = mod->normalmaxs[1] = mod->normalmaxs[2] = -1000000000.0f; modelyawradius = 0; modelradius = 0; - for (j = 0, surface = &mod->brush.data_surfaces[mod->firstmodelsurface];j < mod->nummodelsurfaces;j++, surface++) + for (j = 0, surface = &mod->data_surfaces[mod->firstmodelsurface];j < mod->nummodelsurfaces;j++, surface++) { // we only need to have a drawsky function if it is used(usually only on world model) if (surface->texture->basematerialflags & MATERIALFLAG_SKY) @@ -3158,7 +3158,7 @@ void Mod_Q1BSP_Load(model_t *mod, void *buffer) //Mod_Q1BSP_ProcessLightList(); if (developer.integer) - Con_Printf("Some stats for q1bsp model \"%s\": %i faces, %i nodes, %i leafs, %i visleafs, %i visleafportals\n", loadmodel->name, loadmodel->brush.num_surfaces, loadmodel->brush.num_nodes, loadmodel->brush.num_leafs, mod->brushq1.submodels[i].visleafs, loadmodel->brush.num_portals); + Con_Printf("Some stats for q1bsp model \"%s\": %i faces, %i nodes, %i leafs, %i visleafs, %i visleafportals\n", loadmodel->name, loadmodel->num_surfaces, loadmodel->brush.num_nodes, loadmodel->brush.num_leafs, mod->brushq1.submodels[i].visleafs, loadmodel->brush.num_portals); } static void Mod_Q2BSP_LoadEntities(lump_t *l) @@ -3651,8 +3651,8 @@ static void Mod_Q3BSP_LoadTextures(lump_t *l) count = l->filelen / sizeof(*in); out = Mem_Alloc(loadmodel->mempool, count * sizeof(*out)); - loadmodel->brush.data_textures = out; - loadmodel->brush.num_textures = count; + loadmodel->data_textures = out; + loadmodel->num_textures = count; for (i = 0;i < count;i++, in++, out++) { @@ -3842,7 +3842,7 @@ static void Mod_Q3BSP_LoadTextures(lump_t *l) } // add shader to list (shadername and flags) // actually here we just poke into the texture settings - for (j = 0, out = loadmodel->brush.data_textures;j < loadmodel->brush.num_textures;j++, out++) + for (j = 0, out = loadmodel->data_textures;j < loadmodel->num_textures;j++, out++) { if (!strcasecmp(out->name, shadername)) { @@ -3890,7 +3890,7 @@ parseerror: } c = 0; - for (j = 0, out = loadmodel->brush.data_textures;j < loadmodel->brush.num_textures;j++, out++) + for (j = 0, out = loadmodel->data_textures;j < loadmodel->num_textures;j++, out++) { if (out->surfaceparms == -1) { @@ -3970,9 +3970,9 @@ static void Mod_Q3BSP_LoadBrushSides(lump_t *l) Host_Error("Mod_Q3BSP_LoadBrushSides: invalid planeindex %i (%i planes)\n", n, loadmodel->brush.num_planes); out->plane = loadmodel->brush.data_planes + n; n = LittleLong(in->textureindex); - if (n < 0 || n >= loadmodel->brush.num_textures) - Host_Error("Mod_Q3BSP_LoadBrushSides: invalid textureindex %i (%i textures)\n", n, loadmodel->brush.num_textures); - out->texture = loadmodel->brush.data_textures + n; + if (n < 0 || n >= loadmodel->num_textures) + Host_Error("Mod_Q3BSP_LoadBrushSides: invalid textureindex %i (%i textures)\n", n, loadmodel->num_textures); + out->texture = loadmodel->data_textures + n; } } @@ -4004,9 +4004,9 @@ static void Mod_Q3BSP_LoadBrushes(lump_t *l) out->firstbrushside = loadmodel->brush.data_brushsides + n; out->numbrushsides = c; n = LittleLong(in->textureindex); - if (n < 0 || n >= loadmodel->brush.num_textures) - Host_Error("Mod_Q3BSP_LoadBrushes: invalid textureindex %i (%i textures)\n", n, loadmodel->brush.num_textures); - out->texture = loadmodel->brush.data_textures + n; + if (n < 0 || n >= loadmodel->num_textures) + Host_Error("Mod_Q3BSP_LoadBrushes: invalid textureindex %i (%i textures)\n", n, loadmodel->num_textures); + out->texture = loadmodel->data_textures + n; // make a list of mplane_t structs to construct a colbrush from if (maxplanes < out->numbrushsides) @@ -4155,8 +4155,8 @@ static void Mod_Q3BSP_LoadFaces(lump_t *l) count = l->filelen / sizeof(*in); out = Mem_Alloc(loadmodel->mempool, count * sizeof(*out)); - loadmodel->brush.data_surfaces = out; - loadmodel->brush.num_surfaces = count; + loadmodel->data_surfaces = out; + loadmodel->num_surfaces = count; i = 0; for (meshnum = 0;i < count;meshnum++) @@ -4180,12 +4180,12 @@ static void Mod_Q3BSP_LoadFaces(lump_t *l) } n = LittleLong(in->textureindex); - if (n < 0 || n >= loadmodel->brush.num_textures) + if (n < 0 || n >= loadmodel->num_textures) { - Con_DPrintf("Mod_Q3BSP_LoadFaces: face #%i: invalid textureindex %i (%i textures)\n", i, n, loadmodel->brush.num_textures); + Con_DPrintf("Mod_Q3BSP_LoadFaces: face #%i: invalid textureindex %i (%i textures)\n", i, n, loadmodel->num_textures); continue; } - out->texture = loadmodel->brush.data_textures + n; + out->texture = loadmodel->data_textures + n; n = LittleLong(in->effectindex); if (n < -1 || n >= loadmodel->brushq3.num_effects) { @@ -4499,8 +4499,8 @@ static void Mod_Q3BSP_LoadModels(lump_t *l) } n = LittleLong(in->firstface); c = LittleLong(in->numfaces); - if (n < 0 || n + c > loadmodel->brush.num_surfaces) - Host_Error("Mod_Q3BSP_LoadModels: invalid face range %i : %i (%i faces)\n", n, n + c, loadmodel->brush.num_surfaces); + if (n < 0 || n + c > loadmodel->num_surfaces) + Host_Error("Mod_Q3BSP_LoadModels: invalid face range %i : %i (%i faces)\n", n, n + c, loadmodel->num_surfaces); out->firstface = n; out->numfaces = c; n = LittleLong(in->firstbrush); @@ -4554,8 +4554,8 @@ static void Mod_Q3BSP_LoadLeafFaces(lump_t *l) for (i = 0;i < count;i++, in++, out++) { n = LittleLong(*in); - if (n < 0 || n >= loadmodel->brush.num_surfaces) - Host_Error("Mod_Q3BSP_LoadLeafFaces: invalid face index %i (%i faces)\n", n, loadmodel->brush.num_surfaces); + if (n < 0 || n >= loadmodel->num_surfaces) + Host_Error("Mod_Q3BSP_LoadLeafFaces: invalid face index %i (%i faces)\n", n, loadmodel->num_surfaces); *out = n; } } @@ -4899,7 +4899,7 @@ static void Mod_Q3BSP_TraceLine_RecursiveBSPNode(trace_t *trace, model_t *model, // line trace the curves for (i = 0;i < leaf->numleafsurfaces;i++) { - surface = model->brush.data_surfaces + leaf->firstleafsurface[i]; + surface = model->data_surfaces + leaf->firstleafsurface[i]; if (surface->num_collisiontriangles && surface->collisionmarkframe != markframe && BoxesOverlap(nodesegmentmins, nodesegmentmaxs, surface->mins, surface->maxs)) { surface->collisionmarkframe = markframe; @@ -5279,7 +5279,7 @@ static void Mod_Q3BSP_TraceBrush_RecursiveBSPNode(trace_t *trace, model_t *model { for (i = 0;i < leaf->numleafsurfaces;i++) { - surface = model->brush.data_surfaces + leaf->firstleafsurface[i]; + surface = model->data_surfaces + leaf->firstleafsurface[i]; if (surface->num_collisiontriangles && surface->collisionmarkframe != markframe && BoxesOverlap(nodesegmentmins, nodesegmentmaxs, surface->mins, surface->maxs)) { surface->collisionmarkframe = markframe; @@ -5333,7 +5333,7 @@ static void Mod_Q3BSP_TraceBox(model_t *model, int frame, trace_t *trace, const if (brush->colbrushf) Collision_TraceLineBrushFloat(trace, boxstartmins, boxendmins, brush->colbrushf, brush->colbrushf); if (mod_q3bsp_curves_collisions.integer) - for (i = 0, surface = model->brush.data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++) + for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++) if (surface->num_collisiontriangles) Collision_TraceLineTriangleMeshFloat(trace, boxstartmins, boxendmins, surface->num_collisiontriangles, surface->data_collisionelement3i, surface->data_collisionvertex3f, surface->texture->supercontents, segmentmins, segmentmaxs); } @@ -5352,7 +5352,7 @@ static void Mod_Q3BSP_TraceBox(model_t *model, int frame, trace_t *trace, const if (brush->colbrushf) Collision_TraceBrushBrushFloat(trace, thisbrush_start, thisbrush_end, brush->colbrushf, brush->colbrushf); if (mod_q3bsp_curves_collisions.integer) - for (i = 0, surface = model->brush.data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++) + for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++) if (surface->num_collisiontriangles) Collision_TraceBrushTriangleMeshFloat(trace, thisbrush_start, thisbrush_end, surface->num_collisiontriangles, surface->data_collisionelement3i, surface->data_collisionvertex3f, surface->texture->supercontents, segmentmins, segmentmaxs); } @@ -5497,13 +5497,13 @@ void Mod_Q3BSP_Load(model_t *mod, void *buffer) // make a single combined shadow mesh to allow optimized shadow volume creation numshadowmeshtriangles = 0; - for (j = 0, surface = loadmodel->brush.data_surfaces;j < loadmodel->brush.num_surfaces;j++, surface++) + for (j = 0, surface = loadmodel->data_surfaces;j < loadmodel->num_surfaces;j++, surface++) { surface->num_firstshadowmeshtriangle = numshadowmeshtriangles; numshadowmeshtriangles += surface->num_triangles; } loadmodel->brush.shadowmesh = Mod_ShadowMesh_Begin(loadmodel->mempool, numshadowmeshtriangles * 3, numshadowmeshtriangles, NULL, NULL, NULL, false, false, true); - for (j = 0, surface = loadmodel->brush.data_surfaces;j < loadmodel->brush.num_surfaces;j++, surface++) + for (j = 0, surface = loadmodel->data_surfaces;j < loadmodel->num_surfaces;j++, surface++) Mod_ShadowMesh_AddMesh(loadmodel->mempool, loadmodel->brush.shadowmesh, NULL, NULL, NULL, surface->groupmesh->data_vertex3f, NULL, NULL, NULL, NULL, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle)); loadmodel->brush.shadowmesh = Mod_ShadowMesh_Finish(loadmodel->mempool, loadmodel->brush.shadowmesh, false, true); Mod_BuildTriangleNeighbors(loadmodel->brush.shadowmesh->neighbor3i, loadmodel->brush.shadowmesh->element3i, loadmodel->brush.shadowmesh->numtriangles); @@ -5574,7 +5574,7 @@ void Mod_Q3BSP_Load(model_t *mod, void *buffer) mod->radius2 = modelradius * modelradius; for (j = 0;j < mod->nummodelsurfaces;j++) - if (mod->brush.data_surfaces[j + mod->firstmodelsurface].texture->surfaceflags & Q3SURFACEFLAG_SKY) + if (mod->data_surfaces[j + mod->firstmodelsurface].texture->surfaceflags & Q3SURFACEFLAG_SKY) break; if (j < mod->nummodelsurfaces) mod->DrawSky = R_Q1BSP_DrawSky; diff --git a/model_brush.h b/model_brush.h index 0f2aadee..1bf8be8d 100644 --- a/model_brush.h +++ b/model_brush.h @@ -87,119 +87,15 @@ mplane_t; // probably used only on q1bsp water #define MATERIALFLAG_LIGHTBOTHSIDES 1024 -struct entity_render_s; -struct texture_s; -struct msurface_s; - -typedef struct texture_s -{ - // q1bsp - // name - //char name[16]; - // size - unsigned int width, height; - // SURF_ flags - //unsigned int flags; - - // base material flags - int basematerialflags; - // current material flags (updated each bmodel render) - int currentmaterialflags; - - // loaded the same as model skins - skinframe_t skin; - - // total frames in sequence and alternate sequence - int anim_total[2]; - // direct pointers to each of the frames in the sequences - // (indexed as [alternate][frame]) - struct texture_s *anim_frames[2][10]; - // set if animated or there is an alternate frame set - // (this is an optimization in the renderer) - int animated; - // the current texture frame in animation - struct texture_s *currentframe; - // current alpha of the texture - float currentalpha; - - // q3bsp - char name[Q3PATHLENGTH]; - char firstpasstexturename[Q3PATHLENGTH]; // used only during loading - int surfaceflags; - int supercontents; - int surfaceparms; - int textureflags; - - //skinframe_t skin; -} -texture_t; - typedef struct { unsigned short v[2]; } medge_t; -typedef struct -{ - float vecs[2][4]; - texture_t *texture; - int flags; -} -mtexinfo_t; - -typedef struct msurface_lightmapinfo_s -{ - // texture mapping properties used by this surface - mtexinfo_t *texinfo; // q1bsp - // index into d_lightstylevalue array, 255 means not used (black) - qbyte styles[MAXLIGHTMAPS]; // q1bsp - // RGB lighting data [numstyles][height][width][3] - qbyte *samples; // q1bsp - // stain to apply on lightmap (soot/dirt/blood/whatever) - qbyte *stainsamples; // q1bsp - // the stride when building lightmaps to comply with fragment update - int lightmaptexturestride; // q1bsp - int texturemins[2]; // q1bsp - int extents[2]; // q1bsp -} -msurface_lightmapinfo_t; - -struct q3deffect_s; -typedef struct msurface_s -{ - // bounding box for onscreen checks - vec3_t mins; - vec3_t maxs; - // the texture to use on the surface - texture_t *texture; - // the lightmap texture fragment to use on the rendering mesh - rtexture_t *lightmaptexture; - - // this surface is part of this mesh - surfmesh_t *groupmesh; - int num_triangles; // number of triangles in the mesh - int num_firsttriangle; // first triangle in the mesh (index into groupmesh) - int num_vertices; // number of vertices in the mesh - int num_firstvertex; // first vertex in the mesh (index into groupmesh) - - // shadow volume building information - int num_firstshadowmeshtriangle; // index into model->brush.shadowmesh - - // lightmaptexture rebuild information not used in q3bsp - int cached_dlight; // q1bsp // forces rebuild of lightmaptexture - msurface_lightmapinfo_t *lightmapinfo; // q1bsp - - // mesh information for collisions (only used by q3bsp curves) - int num_collisiontriangles; // q3bsp - int *data_collisionelement3i; // q3bsp - int num_collisionvertices; // q3bsp - float *data_collisionvertex3f; // q3bsp - struct q3deffect_s *effect; // q3bsp - // FIXME: collisionmarkframe should be kept in a separate array - int collisionmarkframe; // q3bsp // don't collide twice in one trace -} -msurface_t; +struct entity_render_s; +struct texture_s; +struct msurface_s; typedef struct mnode_s { diff --git a/model_shared.c b/model_shared.c index bcc813aa..da90f785 100644 --- a/model_shared.c +++ b/model_shared.c @@ -63,7 +63,7 @@ static void mod_newmap(void) { if (mod_known[i].name[0]) { - for (surfacenum = 0, surface = mod_known[i].brush.data_surfaces;surfacenum < mod_known[i].brush.num_surfaces;surfacenum++, surface++) + for (surfacenum = 0, surface = mod_known[i].data_surfaces;surfacenum < mod_known[i].num_surfaces;surfacenum++, surface++) { if (surface->lightmapinfo && surface->lightmapinfo->stainsamples) { diff --git a/model_shared.h b/model_shared.h index 96cf1292..614ac4c1 100644 --- a/model_shared.h +++ b/model_shared.h @@ -73,6 +73,15 @@ typedef struct overridetagnameset_s } overridetagnameset_t; +typedef struct surfmeshvertexboneweight_s +{ + unsigned int vertexindex; + unsigned int boneindex; + float origin[3]; + float weight; +} +surfmeshvertexboneweight_t; + // used for mesh lists in q1bsp/q3bsp map models // (the surfaces reference portions of these meshes) typedef struct surfmesh_s @@ -82,14 +91,23 @@ typedef struct surfmesh_s int *data_neighbor3i; // int[tris*3] neighboring triangle on each edge (-1 if none) int num_vertices; // number of vertices in the mesh float *data_vertex3f; // float[verts*3] vertex locations - float *data_texcoordtexture2f; // float[verts*2] texcoords for surface texture - float *data_texcoordlightmap2f; // float[verts*2] texcoords for lightmap texture - float *data_lightmapcolor4f; float *data_svector3f; // float[verts*3] direction of 'S' (right) texture axis for each vertex float *data_tvector3f; // float[verts*3] direction of 'T' (down) texture axis for each vertex float *data_normal3f; // float[verts*3] direction of 'R' (out) texture axis for each vertex + float *data_texcoordtexture2f; // float[verts*2] texcoords for surface texture + float *data_texcoordlightmap2f; // float[verts*2] texcoords for lightmap texture float *data_texcoorddetail2f; // float[verts*2] texcoords for detail texture + float *data_lightmapcolor4f; int *data_lightmapoffsets; // index into surface's lightmap samples for vertex lighting + // if a model these will be a skin list to choose from + int num_skins; + struct texture_s *data_skins; + // morph blending, these are zero if model is skeletal or static + int num_morphframes; + float *data_morphvertex3f; + // skeletal blending, these are zero if model is morph or static + int num_vertexboneweights; + surfmeshvertexboneweight_t *data_vertexboneweights; } surfmesh_t; @@ -128,33 +146,115 @@ typedef struct shadowmesh_s } shadowmesh_t; +typedef struct texture_s +{ + // q1bsp + // name + //char name[16]; + // size + unsigned int width, height; + // SURF_ flags + //unsigned int flags; + + // base material flags + int basematerialflags; + // current material flags (updated each bmodel render) + int currentmaterialflags; + + // loaded the same as model skins + skinframe_t skin; + + // total frames in sequence and alternate sequence + int anim_total[2]; + // direct pointers to each of the frames in the sequences + // (indexed as [alternate][frame]) + struct texture_s *anim_frames[2][10]; + // set if animated or there is an alternate frame set + // (this is an optimization in the renderer) + int animated; + // the current texture frame in animation + struct texture_s *currentframe; + // current alpha of the texture + float currentalpha; + + // q3bsp + char name[64]; + char firstpasstexturename[64]; // used only during loading + int surfaceflags; + int supercontents; + int surfaceparms; + int textureflags; + + //skinframe_t skin; +} +texture_t; -#include "matrixlib.h" - -#include "model_brush.h" -#include "model_sprite.h" -#include "model_alias.h" +typedef struct +{ + float vecs[2][4]; + texture_t *texture; + int flags; +} +mtexinfo_t; -typedef struct model_alias_s +typedef struct msurface_lightmapinfo_s { - // mdl/md2/md3/zym model formats are treated the same after loading + // texture mapping properties used by this surface + mtexinfo_t *texinfo; // q1bsp + // index into d_lightstylevalue array, 255 means not used (black) + qbyte styles[MAXLIGHTMAPS]; // q1bsp + // RGB lighting data [numstyles][height][width][3] + qbyte *samples; // q1bsp + // stain to apply on lightmap (soot/dirt/blood/whatever) + qbyte *stainsamples; // q1bsp + // the stride when building lightmaps to comply with fragment update + int lightmaptexturestride; // q1bsp + int texturemins[2]; // q1bsp + int extents[2]; // q1bsp +} +msurface_lightmapinfo_t; - // the shader meshes comprising this model - int aliasnum_meshes; - aliasmesh_t *aliasdata_meshes; +struct q3deffect_s; +typedef struct msurface_s +{ + // bounding box for onscreen checks + vec3_t mins; + vec3_t maxs; + // the texture to use on the surface + texture_t *texture; + // the lightmap texture fragment to use on the rendering mesh + rtexture_t *lightmaptexture; + + // this surface is part of this mesh + surfmesh_t *groupmesh; + int num_triangles; // number of triangles in the mesh + int num_firsttriangle; // first triangle in the mesh (index into groupmesh) + int num_vertices; // number of vertices in the mesh + int num_firstvertex; // first vertex in the mesh (index into groupmesh) + + // shadow volume building information + int num_firstshadowmeshtriangle; // index into model->brush.shadowmesh + + // lightmaptexture rebuild information not used in q3bsp + int cached_dlight; // q1bsp // forces rebuild of lightmaptexture + msurface_lightmapinfo_t *lightmapinfo; // q1bsp + + // mesh information for collisions (only used by q3bsp curves) + int num_collisiontriangles; // q3bsp + int *data_collisionelement3i; // q3bsp + int num_collisionvertices; // q3bsp + float *data_collisionvertex3f; // q3bsp + struct q3deffect_s *effect; // q3bsp + // FIXME: collisionmarkframe should be kept in a separate array + int collisionmarkframe; // q3bsp // don't collide twice in one trace +} +msurface_t; - // for md3 models - int aliasnum_tags; - int aliasnum_tagframes; - aliastag_t *aliasdata_tags; +#include "matrixlib.h" - // for skeletal models - int aliasnum_bones; - aliasbone_t *aliasdata_bones; - int aliasnum_poses; - float *aliasdata_poses; -} -model_alias_t; +#include "model_brush.h" +#include "model_sprite.h" +#include "model_alias.h" typedef struct model_sprite_s { @@ -206,13 +306,6 @@ typedef struct model_brush_s int num_portalpoints; mvertex_t *data_portalpoints; - int num_textures; - texture_t *data_textures; - - int num_surfaces; - msurface_t *data_surfaces; - msurface_lightmapinfo_t *data_surfaces_lightmapinfo; - int num_brushes; q3mbrush_t *data_brushes; @@ -392,6 +485,23 @@ typedef struct model_s int nummodelbrushes; // list of surface numbers in this (sub)model int *surfacelist; + // for md3 models + int num_tags; + int num_tagframes; + aliastag_t *data_tags; + // for skeletal models + int num_bones; + aliasbone_t *data_bones; + int num_poses; + float *data_poses; + // textures of this model + int num_textures; + texture_t *data_textures; + // surfaces of this model + int num_surfaces; + msurface_t *data_surfaces; + // optional lightmapinfo data for surface lightmap updates + msurface_lightmapinfo_t *data_surfaces_lightmapinfo; // surface meshes are merged to a smaller set of meshes to allow reduced // vertex array switching, the meshes are limited to 65536 vertices each // to play nice with Geforce1 hardware @@ -409,8 +519,7 @@ typedef struct model_s void(*DrawLight)(struct entity_render_s *ent, float *lightcolor, int numsurfaces, const int *surfacelist); // trace a box against this model void (*TraceBox)(struct model_s *model, int frame, struct trace_s *trace, const vec3_t boxstartmins, const vec3_t boxstartmaxs, const vec3_t boxendmins, const vec3_t boxendmaxs, int hitsupercontentsmask); - // fields belonging to each type of model - model_alias_t alias; + // fields belonging to some types of model model_sprite_t sprite; model_brush_t brush; model_brushq1_t brushq1; diff --git a/portals.c b/portals.c index 7d79b32c..fda14920 100644 --- a/portals.c +++ b/portals.c @@ -319,7 +319,7 @@ void Portal_RecursiveFlow (portalrecursioninfo_t *info, mleaf_t *leaf, int first int surfaceindex = leaf->firstleafsurface[i]; if (!CHECKPVSBIT(info->surfacepvs, surfaceindex)) { - msurface_t *surface = info->model->brush.data_surfaces + surfaceindex; + msurface_t *surface = info->model->data_surfaces + surfaceindex; if (BoxesOverlap(surface->mins, surface->maxs, info->boxmins, info->boxmaxs)) { if (info->exact) diff --git a/pr_cmds.c b/pr_cmds.c index b1be56e3..19643ea0 100644 --- a/pr_cmds.c +++ b/pr_cmds.c @@ -2658,7 +2658,7 @@ static msurface_t *getsurface(edict_t *ed, int surfacenum) model = sv.models[modelindex]; if (surfacenum < 0 || surfacenum >= model->nummodelsurfaces) return NULL; - return model->brush.data_surfaces + surfacenum + model->firstmodelsurface; + return model->data_surfaces + surfacenum + model->firstmodelsurface; } @@ -2740,7 +2740,7 @@ void PF_getsurfacenearpoint(void) if (modelindex < 1 || modelindex >= MAX_MODELS) return; model = sv.models[modelindex]; - if (!model->brush.num_surfaces) + if (!model->num_surfaces) return; // FIXME: implement rotation/scaling @@ -2749,7 +2749,7 @@ void PF_getsurfacenearpoint(void) bestdist = 1000000000; for (surfacenum = 0;surfacenum < model->nummodelsurfaces;surfacenum++) { - surface = model->brush.data_surfaces + surfacenum + model->firstmodelsurface; + surface = model->data_surfaces + surfacenum + model->firstmodelsurface; // first see if the nearest point on the surface's box is closer than the previous match clipped[0] = bound(surface->mins[0], p[0], surface->maxs[0]) - p[0]; clipped[1] = bound(surface->mins[1], p[1], surface->maxs[1]) - p[1]; diff --git a/prvm_cmds.c b/prvm_cmds.c index a326cd46..7c06b387 100644 --- a/prvm_cmds.c +++ b/prvm_cmds.c @@ -2160,9 +2160,9 @@ void PF_setattachment (void) if (!strcmp(tagname, model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].data_overridetagnames[i].name)) v->_float = i + 1; // FIXME: use a model function to get tag info (need to handle skeletal) - if (v->_float == 0 && model->alias.aliasnum_tags) - for (i = 0;i < model->alias.aliasnum_tags;i++) - if (!strcmp(tagname, model->alias.aliasdata_tags[i].name)) + if (v->_float == 0 && model->num_tags) + for (i = 0;i < model->num_tags;i++) + if (!strcmp(tagname, model->data_tags[i].name)) v->_float = i + 1; if (v->_float == 0) Con_DPrintf("setattachment(edict %i, edict %i, string \"%s\"): tried to find tag named \"%s\" on entity %i (model \"%s\") but could not find it\n", NUM_FOR_EDICT(e), NUM_FOR_EDICT(tagentity), tagname, tagname, NUM_FOR_EDICT(tagentity), model->name); diff --git a/r_shadow.c b/r_shadow.c index f39a0965..45de930d 100644 --- a/r_shadow.c +++ b/r_shadow.c @@ -2632,7 +2632,7 @@ void R_RTLight_Compile(rtlight_t *rtlight) { // this variable directs the DrawShadowVolume and DrawLight code to capture into the mesh chain instead of rendering r_shadow_compilingrtlight = rtlight; - R_Shadow_EnlargeLeafSurfaceBuffer(model->brush.num_leafs, model->brush.num_surfaces); + R_Shadow_EnlargeLeafSurfaceBuffer(model->brush.num_leafs, model->num_surfaces); model->GetLightInfo(ent, rtlight->shadoworigin, rtlight->radius, rtlight->cullmins, rtlight->cullmaxs, r_shadow_buffer_leaflist, r_shadow_buffer_leafpvs, &numleafs, r_shadow_buffer_surfacelist, r_shadow_buffer_surfacepvs, &numsurfaces); numleafpvsbytes = (model->brush.num_leafs + 7) >> 3; data = Mem_Alloc(r_shadow_mempool, sizeof(int) * numleafs + numleafpvsbytes + sizeof(int) * numsurfaces); @@ -2872,7 +2872,7 @@ void R_DrawRTLight(rtlight_t *rtlight, qboolean visible) { // dynamic light, world available and can receive realtime lighting // calculate lit surfaces and leafs - R_Shadow_EnlargeLeafSurfaceBuffer(r_refdef.worldmodel->brush.num_leafs, r_refdef.worldmodel->brush.num_surfaces); + R_Shadow_EnlargeLeafSurfaceBuffer(r_refdef.worldmodel->brush.num_leafs, r_refdef.worldmodel->num_surfaces); r_refdef.worldmodel->GetLightInfo(r_refdef.worldentity, rtlight->shadoworigin, rtlight->radius, rtlight->cullmins, rtlight->cullmaxs, r_shadow_buffer_leaflist, r_shadow_buffer_leafpvs, &numleafs, r_shadow_buffer_surfacelist, r_shadow_buffer_surfacepvs, &numsurfaces); leaflist = r_shadow_buffer_leaflist; leafpvs = r_shadow_buffer_leafpvs; diff --git a/render.h b/render.h index 98ea4ebf..0973f84d 100644 --- a/render.h +++ b/render.h @@ -27,7 +27,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. qbyte r_pvsbits[(32768+7)>>3]; // TODO: dynamic resize according to r_refdef.worldmodel->brush.num_leafs qbyte r_worldleafvisible[32768]; -// TODO: dynamic resize according to r_refdef.worldmodel->brush.num_surfaces +// TODO: dynamic resize according to r_refdef.worldmodel->num_surfaces qbyte r_worldsurfacevisible[262144]; extern matrix4x4_t r_identitymatrix; @@ -223,5 +223,13 @@ void R_Draw2DCrosshair(void); void R_CalcBeam_Vertex3f(float *vert, const vec3_t org1, const vec3_t org2, float width); void R_DrawSprite(int blendfunc1, int blendfunc2, rtexture_t *texture, int depthdisable, const vec3_t origin, const vec3_t left, const vec3_t up, float scalex1, float scalex2, float scaley1, float scaley2, float cr, float cg, float cb, float ca); +struct entity_render_s; +struct texture_s; +struct msurface_s; +void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t); +void R_UpdateAllTextureInfo(entity_render_t *ent); +void R_QueueTextureSurfaceList(entity_render_t *ent, struct texture_s *texture, int texturenumsurfaces, const struct msurface_s **texturesurfacelist, const vec3_t modelorg); +void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces); + #endif -- 2.39.2