Intersect bug: AddToHitList adds the object to the hitlist without checking if there is room in the hitlist->data array. Shadowcache bug: There is a problem if a CSG object or an animated object is put in the shadowcache. If the cached object is used in the next Shadowed() call, TRUE is returned if the object is hit. This can be wrong, because parts of the object may be transparent. The following scene will show the bug: surface glass ambient .02 .02 .02 diffuse 0.1 0.1 0.1 specular 0.8 0.8 0.8 specpow 200 transp 1. index 1.2 extinct 0.98 screen 200 150 eyep -20 30 10 lookp 0 0 0 fov 50 light 1 directional -30 0 50 background .3 0 .4 shutter 1 list sphere glass 3 3 0 -3 sphere 3 3 0 6 end translate (time) 0 0 plane 0 0 -12 0 0 1 ======================= cut here ======================== *** intersect.c.orig Wed Jun 17 17:36:47 1992 --- intersect.c Wed Jun 17 17:38:51 1992 *************** *** 139,146 **** { HitNode *np; Trans *list; ! np = &hitlist->data[hitlist->nodes++]; np->ray = *ray; np->obj = obj; --- 139,150 ---- { HitNode *np; Trans *list; + int i; ! np = &hitlist->data[i = hitlist->nodes++]; ! ! if (i >= MAXMODELDEPTH) ! RLerror(RL_ABORT, "HitList full. Increase libray/libobj/geom.h:MAXMODELDEPTH.\n"); np->ray = *ray; np->obj = obj; *** light.h.orig Thu Jun 18 15:15:04 1992 --- light.h Thu Jun 18 15:18:16 1992 *************** *** 43,50 **** typedef struct { struct Geom *obj; /* Pointer to cached object */ ! RSMatrix trans; /* World-to-object transformation */ char dotrans; /* TRUE if above trans is non-identity */ } ShadowCache; typedef struct { --- 43,52 ---- typedef struct { struct Geom *obj; /* Pointer to cached object */ ! RSMatrix trans; /* World-to-object transformation */ char dotrans; /* TRUE if above trans is non-identity */ + char transp; /* TRUE if parts of the object that */ + /* have no surface will be transparent */ } ShadowCache; typedef struct { *** shadow.c.orig Mon Jun 15 18:37:18 1992 --- shadow.c Thu Jun 18 17:25:51 1992 *************** *** 94,107 **** */ if (intersect(cp->obj, &tmpray, &hitlist, SHADOW_EPSILON, &s)) { ! CacheHits++; ! return TRUE; } } else if (IsAggregate(cp->obj)) { if ((*cp->obj->methods->intersect)(cp->obj->obj, &tmpray, &hitlist, SHADOW_EPSILON, &s)) { ! CacheHits++; ! return TRUE; } } else if ((*cp->obj->methods->intersect)(cp->obj->obj, &tmpray, SHADOW_EPSILON, &s)) { --- 94,118 ---- */ if (intersect(cp->obj, &tmpray, &hitlist, SHADOW_EPSILON, &s)) { ! /* Cannot use GetShadingSurf() */ ! for (sptr = 0, i = 0; i < hitlist.nodes; i++) ! if (sptr = hitlist.data[i].obj->surf) ! break; ! if (sptr && sptr->transp < EPSILON || sptr == 0 && !cp->transp) { ! CacheHits++; ! return TRUE; ! } } } else if (IsAggregate(cp->obj)) { if ((*cp->obj->methods->intersect)(cp->obj->obj, &tmpray, &hitlist, SHADOW_EPSILON, &s)) { ! for (sptr = 0, i = 0; i < hitlist.nodes; i++) ! if (sptr = hitlist.data[i].obj->surf) ! break; ! if (sptr && sptr->transp < EPSILON || sptr == 0 && !cp->transp) { ! CacheHits++; ! return TRUE; ! } } } else if ((*cp->obj->methods->intersect)(cp->obj->obj, &tmpray, SHADOW_EPSILON, &s)) { *************** *** 252,257 **** --- 263,269 ---- HitNode *np; int i, n; extern long ShadowOptions; + int gotsurf = FALSE; i = 0; *************** *** 295,300 **** --- 307,316 ---- i++; np++; } + /* + * DefaultSurface is not transparent + */ + cache->transp = FALSE; cache->dotrans = FALSE; while (i < hitlist->nodes -1) { if (np->obj->trans) { *************** *** 309,314 **** --- 325,335 ---- &cache->trans); cache->dotrans = TRUE; } + } + if (!gotsurf && np->obj->surf) { + gotsurf = TRUE; + if (np->obj->surf->transp >= EPSILON) + cache->transp = TRUE; } i++; np++;