diff --git a/Rmakefile b/Rmakefile
index d5cbe20..ed1ef49 100644
--- a/Rmakefile
+++ b/Rmakefile
@@ -1,471 +1,479 @@
 # RCSid: $Id: Rmakefile,v 2.87 2021/01/19 23:31:47 greg Exp $
 #
 # Compiles for ray tracing programs.
 #
 
 OPT = -O
 MACH = -DBSD
 CFLAGS = -I../common -L../lib $(OPT) $(MACH)
 SPECIAL = 
 CC = cc
 AR = ar
 MLIB = -lm
 LINT = lint
 LINTFLAGS = -DBSD
 
 #
 # The following are user-definable:
 #
 DESTDIR = .
 INSTDIR = /usr/local/bin
 INSTALL = cp
 
 #
 # The following paths must exist and be relative to root:
 #
 DEVDIR = $(INSTDIR)/dev
 LIBDIR = /usr/local/lib/ray
 
 #
 # Library routines:
 #
 RLIB = ../lib/libradiance.a
 RCLIB = ../lib/libraycalls.a
 LIBS = -lrtrad $(MLIB)
 
 #
 # Device drivers for rvu (see also devtable.c):
 #
 DOBJS = devtable.o devcomm.o editline.o x11.o x11twind.o \
 	colortab.o
 DSRC = devtable.c devcomm.c editline.c x11.c x11twind.c \
 	colortab.c
 DLIBS = -lX11
 
 #
 # Standard object files:
 #
 
 RTOBJS = rtmain.o rtrace.o duphead.o persist.o
 RTSRC = rtmain.c rtrace.c duphead.c persist.c
 
 RPOBJS = rpmain.o rpict.o srcdraw.o duphead.o persist.o
 RPSRC = rpmain.c rpict.c srcdraw.c duphead.c persist.c
 
 RVOBJS = rvmain.o rview.o rv2.o rv3.o $(DOBJS)
 RVSRC = rvmain.c rview.c rv2.c rv3.c $(DSRC)
 
 RCOBJS = rcmain.o rcontrib.o rc2.o rc3.o
 RCSRC = rcmain.c rcontrib.c rc2.c rc3.c
 
 RLOBJS = raycalls.o raypcalls.o rayfifo.o
 RLSRC = raycalls.c raypcalls.c rayfifo.c
 
 ROBJS = $(RAYOBJS) $(SURFOBJS) $(MATOBJS) \
 	$(MODOBJS) $(SUPPOBJS) $(PMOBJS)
 RSRC = $(RAYSRC) $(SURFSRC) $(MATSRC) \
 	$(MODSRC) $(SUPPSRC)
 
 RAYOBJS = ambcomp.o ambient.o ambio.o freeobjmem.o initotypes.o \
 	preload.o raytrace.o renderopts.o
 RAYSRC = ambcomp.c ambient.c ambio.c freeobjmem.c initotypes.c \
 	preload.c raytrace.c renderopts.c
 
 SURFOBJS = source.o sphere.o srcobstr.o srcsupp.o srcsamp.o virtuals.o \
 	o_face.o o_cone.o o_instance.o o_mesh.o
 SURFSRC = sphere.c source.c srcobstr.c srcsupp.c srcsamp.c virtuals.c \
 	o_face.c srcsamp.c o_cone.c o_instance.c o_mesh.c
 
 MATOBJS = aniso.o normal.o dielectric.o m_clip.o glass.o m_brdf.o \
 	m_mirror.o m_direct.o m_mist.o fprism.o m_alias.o m_bsdf.o \
 	ashikhmin.o
 MATSRC = aniso.c normal.c dielectric.c m_clip.c glass.c m_brdf.c \
 	m_mirror.c m_direct.c m_mist.c fprism.c m_alias.c m_bsdf.c \
 	ashikhmin.c
 
 MODOBJS = p_func.o t_func.o p_data.o t_data.o text.o mx_func.o mx_data.o
 MODSRC = p_func.c t_func.c p_data.c t_data.c text.c mx_func.c mx_data.c
 
 SUPPOBJS = func.o noise3.o data.o
 SUPPSRC = func.c noise3.c data.c
 
 PMOBJS = pmap.o pmapsrc.o pmapmat.o pmaprand.o pmapio.o pmapdata.o pmapdens.o \
          pmapbias.o pmapparm.o pmapcontrib.o pmcontrib2.o pmapamb.o pmapray.o \
          pmapopt.o pmapdiag.o pmaptype.o morton.o oococt.o oocsort.o \
          oocbuild.o oocnn.o ooccache.o pmutil.o pmaproi.o pmapfilt.o mrgbe.o
 PMSRC = pmap.c pmapsrc.c pmapmat.c pmaprand.c pmapio.c pmapdata.c pmapdens.c \
         pmapbias.c pmapparm.c pmapcontrib.c pmcontrib2.c pmapamb.c pmapray.c \
         pmapopt.c pmapdiag.c pmaptype.c morton.c oococt.c oocsort.c \
         oocbuild.c oocnn.c ooccache.c pmutil.c pmapfilt.c pmaproi.c \
         pmapkdt.c pmaptkdt.c pmapooc.c mrgbe.c
 
 HEADERS = ambient.h ray.h data.h otspecial.h source.h
 
 #
 # What this makefile produces:
 #
 
 PROGS = $(DESTDIR)/rtrace $(DESTDIR)/rpict $(DESTDIR)/rvu $(DESTDIR)/rcontrib \
 $(DESTDIR)/lookamb $(DESTDIR)/mkpmap $(DESTDIR)/pmapdump
 
 all:	$(PROGS) $(RCLIB) $(SPECIAL)
 
 install:	all rayinit.cal
 	$(INSTALL) $(PROGS) $(INSTDIR)
 	rm -f $(LIBDIR)/rayinit.cal
 	cp rayinit.cal $(LIBDIR)
 
 ogl:	
 
 clean:
 	set nonomatch; rm -f $(PROGS) *.o
 
 lint:	$(RVSRC)
 	$(LINT) $(LINTFLAGS) -DRVIEW $(RVSRC) $(LIBS)
 
 #
 # Links:
 #
 
 $(DESTDIR)/rtrace:	$(RTOBJS) $(RCLIB) $(RLIB)
 	$(CC) $(CFLAGS) -o $(DESTDIR)/rtrace $(RTOBJS) $(RCLIB) $(RLIB) $(LIBS)
 
 $(DESTDIR)/rpict:	$(RPOBJS) $(RLIB)
 	$(CC) $(CFLAGS) -o $(DESTDIR)/rpict $(RPOBJS) $(RLIB) $(LIBS)
 
 $(DESTDIR)/rvu:	$(RVOBJS) $(RCLIB) $(RLIB)
 	$(CC) $(CFLAGS) -o $(DESTDIR)/rvu $(RVOBJS) $(RCLIB) \
 $(RLIB) $(LIBS) $(DLIBS)
 
 $(DESTDIR)/rcontrib:      $(RCOBJS) $(RLIB)
 	$(CC) $(CFLAGS) -o $(DESTDIR)/rcontrib $(RCOBJS) $(RLIB) $(LIBS)
 
 $(DESTDIR)/lookamb:	lookamb.o ambio.o
 	$(CC) $(CFLAGS) -o $(DESTDIR)/lookamb lookamb.o ambio.o $(LIBS)
 
 $(DESTDIR)/mkpmap: mkpmap.o $(RLIB)
 	$(CC) $(CFLAGS) -o $(DESTDIR)/mkpmap mkpmap.o $(RLIB) $(LIBS)
 
 $(DESTDIR)/pmapdump: pmapdump.o pmaptype.o pmapparm.o
 	$(CC) $(CFLAGS) -o pmapdump pmapdump.o pmaptype.o pmapparm.o $(LIBS)
 
 $(RLIB):	$(ROBJS) Version.o
 	rm -f $(RLIB)
 	$(AR) rc $(RLIB) $(ROBJS) Version.o
 	-ranlib $(RLIB)
 
 $(RCLIB):	$(RLOBJS)
 	rm -f $(RCLIB)
 	$(AR) rc $(RCLIB) $(RLOBJS)
 	-ranlib $(RCLIB)
 
 #
 # Uncomment the following to model dispersion:
 #
 dielectric.o:	dielectric.c source.h
 	$(CC) $(CFLAGS) -DDISPERSE -c dielectric.c
 
 # end of dispersion compiles.
 
 devcomm.o:	devcomm.c
 	$(CC) $(CFLAGS) -DDEVPATH=\"$(DEVDIR)\" -c devcomm.c
 
 #
 # Version module:
 #
 
 Version.c:	VERSION $(RSRC) $(HEADERS)
 	( cat VERSION ; date ; whoami ; hostname ) > Version.c
 	ed - Version.c < verscript.ed || rm Version.c
 
 #
 # Include dependencies:
 #
 
 ambio.o colortab.o data.o devcomm.o \
 devmain.o lookamb.o rview.o x11.o:	../common/color.h
 
 freeobjmem.o o_cone.o srcsupp.o:	../common/cone.h
 
 data.o freeobjmem.o m_brdf.o mx_data.o \
 p_data.o raycalls.o t_data.o:	data.h
 
 devcomm.o devmain.o devtable.o \
 editline.o x11.o:	driver.h
 
 freeobjmem.o o_face.o srcsupp.o:	../common/face.h
 
 ambient.o raytrace.o rpmain.o rtmain.o \
 rtrace.o rvmain.o rv2.o rv3.o:	../common/octree.h
 
 o_instance.o:	../common/instance.h
 
 ambient.o aniso.o ashikhmin.o dielectric.o freeobjmem.o func.o glass.o \
 initotypes.o m_brdf.o m_bsdf.o m_direct.o m_mirror.o normal.o o_cone.o \
 preload.o raycalls.o raytrace.o rtrace.o rv2.o source.o sphere.o \
 srcsupp.o text.o srcdraw.o srcobstr.o virtuals.o:	../common/otypes.h
 
 ambient.o ambcomp.o aniso.o ashikhmin.o normal.o raycalls.o raytrace.o \
 rpict.o rvmain.o rtmain.o rpmain.o rcmain.o persist.o source.o rv3.o \
 srcsamp.o virtuals.o:	../common/random.h
 
 ambcomp.o ambient.o aniso.o ashikhmin.o dielectric.o freeobjmem.o func.o \
 glass.o m_bsdf.o m_brdf.o m_clip.o m_direct.o m_mirror.o m_mist.o mx_data.o \
 o_mesh.o mx_func.o normal.o o_cone.o o_face.o o_instance.o p_data.o p_func.o \
 raycalls.o raypcalls.o rayfifo.o raytrace.o rpict.o rtrace.o rv2.o rv3.o rview.o \
 source.o sphere.o srcdraw.o srcobstr.o srcsamp.o srcsupp.o t_data.o t_func.o \
 text.o rpmain.o rtmain.o rvmain.o virtuals.o m_alias.o rcmain.o \
 rcontrib.o rc2.o rc3.o:	ray.h \
 ../common/standard.h ../common/rtmisc.h ../common/rtio.h ../common/rtmath.h \
 ../common/rterror.h ../common/octree.h \
 ../common/mat4.h ../common/fvect.h ../common/object.h ../common/color.h
 
 rv2.o rv3.o rview.o:	rpaint.h driver.h ../common/view.h ../common/resolu.h
 
 m_direct.o m_mirror.o m_mist.o dielectric.o raycalls.o \
 rpict.o rpmain.o rtmain.o rvmain.o source.o srcdraw.o \
 srcobstr.o srcsamp.o srcsupp.o virtuals.o:	source.h
 
 cone.o data.o devcomm.o initotypes.o fprism.o preload.o \
 duphead.o octree.o:	../common/standard.h ../common/rtmisc.h \
 ../common/rtio.h ../common/rtmath.h \
 ../common/rterror.h ../common/mat4.h ../common/fvect.h
 
 ambio.o:	../common/fvect.h
 
 ambient.o initotypes.o m_alias.o pmapcontrib.o pmapdata.o pmapsrc.o \
 pmcontrib2.o raytrace.o rtrace.o rv2.o rv3.o source.o \
 srcdraw.o srcobstr.o virtuals.o:	otspecial.h
 
 rpmain.o rtmain.o rvmain.o rpict.o \
 srcdraw.o:	../common/view.h ../common/resolu.h
 
 rpict.o:	../common/hilbert.h
 
 x11.o x11twind.o: x11twind.h
 
 x11.o:	x11icon.h
 
 ambient.o ambcomp.o ambio.o lookamb.o raycalls.o:	ambient.h
 
 data.o rpmain.o rtmain.o rvmain.o rpict.o rtrace.o \
 rv2.o:	../common/resolu.h
 
 aniso.o func.o m_brdf.o m_direct.o mx_data.o mx_func.o p_data.o \
 p_func.o t_data.o t_func.o:	func.h ../common/calcomp.h
 
 preload.o:	data.h func.h ../common/object.h ../common/face.h \
 ../common/cone.h ../common/instance.h ../common/mesh.h \
 ../common/color.h ../common/bsdf.h ../common/otypes.h
 
 rtmain.o rpmain.o rvmain.o persist.o duphead.o \
 renderopts.o rpict.o:	../common/paths.h
 
 freeobjmem.o raycalls.o text.o:	../common/font.h
 
 raypcalls.o:	../common/selcall.h
 
 o_mesh.o:	../common/mesh.h
 
 noise3.o:	../common/calcomp.h
 
 aniso.o ashikhmin.o dielectric.o freeobjmem.o glass.o initotypes.o \
 m_alias.o m_brdf.o m_clip.o m_direct.o m_mirror.o m_mist.o \
 mx_data.o mx_func.o normal.o o_cone.o o_face.o o_instance.o \
 o_mesh.o p_data.o p_func.o source.o sphere.o t_data.o t_func.o \
 srcobstr.o text.o:		rtotypes.h
 
 m_bsdf.o:	ambient.h source.h func.h \
 ../common/calcomp.h ../common/bsdf.h ../common/random.h
 
 rcmain.o rcontrib.o rc2.o rc3.o:	rcontrib.h \
 ../common/platform.h ../common/paths.h ../common/lookup.h \
 func.h ../common/calcomp.h ../common/rtprocess.h
 
 ambient.o rcmain.o:	ambient.h
 
 rcmain.o:	source.h
 
 rcontrib.o:	source.h ../common/otypes.h
 
 rc2.o:	../common/resolu.h
 
 rc3.o:	../common/selcall.h
 
 #
 # Photon map include dependencies (via 'gcc -MM -I../common')
 # TODO: Update after adding pmaproi module!
 #
 ambient.o: pmapparm.h pmaptype.h pmapamb.h pmapdata.h
 
 dielectric.o glass.o normal.o m_brdf.o m_bsdf.o ashikhmin.o aniso.o: \
    pmapparm.h pmaptype.h pmapmat.h pmap.h pmapdata.h
    
 raycalls.o rpmain.o rcmain.o rtmain.o rvmain.o: \
    pmapparm.h pmaptype.h pmapray.h
    
 rcmain.o: pmapparm.h pmaptype.h pmapray.h pmapcontrib.h pmapdata.h
    
 raytrace.o: pmapparm.h pmaptype.h pmap.h pmapdata.h
 
 renderopts.o: pmapparm.h pmaptype.h pmapopt.h
 
 rpict.o: pmapparm.h pmaptype.h pmapbias.h pmapdata.h pmapdiag.h
 
 source.o: pmapparm.h pmaptype.h pmap.h pmapdata.h pmapsrc.h
 
 pmapbias.o: pmapbias.c pmapbias.h pmapdata.h ray.h ../common/standard.h \
  ../common/copyright.h ../common/rtio.h ../common/rtmisc.h \
  ../common/rtmath.h ../common/tiff.h ../common/mat4.h ../common/fvect.h \
  ../common/rterror.h ../common/octree.h ../common/object.h \
  ../common/color.h pmapparm.h pmaptype.h ../common/lookup.h pmap.h \
  pmaprand.h
 
 pmapcontrib.o: pmapcontrib.c pmapcontrib.h pmapdata.h ray.h \
  ../common/standard.h ../common/copyright.h ../common/rtio.h \
  ../common/rtmisc.h ../common/rtmath.h ../common/tiff.h ../common/mat4.h \
  ../common/fvect.h ../common/rterror.h ../common/octree.h \
  ../common/object.h ../common/color.h pmapparm.h pmaptype.h \
  ../common/paths.h ../common/lookup.h pmapmat.h pmap.h pmapsrc.h \
  source.h pmaprand.h pmapio.h pmapdiag.h ../common/platform.h \
  rcontrib.h ../common/rtprocess.h ../common/paths.h func.h \
  ../common/calcomp.h ../common/otypes.h \
  pmapkdt.h pmapkdt.c pmapooc.h pmapooc.c
 
 pmapdiag.o: pmapdiag.c pmapdiag.h ../common/platform.h pmapdata.h ray.h \
  ../common/standard.h ../common/copyright.h ../common/rtio.h \
  ../common/rtmisc.h ../common/rtmath.h ../common/tiff.h ../common/mat4.h \
  ../common/fvect.h ../common/rterror.h ../common/octree.h \
  ../common/object.h ../common/color.h pmapparm.h pmaptype.h \
  ../common/lookup.h
 
 pmapio.o: pmapio.c pmapio.h pmapdata.h ray.h ../common/standard.h \
  ../common/copyright.h ../common/rtio.h ../common/rtmisc.h \
  ../common/rtmath.h ../common/tiff.h ../common/mat4.h ../common/fvect.h \
  ../common/rterror.h ../common/octree.h ../common/object.h \
  ../common/color.h pmapparm.h pmaptype.h ../common/paths.h \
  ../common/lookup.h pmapdiag.h ../common/platform.h ../common/resolu.h \
   pmapkdt.h pmapkdt.c pmapooc.h pmapooc.c
 
 pmapray.o: pmapray.c pmapray.h ray.h ../common/standard.h \
  ../common/copyright.h ../common/rtio.h ../common/rtmisc.h \
  ../common/rtmath.h ../common/tiff.h ../common/mat4.h ../common/fvect.h \
  ../common/rterror.h ../common/octree.h ../common/object.h \
  ../common/color.h pmapparm.h pmaptype.h pmap.h pmapdata.h \
  ../common/lookup.h
 
 pmaptype.o: pmaptype.c pmaptype.h
 
 ooccache.o: ooccache.c ooccache.h
 
 oocsort.o: oocsort.c oocsort.h ../common/fvect.h morton.h
 
 oocbuild.o: oocbuild.c oococt.h morton.h ../common/fvect.h ooccache.h \
  oocsort.h
 
 oococt.o: oococt.c oococt.h morton.h ../common/fvect.h ooccache.h \
  ../common/rtio.h
 
 oocnn.o: oocnn.c oocnn.h oococt.h morton.h ../common/fvect.h \
  ooccache.h pmapfilt.h ../common/lookup.h oocsort.h
 
 pmapfilt.o: pmapfilt.c pmapfilt.h ../common/lookup.h pmapdata.h ray.h \
  ../common/standard.h ../common/copyright.h ../common/rtio.h \
  ../common/rtmisc.h ../common/rtmath.h ../common/tiff.h ../common/mat4.h \
  ../common/fvect.h ../common/rterror.h ../common/octree.h \
  ../common/object.h ../common/color.h pmapparm.h pmaptype.h \
  ../common/paths.h  ../common/random.h source.h otspecial.h \
  pmapkdt.h pmapkdt.c pmapooc.h pmapooc.c 
 
 pmapdens.o: pmapdens.c pmapdens.h pmap.h pmapparm.h pmaptype.h pmapdata.h \
  ray.h ../common/standard.h ../common/copyright.h ../common/rtio.h \
  ../common/rtmisc.h ../common/rtmath.h ../common/tiff.h ../common/mat4.h \
  ../common/fvect.h ../common/rterror.h ../common/octree.h \
  ../common/object.h ../common/color.h ../common/paths.h \
  ../common/lookup.h pmapbias.h ../common/otypes.h \
   pmapkdt.h pmapkdt.c pmaptkdt.h pmaptkdt.c pmapooc.h pmapooc.c 
 
-mkpmap.o: pmap.h pmapparm.h pmaptype.h pmapdata.h ray.h \
- ../common/standard.h ../common/copyright.h ../common/rtio.h \
- ../common/rtmisc.h ../common/rtmath.h ../common/tiff.h ../common/mat4.h \
- ../common/fvect.h ../common/rterror.h ../common/octree.h \
- ../common/object.h ../common/color.h ../common/paths.h \
- ../common/lookup.h pmapmat.h pmapsrc.h source.h pmapcontrib.h \
- pmaprand.h ambient.h ../common/resolu.h \
- pmapkdt.h pmapkdt.c pmaptkdt.h pmaptkdt.c pmapooc.h pmapooc.c
-
 pmapdump.o: pmapdump.c pmap.h pmapparm.h pmaptype.h pmapdata.h ray.h \
  ../common/standard.h ../common/copyright.h ../common/rtio.h \
  ../common/rtmisc.h ../common/rtmath.h ../common/tiff.h ../common/mat4.h \
  ../common/fvect.h ../common/rterror.h ../common/octree.h \
  ../common/object.h ../common/color.h ../common/paths.h \
  ../common/lookup.h pmapio.h ../common/rtio.h \
  ../common/resolu.h ../common/random.h \
   pmapkdt.h pmapkdt.c pmaptkdt.h pmaptkdt.c pmapooc.h pmapooc.c
 
+
 pmapdata.o: pmapdata.c pmapdata.h ray.h ../common/standard.h \
  ../common/copyright.h ../common/rtio.h ../common/rtmisc.h \
  ../common/rtmath.h ../common/tiff.h ../common/mat4.h ../common/fvect.h \
  ../common/rterror.h ../common/octree.h ../common/object.h \
  ../common/color.h pmapparm.h pmaptype.h ../common/paths.h \
  ../common/lookup.h pmapdens.h pmap.h pmaprand.h pmapmat.h \
  ../common/otypes.h ../common/random.h source.h otspecial.h \
   pmapkdt.h pmapkdt.c pmaptkdt.h pmaptkdt.c pmapooc.h pmapooc.c
 
 pmap.o: pmap.c pmap.h pmapparm.h pmaptype.h pmapdata.h ray.h \
  ../common/standard.h ../common/copyright.h ../common/rtio.h \
  ../common/rtmisc.h ../common/rtmath.h ../common/tiff.h ../common/mat4.h \
  ../common/fvect.h ../common/rterror.h ../common/octree.h \
  ../common/object.h ../common/color.h ../common/paths.h \
  ../common/lookup.h pmapmat.h pmapsrc.h source.h pmaprand.h pmapio.h \
  pmapdens.h pmapbias.h pmapdiag.h ../common/platform.h ../common/otypes.h \
   pmapkdt.h pmapkdt.c pmaptkdt.h pmaptkdt.c pmapooc.h pmapooc.c
 
 pmapamb.o: pmapamb.c pmapamb.h pmapdata.h ray.h ../common/standard.h \
  ../common/copyright.h ../common/rtio.h ../common/rtmisc.h \
  ../common/rtmath.h ../common/tiff.h ../common/mat4.h ../common/fvect.h \
  ../common/rterror.h ../common/octree.h ../common/object.h \
  ../common/color.h pmapparm.h pmaptype.h ../common/paths.h \
  ../common/lookup.h pmap.h \
   pmapkdt.h pmapkdt.c pmapooc.h pmapooc.c
 
 pmapmat.o: pmapmat.c pmapmat.h pmap.h pmapparm.h pmaptype.h pmapdata.h \
  ray.h ../common/standard.h ../common/copyright.h ../common/rtio.h \
  ../common/rtmisc.h ../common/rtmath.h ../common/tiff.h ../common/mat4.h \
  ../common/fvect.h ../common/rterror.h ../common/octree.h \
  ../common/object.h ../common/color.h ../common/paths.h \
  ../common/lookup.h pmaprand.h ../common/otypes.h data.h func.h \
  ../common/calcomp.h ../common/bsdf.h ../common/ccolor.h \
  ../common/platform.h \
   pmapkdt.h pmapkdt.c pmapooc.h pmapooc.c
 
 pmapsrc.o: pmapsrc.c pmapsrc.h ray.h ../common/standard.h \
  ../common/copyright.h ../common/rtio.h ../common/rtmisc.h \
  ../common/rtmath.h ../common/tiff.h ../common/mat4.h ../common/fvect.h \
  ../common/rterror.h ../common/octree.h ../common/object.h \
  ../common/color.h pmapparm.h pmaptype.h source.h pmap.h pmapdata.h \
  ../common/paths.h ../common/lookup.h pmaprand.h \
  ../common/otypes.h otspecial.h \
   pmapkdt.h pmapkdt.c pmapooc.h pmapooc.c
 
 pmapopt.o: pmapopt.c ray.h ../common/standard.h ../common/copyright.h \
  ../common/rtio.h ../common/rtmisc.h ../common/rtmath.h ../common/tiff.h \
  ../common/mat4.h ../common/fvect.h ../common/rterror.h \
  ../common/octree.h ../common/object.h ../common/color.h pmapparm.h \
  pmaptype.h
 
 pmapparm.o: pmapparm.c pmapparm.h pmaptype.h pmapdata.h ray.h \
  ../common/standard.h ../common/copyright.h ../common/rtio.h \
  ../common/rtmisc.h ../common/rtmath.h ../common/tiff.h ../common/mat4.h \
  ../common/fvect.h ../common/rterror.h ../common/octree.h \
  ../common/object.h ../common/color.h ../common/paths.h ../common/lookup.h \
   pmapkdt.h pmapkdt.c pmapooc.h pmapooc.c
  
 pmutil.o: pmutil.h pmutil.c pmap.h pmapparm.h pmaptype.h pmapdata.h ray.h \
  ../common/standard.h ../common/copyright.h ../common/rtio.h \
  ../common/rtmisc.h ../common/rtmath.h ../common/tiff.h ../common/mat4.h \
  ../common/fvect.h ../common/rterror.h ../common/octree.h \
  ../common/object.h ../common/color.h ../common/paths.h \
  ../common/lookup.h pmapio.h \
   pmapkdt.h pmapkdt.c pmapooc.h pmapooc.c
 
+pmaproi.o: pmaproi.c pmaproi.h ray.h ../common/standard.h \
+ ../common/copyright.h ../common/rtio.h ../common/rtmisc.h \
+ ../common/rtmath.h ../common/tiff.h ../common/mat4.h ../common/fvect.h \
+ ../common/rterror.h ../common/octree.h ../common/object.h \
+ ../common/color.h pmapparm.h pmaptype.h otspecial.h ../common/otypes.h
+
+mkpmap.o: mkpmap.c pmap.h pmapparm.h pmaptype.h ray.h \
+ ../common/standard.h ../common/copyright.h ../common/rtio.h \
+ ../common/rtmisc.h ../common/rtmath.h ../common/tiff.h ../common/mat4.h \
+ ../common/fvect.h ../common/rterror.h ../common/octree.h \
+ ../common/object.h ../common/color.h pmapdata.h ../common/paths.h \
+ ../common/lookup.h pmapkdt.h pmapfilt.h ../common/fvect.h pmaptkdt.h \
+ pmutil.h pmapmat.h pmapsrc.h source.h pmapcontrib.h mrgbe.h rcontrib.h \
+ ../common/platform.h ../common/rtprocess.h ../common/paths.h func.h \
+ ../common/calcomp.h pmaprand.h pmaproi.h pmapio.h ambient.h \
+ ../common/resolu.h
diff --git a/pmaproi.c b/pmaproi.c
index 88e6afe..38094d6 100644
--- a/pmaproi.c
+++ b/pmaproi.c
@@ -1,139 +1,161 @@
 #ifndef lint
 static const char RCSid[] = "$Id$";
 #endif
 
 /* 
    ======================================================================
    Regions of interest used by mkpmap to constrain location of photons
    
    Roland Schregle (roland.schregle@{hslu.ch, gmail.com}
    (c) Fraunhofer Institute for Solar Energy Systems,
        supported by the German Research Foundation 
        (DFG LU-204/10-2, "Fassadenintegrierte Regelsysteme" (FARESYS)) 
    (c) Lucerne University of Applied Sciences and Arts,
        supported by the Swiss National Science Foundation 
        (SNSF #147053, "Daylight Redirecting Components",
         SNSF #179067, "Light Fields for Spatio-Temporal Glare Assessment")
    (c) Tokyo University of Science,
        supported by the JSPS Grants-in-Aid for Scientific Research 
        (KAKENHI JP19KK0115, "Three-Dimensional Light Flow")
    ======================================================================
    
    $Id$
 */
 
 
 #include "pmaproi.h"
 #include "otspecial.h"
 #include "otypes.h"
 
 
 /* Rectangular / spherical regions of interest */
 unsigned pmapNumROI           = 0;
 PhotonMapROI *pmapROI         = NULL;
 
 /* Polyhedral regions of interest by modifier */
 char *pmapROImodList [MAXSET + 1] = {NULL};
-OBJECT polyROIset [MAXSET + 1] = {0};
+OBJECT polyROIset [PMAP_MAXROI + 1] = {0};
 
 
 
 void getPolyROIs (char **roiModList)
 /* Find geometry comprising polyhedral regions of interest from modifiers in
  * roiModList */
 {
    OBJECT i;
    OBJREC *obj, *mat;
    char **lp;
    unsigned lastNumPolys = 0;
    
    /* Init poly ROI set */
    polyROIset [0] = 0;
    
    if (!roiModList [0])
       return;
    
    for (lp = roiModList; *lp; lp++) {
       lastNumPolys = polyROIset [0];
       
       for (i = 0; i < nobjects; i++) {
          obj = objptr(i);
          mat = findmaterial(obj);
       
          /* Check if object is geometry and its modifier is in list */
-         if (issurface(obj -> otype) && mat && !strcmp(mat -> oname, *lp)) {
+         if (mat && !strcmp(mat -> oname, *lp) && issurface(obj -> otype)) {
             if (polyROIset [0] >= PMAP_MAXROI)
                error(USER, "too many ROI objects");
-            
-            insertelem(polyROIset, i);
+            else
+               insertelem(polyROIset, i);
          }
       }
       
       if (polyROIset [0] == lastNumPolys) {
-         /* No geometry found for this modifier */
+         /* No geometry added for this modifier */
          sprintf(errmsg, "no ROI geometry found for modifier %s", *lp);
          error(USER, errmsg);
       }
    }
    
    if (!polyROIset [0])
       /* Made redundant by check above? */
       error(USER, "no ROI modifiers found");
 }
 
 
 
 int photonInROI (const RAY *photonRay)
 /* Returns nonzero if photon defined by photonRay lies in any defined region
  * of interest */
 {
-   unsigned inROI = 0, i;
+   int inROI = 0, i;
 
    if (pmapNumROI && pmapROI) {
       /* Check rectangular / spherical ROIs */
       FVECT    photonDist;
 
       for (i = 0; i < pmapNumROI; i++) {
          VSUB(photonDist, photonRay -> rop, pmapROI [i].pos);
          /* NOTE: Size of spherical ROI is _squared_ */
          inROI = (PMAP_ROI_ISSPHERE(pmapROI + i) 
             ?  DOT(photonDist, photonDist) <= pmapROI [i].siz [0] 
             :  fabs(photonDist [0]) <= pmapROI [i].siz [0] &&
                fabs(photonDist [1]) <= pmapROI [i].siz [1] && 
                fabs(photonDist [2]) <= pmapROI [i].siz [2]
          );
          if (inROI)
             /* Bail out early, skip remaining ROIs */
             return 1;
       }
    }
 
    if (polyROIset [0]) {
       /* Check polyhedral ROIs; send ray and count number of crossed
        * polygons in ROI set */
-      RAY testRay;
+      RAY      testRay;
+      int      rayFlip = 0;
 
       /* Init inclusion test ray from photon origin and incident direction */
       rayorigin(&testRay, PRIMARY, NULL, NULL);
-      /* Offset origin along reversed photon direction in case we have a
-       * surface-bound (i.e. global, caustic) photon, thereby avoiding
-       * potential boundary issues. */
-      VSUM(testRay.rorg, photonRay -> rop, photonRay -> rdir, -2 * FTINY);
-      VCOPY(testRay.rdir, photonRay -> rdir);
       testRay.rmax = FHUGE;
 
-      /* Follow inclusion test ray until it leaves the scene */
-      while (localhit(&testRay, &thescene)) {
-         /* Toggle odd/even number of crossings if intersected object is in
-            ROI set (note this works since inset() returns 0 or 1!) */
-         inROI ^= inset(polyROIset, testRay.robj);
-         /* Update ray origin with intersection for next iteration */
-         VCOPY(testRay.rorg, testRay.rop);
-      }
-
-      return inROI;
+      do {
+         if (!rayFlip) {
+            /* 1st iteration: set up forward test ray from photon hitpoint,
+               offset slightly in reversed direction to avoid potential
+               boundary issues with surface-bound (i.e. global, caustic) 
+               photons */
+            VSUM(testRay.rorg, photonRay -> rop, 
+               photonRay -> rdir, -2 * FTINY
+            );
+            VCOPY(testRay.rdir, photonRay -> rdir);
+         }
+         else {
+            /* 2nd iteration: reverse test ray direction from photon 
+               hitpoint. This additional test mitigates issues with 
+               semi-open ROIs */
+            VCOPY(testRay.rorg, photonRay -> rop);
+            for (i = 0; i < 3; i++)
+               testRay.rdir [i] = -photonRay -> rdir [i];
+         }
+         
+         /* Follow inclusion test ray until it leaves the scene */
+         while (localhit(&testRay, &thescene)) {
+            /* Toggle odd/even number of crossings if intersected object is in
+               ROI set (note this works since inset() returns 0 or 1!) */
+            inROI ^= inset(polyROIset, testRay.robj);
+            /* Update ray origin with intersection for next iteration */
+            VCOPY(testRay.rorg, testRay.rop);
+         }
+         
+         if (!(rayFlip || inROI))
+            /* Preempt reversed test ray if fwd already outside ROI */
+            return 0;
+      } while (rayFlip ^= 1);
+
+      /* inROI==0 if odd #crossings (=inside) in each iteration */
+      return !inROI;
    }
 
    /* No ROIs defined; accept photon unconditionally */
    return 1;
 }
diff --git a/pmaproi.h b/pmaproi.h
index f6e5189..6f7a6fe 100644
--- a/pmaproi.h
+++ b/pmaproi.h
@@ -1,53 +1,53 @@
 /* 
    ======================================================================
    Regions of interest used by mkpmap to constrain location of photons
    
    Roland Schregle (roland.schregle@{hslu.ch, gmail.com}
    (c) Fraunhofer Institute for Solar Energy Systems,
        supported by the German Research Foundation 
        (DFG LU-204/10-2, "Fassadenintegrierte Regelsysteme" (FARESYS)) 
    (c) Lucerne University of Applied Sciences and Arts,
        supported by the Swiss National Science Foundation 
        (SNSF #147053, "Daylight Redirecting Components",
         SNSF #179067, "Light Fields for Spatio-Temporal Glare Assessment")
    (c) Tokyo University of Science,
        supported by the JSPS Grants-in-Aid for Scientific Research 
        (KAKENHI JP19KK0115, "Three-Dimensional Light Flow")
    ======================================================================
    
    $Id$
 */
 
 #ifndef _PMAP_ROI_H
    #define _PMAP_ROI_H
 
    #include "ray.h"
 
-   #define PMAP_MAXROI              1024
+   #define PMAP_MAXROI              2048
    #define PMAP_ROI_ISSPHERE(roi)   ((roi)->siz[1] <= 0 && (roi)->siz[2] <= 0)
    #define PMAP_ROI_SETSPHERE(roi)  ((roi)->siz[1] = (roi)->siz[2] = -1)
 
 
    /* Region of interest defined by geometry */
    typedef struct {
       /* siz [1], siz [2] <= 0 --> sphere, else rectangle */
       float pos [3], siz [3];
    } PhotonMapROI;
 
 
    /* Rectangular / spherical regions of interest */
    extern unsigned         pmapNumROI;
    extern PhotonMapROI     *pmapROI;
 
    /* Polyhedral regions of interest by modifier */
    extern char             *pmapROImodList [];
    extern OBJECT           polyROIset [];
 
 
    void getPolyROIs (char **roiModList);
    /* Find geometry of polyhedral regions of interest from modifier list */
 
    int photonInROI (const RAY *photonRay);
    /* Returns nonzero if photon defined by photonRay lies in any defined
     * region of interest */
 #endif