/* shadowcaching.c: shadow caching routines: */
#include "shadowcaching.h"

int ShadowRays=0, ShadowCacheHits=0;

#define MAXCACHE 5	/* cache at most 5 blocking patches */
static PATCH *cache[MAXCACHE];
static int cachedpatches, ncached;

/* initialize shadow cache */
void InitShadowCache(void)
{
	int i;

	ncached = cachedpatches = 0;
	for (i=0; i<MAXCACHE; i++) cache[i] = NULL;
}

/* test ray against patches in the shadow cache */
PATCH *CacheHit(RAY *ray, float *dist)
{
	int i; 
	PATCH *hit;

	for (i=0; i<ncached; i++) {
		if ((hit = PatchIntersect(cache[i], ray, 0., dist)))
			return hit;
	}
	return NULL;
}
				
/* replace least recently added patch */
void AddToShadowCache(PATCH *patch)
{
	cache[cachedpatches % MAXCACHE] = patch;
	cachedpatches++;
	if (ncached<MAXCACHE) ncached++;
}

PATCH *ShadowTestGeomlist(RAY *ray, GEOMLIST *world, float dist)
{
	PATCH *hit=NULL;

	ShadowRays++;
	if ((hit = CacheHit(ray, &dist))) 
		ShadowCacheHits++;
	else if ((hit = GeomListIntersect(world, ray, EPSILON, &dist, TRUE))) 
		AddToShadowCache(hit);

	return hit;
}

PATCH *ShadowTestPatchlist(RAY *ray, PATCHLIST *ShadowList, float dist)
{
	PATCH *hit=NULL;

	ShadowRays++;
	if ((hit = CacheHit(ray, &dist))) 
		ShadowCacheHits++;
	else if ((hit = PatchListIntersect(ShadowList, ray, EPSILON, &dist, TRUE))) 
		AddToShadowCache(hit);

	return hit;
}

