From 479cccfd703e8f2f70b7015d95fb8dd23bb11d4a Mon Sep 17 00:00:00 2001 From: havoc Date: Fri, 11 Sep 2009 09:45:33 +0000 Subject: [PATCH] refactored and reformatted animcache code, now generates caches on demand (not ideal but never loses speed anymore) git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@9176 d7cf8633-e32d-0410-b094-e92efae38249 --- gl_rmain.c | 190 ++++++++++++++++++++++++++--------------------------- 1 file changed, 92 insertions(+), 98 deletions(-) diff --git a/gl_rmain.c b/gl_rmain.c index 52a10187..9413ad4f 100644 --- a/gl_rmain.c +++ b/gl_rmain.c @@ -2653,133 +2653,126 @@ int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, c //================================================================================== +// LordHavoc: animcache written by Echon, refactored and reformatted by me + /** * Animation cache helps save re-animating a player mesh if it's re-rendered again in a given frame * (reflections, lighting, etc). All animation cache becomes invalid on the next frame and is flushed * (well, over-wrote). The memory for each cache is kept around to save on allocation thrashing. */ -typedef struct +typedef struct r_animcache_entity_s { - int numVerts; - float *vertexes; - float *normals; - float *sVectors; - float *tVectors; -} anim_cache_t; + float *vertex3f; + float *normal3f; + float *svector3f; + float *tvector3f; + int maxvertices; + qboolean wantnormals; + qboolean wanttangents; +} +r_animcache_entity_t; -static anim_cache_t r_animCache[MAX_EDICTS]; -static int r_numAnimCache; +typedef struct r_animcache_s +{ + r_animcache_entity_t entity[MAX_EDICTS]; + int maxindex; + int currentindex; +} +r_animcache_t; + +static r_animcache_t r_animcachestate; -void R_EmptyAnimCache(void) +void R_AnimCache_Free(void) { int idx; - for (idx=0 ; idxnumVerts >= numVerts) + if (cache->maxvertices >= numvertices) return; // Release existing memory - if (cache->vertexes) - Mem_Free(cache->vertexes); + if (cache->vertex3f) + Mem_Free(cache->vertex3f); // Pad by 1024 verts - cache->numVerts = (numVerts + 1023) & ~1023; - arraySize = cache->numVerts * 3; + cache->maxvertices = (numvertices + 1023) & ~1023; + arraySize = cache->maxvertices * 3; // Allocate, even if we don't need this memory in this instance it will get ignored and potentially used later base = (float *)Mem_Alloc(r_main_mempool, arraySize * sizeof(float) * 4); - r_animCache[cacheIdx].vertexes = base; - r_animCache[cacheIdx].normals = base + arraySize; - r_animCache[cacheIdx].sVectors = base + arraySize*2; - r_animCache[cacheIdx].tVectors = base + arraySize*3; + r_animcachestate.entity[cacheIdx].vertex3f = base; + r_animcachestate.entity[cacheIdx].normal3f = base + arraySize; + r_animcachestate.entity[cacheIdx].svector3f = base + arraySize*2; + r_animcachestate.entity[cacheIdx].tvector3f = base + arraySize*3; // Con_Printf("allocated cache for %i (%f KB)\n", cacheIdx, (arraySize*sizeof(float)*4)/1024.0f); } -void R_RunAnimCache(void) +void R_AnimCache_NewFrame(void) { - int entIdx, cacheIdx; - entity_render_t *ent; - dp_model_t *model; - qboolean bWantNormals; - qboolean bWantTangents; - - // Only proceed if desired - if (!r_animcache.integer || !r_drawentities.integer) - { - // Flush memory - if (r_numAnimCache != 0) - { - R_EmptyAnimCache(); + int i; - // Clear any existing animcacheindex references - for (entIdx=0 ; entIdxanimcacheindex = 0; - } - } - return; - } + if (r_animcache.integer && r_drawentities.integer) + r_animcachestate.maxindex = sizeof(r_animcachestate.entity) / sizeof(r_animcachestate.entity[0]); + else if (r_animcachestate.maxindex) + R_AnimCache_Free(); - // Generate new cache - cacheIdx = 0; - for (entIdx=0 ; entIdxanimcacheindex = 0; - continue; - } + for (i = 0;i < r_refdef.scene.numentities;i++) + r_refdef.scene.entities[i]->animcacheindex = -1; +} - model = ent->model; - if (model && model->Draw != NULL - && model->surfmesh.isanimated && model->AnimateVertices && (ent->frameblend[0].lerp != 1 || ent->frameblend[0].subframe != 0)) - { - R_ResizeAnimCache(cacheIdx, model->surfmesh.num_vertices); - - // FIXME: Some stable way of determining if normals/tangets aren't going to be needed would be good for optimizing this - // Need to consider deformvertexes and tcgens that need normals and/or tangents (otherwise they'll slow-path generate them later), as well as some rendering settings - bWantNormals = true; - bWantTangents = true;//bWantNormals && (r_glsl.integer && gl_support_fragment_shader); - model->AnimateVertices( - model, ent->frameblend, - r_animCache[cacheIdx].vertexes, - bWantNormals ? r_animCache[cacheIdx].normals : NULL, - bWantTangents ? r_animCache[cacheIdx].sVectors : NULL, - bWantTangents ? r_animCache[cacheIdx].tVectors : NULL - ); - - cacheIdx++; - ent->animcacheindex = cacheIdx; - } - else - { - ent->animcacheindex = 0; - } +qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents) +{ + dp_model_t *model = ent->model; + r_animcache_entity_t *c; + // see if it's already cached this frame + if (ent->animcacheindex >= 0) + { + // add normals/tangents if needed + c = r_animcachestate.entity + ent->animcacheindex; + if (c->wantnormals) + wantnormals = false; + if (c->wanttangents) + wanttangents = false; + if (wantnormals || wanttangents) + model->AnimateVertices(model, ent->frameblend, NULL, wantnormals ? c->normal3f : NULL, wanttangents ? c->svector3f : NULL, wanttangents ? c->tvector3f : NULL); } - - // Increase our limit if necessary - r_numAnimCache = max(r_numAnimCache, cacheIdx); + else + { + // see if this ent is worth caching + if (r_animcachestate.maxindex <= r_animcachestate.currentindex) + return false; + if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0)) + return false; + // assign it a cache entry and make sure the arrays are big enough + R_AnimCache_ResizeEntityCache(r_animcachestate.currentindex, model->surfmesh.num_vertices); + ent->animcacheindex = r_animcachestate.currentindex++; + c = r_animcachestate.entity + ent->animcacheindex; + c->wantnormals = wantnormals; + c->wanttangents = wanttangents; + model->AnimateVertices(model, ent->frameblend, c->vertex3f, wantnormals ? c->normal3f : NULL, wanttangents ? c->svector3f : NULL, wanttangents ? c->tvector3f : NULL); + } + return true; } //================================================================================== @@ -4135,6 +4128,8 @@ void R_RenderView(void) r_frame++; // used only by R_GetCurrentTexture rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity + R_AnimCache_NewFrame(); + if (r_refdef.view.isoverlay) { // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas] @@ -4298,7 +4293,6 @@ void R_RenderScene(void) if (r_refdef.scene.extraupdate) S_ExtraUpdate (); - R_RunAnimCache(); R_DrawModels(); if (r_timereport_active) R_TimeReport("models"); @@ -5279,12 +5273,12 @@ void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, q } if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0)) { - if (ent->animcacheindex != 0) + if (R_AnimCache_GetEntity((entity_render_t *)ent, wantnormals, wanttangents)) { - rsurface.modelvertex3f = r_animCache[ent->animcacheindex-1].vertexes; - rsurface.modelsvector3f = wanttangents ? r_animCache[ent->animcacheindex-1].sVectors : NULL; - rsurface.modeltvector3f = wanttangents ? r_animCache[ent->animcacheindex-1].tVectors : NULL; - rsurface.modelnormal3f = wantnormals ? r_animCache[ent->animcacheindex-1].normals : NULL; + rsurface.modelvertex3f = r_animcachestate.entity[ent->animcacheindex].vertex3f; + rsurface.modelsvector3f = wanttangents ? r_animcachestate.entity[ent->animcacheindex].svector3f : NULL; + rsurface.modeltvector3f = wanttangents ? r_animcachestate.entity[ent->animcacheindex].tvector3f : NULL; + rsurface.modelnormal3f = wantnormals ? r_animcachestate.entity[ent->animcacheindex].normal3f : NULL; } else if (wanttangents) { @@ -6927,7 +6921,7 @@ static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const // to a model, knowing that they are meaningless otherwise if (ent == r_refdef.scene.worldentity) RSurf_ActiveWorldEntity(); - else if ((ent->effects & EF_FULLBRIGHT) || (r_showsurfaces.integer && r_showsurfaces.integer != 3) || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f)) + else if ((ent->effects & EF_FULLBRIGHT) || (r_showsurfaces.integer && r_showsurfaces.integer != 3)) RSurf_ActiveModelEntity(ent, false, false); else RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader); @@ -7490,7 +7484,7 @@ void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean wr // to a model, knowing that they are meaningless otherwise if (ent == r_refdef.scene.worldentity) RSurf_ActiveWorldEntity(); - else if ((ent->effects & EF_FULLBRIGHT) || (r_showsurfaces.integer && r_showsurfaces.integer != 3) || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f)) + else if ((ent->effects & EF_FULLBRIGHT) || (r_showsurfaces.integer && r_showsurfaces.integer != 3)) RSurf_ActiveModelEntity(ent, false, false); else RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader && !depthonly); -- 2.39.2