diff --git a/include/QF/GL/qf_sky.h b/include/QF/GL/qf_sky.h index bfb99744f..181778993 100644 --- a/include/QF/GL/qf_sky.h +++ b/include/QF/GL/qf_sky.h @@ -38,6 +38,6 @@ extern qboolean skyloaded; extern vec5_t skyvec[6][4]; void R_DrawSky (void); -void R_DrawSkyChain (const msurface_t *s); +void R_DrawSkyChain (const instsurf_t *s); #endif // __QF_GL_sky_h diff --git a/include/QF/model.h b/include/QF/model.h index e5fa57602..3a0f11692 100644 --- a/include/QF/model.h +++ b/include/QF/model.h @@ -68,13 +68,33 @@ typedef struct { vec3_t position; } mvertex_t; +/** Instanced surface data. + + There will be one of these for each surface in the world model. This + covers the sub-models in the world model. These instanced surfaces will + be allocated in one block at map load time and then never freed until + the next map load. + + However, for instanced brush models (ammo boxes, health boxes, etc), an + instanced surface will be allocated for each surface for each model + once per frame. These instanced surfaces will be mass-freed each frame. +*/ +typedef struct instsurf_s { + struct instsurf_s *next; ///< next in free/alloc list + struct instsurf_s *tex_chain; ///< next in texture chain + struct instsurf_s *lm_chain; ///< next in lightmap chain + struct msurface_s *surface; ///< surface to render + vec_t *transform; + float *color; +} instsurf_t; + typedef struct texture_s { char name[16]; unsigned int width, height; int gl_texturenum; int gl_fb_texturenum; - struct msurface_s *texturechain; // for gl_texsort drawing - struct msurface_s **texturechain_tail; + instsurf_t *tex_chain; // for gl_texsort drawing + instsurf_t **tex_chain_tail; int anim_total; // total tenths in sequence ( 0 = no) int anim_min, anim_max; // time for this frame min <=time< max struct texture_s *anim_next; // in the animation sequence @@ -136,8 +156,7 @@ typedef struct msurface_s { int light_s, light_t; // gl lightmap coordinates glpoly_t *polys; // multiple if warped - struct msurface_s *texturechain; -// struct msurface_s *lightmapchain; // Quake 2 ??? + instsurf_t *instsurf; ///< null if not part of world model/sub-model mtexinfo_t *texinfo; diff --git a/include/r_local.h b/include/r_local.h index 0999c6bc8..26be09c45 100644 --- a/include/r_local.h +++ b/include/r_local.h @@ -178,6 +178,9 @@ void D_DrawSurfaces (void); void R_InsertNewEdges (edge_t *edgestoadd, edge_t *edgelist); void R_StepActiveU (edge_t *pedge); void R_RemoveEdges (edge_t *pedge); +void R_AddTexture (texture_t *tex); +void R_ClearTextures (void); +void R_InitSurfaceChains (model_t *model); extern void R_Surf8Start (void); extern void R_Surf8End (void); @@ -191,8 +194,6 @@ extern int r_polycount; extern int r_wholepolycount; extern model_t *cl_worldmodel; -extern texture_t **r_texture_chains; -extern int r_num_texture_chains; extern int *pfrustum_indexes[4]; diff --git a/libs/video/renderer/gl/gl_rmain.c b/libs/video/renderer/gl/gl_rmain.c index c8af45387..cf581fc0b 100644 --- a/libs/video/renderer/gl/gl_rmain.c +++ b/libs/video/renderer/gl/gl_rmain.c @@ -545,7 +545,7 @@ static void R_Mirror (void) { float d; - msurface_t *s; +// msurface_t *s; // if (!mirror) // FIXME: Broken return; @@ -590,6 +590,7 @@ R_Mirror (void) color_white[3] = r_mirroralpha->value * 255; qfglColor4ubv (color_white); +#if 0//FIXME s = r_worldentity.model->textures[mirrortexturenum]->texturechain; for (; s; s = s->texturechain) { texture_t *tex; @@ -611,6 +612,7 @@ R_Mirror (void) // R_RenderBrushPoly (s, tex); // FIXME: Need to move R_Mirror to gl_rsurf.c, and uncommment this line! } r_worldentity.model->textures[mirrortexturenum]->texturechain = NULL; +#endif qfglColor3ubv (color_white); } diff --git a/libs/video/renderer/gl/gl_rmisc.c b/libs/video/renderer/gl/gl_rmisc.c index 7de2da56c..5659fd09f 100644 --- a/libs/video/renderer/gl/gl_rmisc.c +++ b/libs/video/renderer/gl/gl_rmisc.c @@ -66,32 +66,6 @@ static __attribute__ ((used)) const char rcsid[] = int r_init = 0; -texture_t **r_texture_chains; -int r_num_texture_chains; -static int max_texture_chains; - -static void -R_AddTexture (texture_t *tex) -{ - int i; - if (r_num_texture_chains == max_texture_chains) { - max_texture_chains += 64; - r_texture_chains = realloc (r_texture_chains, - max_texture_chains * sizeof (texture_t *)); - for (i = r_num_texture_chains; i < max_texture_chains; i++) - r_texture_chains[i] = 0; - } - r_texture_chains[r_num_texture_chains++] = tex; - tex->texturechain = NULL; - tex->texturechain_tail = &tex->texturechain; -} - -static void -R_ClearTextures (void) -{ - r_num_texture_chains = 0; -} - /* R_Envmap_f @@ -196,8 +170,6 @@ register_textures (model_t *model) tex = model->textures[i]; if (!tex) continue; - if (tex->texturechain_tail) - continue; R_AddTexture (tex); } } @@ -240,16 +212,18 @@ R_NewMap (model_t *worldmodel, struct model_s **models, int num_models) if (!strncmp (tex->name, "window02_1", 10)) mirrortexturenum = i; } + + R_InitSurfaceChains (r_worldentity.model); + R_AddTexture (r_notexture_mip); register_textures (r_worldentity.model); for (i = 0; i < num_models; i++) { if (!models[i]) continue; + if (*models[i]->name == '*') + continue; if (models[i] != r_worldentity.model && models[i]->type == mod_brush) register_textures (models[i]); } - tex = r_notexture_mip; - tex->texturechain = NULL; - tex->texturechain_tail = &tex->texturechain; } void diff --git a/libs/video/renderer/gl/gl_rsurf.c b/libs/video/renderer/gl/gl_rsurf.c index 9c49b1a91..2c39f5a20 100644 --- a/libs/video/renderer/gl/gl_rsurf.c +++ b/libs/video/renderer/gl/gl_rsurf.c @@ -62,22 +62,26 @@ int skytexturenum; glpoly_t *fullbright_polys[MAX_GLTEXTURES]; -msurface_t *waterchain = NULL; -msurface_t **waterchain_tail = &waterchain; -msurface_t *sky_chain; -msurface_t **sky_chain_tail; +instsurf_t *waterchain = NULL; +instsurf_t **waterchain_tail = &waterchain; +instsurf_t *sky_chain; +instsurf_t **sky_chain_tail; #define CHAIN_SURF_F2B(surf,chain) \ do { \ - *(chain##_tail) = (surf); \ - (chain##_tail) = &(surf)->texturechain; \ + instsurf_t *inst = (surf)->instsurf; \ + inst->surface = (surf); \ + *(chain##_tail) = inst; \ + (chain##_tail) = &inst->tex_chain; \ *(chain##_tail) = 0; \ } while (0) #define CHAIN_SURF_B2F(surf,chain) \ do { \ - (surf)->texturechain = (chain); \ - (chain) = (surf); \ + instsurf_t *inst = (surf)->instsurf; \ + inst->surface = (surf); \ + inst->tex_chain = (chain); \ + (chain) = inst; \ } while (0) extern int lightmap_textures; @@ -85,6 +89,46 @@ extern qboolean lightmap_modified[MAX_LIGHTMAPS]; extern glpoly_t *lightmap_polys[MAX_LIGHTMAPS]; extern glRect_t lightmap_rectchange[MAX_LIGHTMAPS]; +static texture_t **r_texture_chains; +static int r_num_texture_chains; +static int max_texture_chains; +static instsurf_t *static_chains; + +void +R_AddTexture (texture_t *tex) +{ + int i; + if (r_num_texture_chains == max_texture_chains) { + max_texture_chains += 64; + r_texture_chains = realloc (r_texture_chains, + max_texture_chains * sizeof (texture_t *)); + for (i = r_num_texture_chains; i < max_texture_chains; i++) + r_texture_chains[i] = 0; + } + r_texture_chains[r_num_texture_chains++] = tex; + tex->tex_chain = NULL; + tex->tex_chain_tail = &tex->tex_chain; +} + +void +R_InitSurfaceChains (model_t *model) +{ + int i; + + if (static_chains) + free (static_chains); + static_chains = calloc (model->nummodelsurfaces, sizeof (instsurf_t)); + for (i = 0; i < model->nummodelsurfaces; i++) + model->surfaces[i].instsurf = static_chains + i; + +} + +void +R_ClearTextures (void) +{ + r_num_texture_chains = 0; +} + /* R_TextureAnimation @@ -247,7 +291,8 @@ void R_DrawWaterSurfaces (void) { int i; - msurface_t *s; + instsurf_t *s; + msurface_t *fa; if (!waterchain) return; @@ -262,13 +307,19 @@ R_DrawWaterSurfaces (void) } i = -1; - for (s = waterchain; s; s = s->texturechain) { - if (i != s->texinfo->texture->gl_texturenum) { - i = s->texinfo->texture->gl_texturenum; + for (s = waterchain; s; s = s->tex_chain) { + fa = s->surface; + if (s->transform) + qfglLoadMatrixf (s->transform); + else + qfglLoadMatrixf (r_world_matrix); + if (i != fa->texinfo->texture->gl_texturenum) { + i = fa->texinfo->texture->gl_texturenum; qfglBindTexture (GL_TEXTURE_2D, i); } - EmitWaterPolys (s); + EmitWaterPolys (fa); } + qfglLoadMatrixf (r_world_matrix); waterchain = NULL; waterchain_tail = &waterchain; @@ -283,7 +334,8 @@ static inline void DrawTextureChains (int disable_blend, int do_bind) { int i; - msurface_t *s; + instsurf_t *s; + msurface_t *fa; texture_t *tex; if (gl_mtex_active_tmus >= 2) { @@ -307,11 +359,22 @@ DrawTextureChains (int disable_blend, int do_bind) qfglBindTexture (GL_TEXTURE_2D, tex->gl_fb_texturenum); qglActiveTexture (gl_mtex_enum + 1); - for (s = tex->texturechain; s; s = s->texturechain) { + for (s = tex->tex_chain; s; s = s->tex_chain) { + fa = s->surface; + if (s->transform) { + qfglPushMatrix (); + qfglLoadMatrixf (s->transform); + } + if (s->color && do_bind) + qfglColor4fv (s->color); qfglBindTexture (GL_TEXTURE_2D, lightmap_textures + - s->lightmaptexturenum); + fa->lightmaptexturenum); + if (s->transform) + qfglPopMatrix (); + if (s->color && do_bind) + qfglColor3ubv (color_white); - R_RenderBrushPoly_3 (s); + R_RenderBrushPoly_3 (fa); } qglActiveTexture (gl_mtex_enum + 2); @@ -320,11 +383,23 @@ DrawTextureChains (int disable_blend, int do_bind) qglActiveTexture (gl_mtex_enum + 0); } else { qglActiveTexture (gl_mtex_enum + 1); - for (s = tex->texturechain; s; s = s->texturechain) { + for (s = tex->tex_chain; s; s = s->tex_chain) { + fa = s->surface; qfglBindTexture (GL_TEXTURE_2D, lightmap_textures + - s->lightmaptexturenum); + fa->lightmaptexturenum); - R_RenderBrushPoly_2 (s); + if (s->transform) { + qfglPushMatrix (); + qfglLoadMatrixf (s->transform); + } + if (s->color && do_bind) + qfglColor4fv (s->color); + R_RenderBrushPoly_2 (fa); + + if (s->transform) + qfglPopMatrix (); + if (s->color && do_bind) + qfglColor3ubv (color_white); } qglActiveTexture (gl_mtex_enum + 0); @@ -347,8 +422,18 @@ DrawTextureChains (int disable_blend, int do_bind) if (do_bind) qfglBindTexture (GL_TEXTURE_2D, tex->gl_texturenum); - for (s = tex->texturechain; s; s = s->texturechain) - R_RenderBrushPoly_1 (s); + for (s = tex->tex_chain; s; s = s->tex_chain) { + if (s->transform) { + qfglPushMatrix (); + qfglLoadMatrixf (s->transform); + } + R_RenderBrushPoly_1 (s->surface); + + if (s->transform) + qfglPopMatrix (); + if (s->color && do_bind) + qfglColor3ubv (color_white); + } } if (disable_blend) qfglEnable (GL_BLEND); @@ -365,12 +450,12 @@ clear_texture_chains (void) tex = r_texture_chains[i]; if (!tex) continue; - tex->texturechain = NULL; - tex->texturechain_tail = &tex->texturechain; + tex->tex_chain = NULL; + tex->tex_chain_tail = &tex->tex_chain; } tex = r_notexture_mip; - tex->texturechain = NULL; - tex->texturechain_tail = &tex->texturechain; + tex->tex_chain = NULL; + tex->tex_chain_tail = &tex->tex_chain; } static inline void @@ -395,7 +480,7 @@ chain_surface (msurface_t *surf) fullbright_polys[tex->gl_fb_texturenum]; fullbright_polys[tex->gl_fb_texturenum] = surf->polys; } - CHAIN_SURF_F2B (surf, tex->texturechain); + CHAIN_SURF_F2B (surf, tex->tex_chain); } } diff --git a/libs/video/renderer/gl/gl_sky_clip.c b/libs/video/renderer/gl/gl_sky_clip.c index ede8c3bdf..e99f0f390 100644 --- a/libs/video/renderer/gl/gl_sky_clip.c +++ b/libs/video/renderer/gl/gl_sky_clip.c @@ -639,14 +639,16 @@ R_DrawSkyBoxPoly (const glpoly_t *poly) } static void -EmitSkyPolys (float speedscale, const msurface_t *fa) +EmitSkyPolys (float speedscale, const instsurf_t *sc) { float length, s, t; float *v; int i; glpoly_t *p; vec3_t dir; + msurface_t *fa = sc->surface; + //FIXME transform/color for (p = fa->polys; p; p = p->next) { qfglBegin (GL_POLYGON); for (i = 0, v = p->verts[0]; i < p->numverts; i++, v += VERTEXSIZE) { @@ -682,21 +684,27 @@ draw_poly (const glpoly_t *poly) } static void -draw_black_sky_polys (const msurface_t *sky_chain) +draw_black_sky_polys (const instsurf_t *sky_chain) { - const msurface_t *sc = sky_chain; + const instsurf_t *sc = sky_chain; qfglDisable (GL_BLEND); qfglDisable (GL_TEXTURE_2D); qfglColor3ubv (color_black); while (sc) { - glpoly_t *p = sc->polys; + glpoly_t *p = sc->surface->polys; + if (sc->transform) { + qfglPushMatrix (); + qfglLoadMatrixf (sc->transform); + } while (p) { draw_poly (p); p = p->next; } - sc = sc->texturechain; + if (sc->transform) + qfglPushMatrix (); + sc = sc->tex_chain; } qfglEnable (GL_TEXTURE_2D); qfglEnable (GL_BLEND); @@ -704,36 +712,37 @@ draw_black_sky_polys (const msurface_t *sky_chain) } static void -draw_skybox_sky_polys (const msurface_t *sky_chain) +draw_skybox_sky_polys (const instsurf_t *sky_chain) { - const msurface_t *sc = sky_chain; + const instsurf_t *sc = sky_chain; qfglDepthMask (GL_FALSE); qfglDisable (GL_DEPTH_TEST); while (sc) { - glpoly_t *p = sc->polys; + glpoly_t *p = sc->surface->polys; + //FIXME transform/color while (p) { R_DrawSkyBoxPoly (p); p = p->next; } - sc = sc->texturechain; + sc = sc->tex_chain; } qfglEnable (GL_DEPTH_TEST); qfglDepthMask (GL_TRUE); } static void -draw_skydome_sky_polys (const msurface_t *sky_chain) +draw_skydome_sky_polys (const instsurf_t *sky_chain) { // this function is not yet implemented so just draw black draw_black_sky_polys (sky_chain); } static void -draw_id_sky_polys (const msurface_t *sky_chain) +draw_id_sky_polys (const instsurf_t *sky_chain) { - const msurface_t *sc = sky_chain; + const instsurf_t *sc = sky_chain; float speedscale; speedscale = r_realtime / 16; @@ -742,7 +751,7 @@ draw_id_sky_polys (const msurface_t *sky_chain) qfglBindTexture (GL_TEXTURE_2D, solidskytexture); while (sc) { EmitSkyPolys (speedscale, sc); - sc = sc->texturechain; + sc = sc->tex_chain; } if (gl_sky_multipass->int_val) { @@ -754,28 +763,34 @@ draw_id_sky_polys (const msurface_t *sky_chain) qfglBindTexture (GL_TEXTURE_2D, alphaskytexture); while (sc) { EmitSkyPolys (speedscale, sc); - sc = sc->texturechain; + sc = sc->tex_chain; } } } static void -draw_z_sky_polys (const msurface_t *sky_chain) +draw_z_sky_polys (const instsurf_t *sky_chain) { - const msurface_t *sc = sky_chain; + const instsurf_t *sc = sky_chain; qfglColorMask (GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); qfglDisable (GL_BLEND); qfglDisable (GL_TEXTURE_2D); qfglColor3ubv (color_black); while (sc) { - glpoly_t *p = sc->polys; + glpoly_t *p = sc->surface->polys; + if (sc->transform) { + qfglPushMatrix (); + qfglLoadMatrixf (sc->transform); + } while (p) { draw_poly (p); p = p->next; } - sc = sc->texturechain; + if (sc->transform) + qfglPopMatrix (); + sc = sc->tex_chain; } qfglColor3ubv (color_white); qfglEnable (GL_TEXTURE_2D); @@ -784,7 +799,7 @@ draw_z_sky_polys (const msurface_t *sky_chain) } void -R_DrawSkyChain (const msurface_t *sky_chain) +R_DrawSkyChain (const instsurf_t *sky_chain) { if (gl_sky_clip->int_val > 2) { draw_black_sky_polys (sky_chain); @@ -807,15 +822,19 @@ R_DrawSkyChain (const msurface_t *sky_chain) } if (gl_sky_debug->int_val) { - const msurface_t *sc; + const instsurf_t *sc; qfglDisable (GL_TEXTURE_2D); if (gl_sky_debug->int_val & 1) { sc = sky_chain; qfglColor3ub (255, 255, 255); while (sc) { - glpoly_t *p = sc->polys; + glpoly_t *p = sc->surface->polys; + if (sc->transform) { + qfglPushMatrix (); + qfglLoadMatrixf (sc->transform); + } while (p) { int i; @@ -826,7 +845,7 @@ R_DrawSkyChain (const msurface_t *sky_chain) qfglEnd (); p = p->next; } - sc = sc->texturechain; + sc = sc->tex_chain; } } if (gl_sky_debug->int_val & 2) { @@ -834,8 +853,12 @@ R_DrawSkyChain (const msurface_t *sky_chain) qfglColor3ub (0, 255, 0); qfglBegin (GL_POINTS); while (sc) { - glpoly_t *p = sc->polys; + glpoly_t *p = sc->surface->polys; + if (sc->transform) { + qfglPushMatrix (); + qfglLoadMatrixf (sc->transform); + } while (p) { int i; vec3_t x, c = { 0, 0, 0 }; @@ -849,7 +872,9 @@ R_DrawSkyChain (const msurface_t *sky_chain) qfglVertex3fv (c); p = p->next; } - sc = sc->texturechain; + if (sc->transform) + qfglPopMatrix (); + sc = sc->tex_chain; } qfglEnd (); }