experiences with memory organization (store the vertexs coords on RayFace)
[blender.git] / source / blender / render / intern / source / rayshade.c
index 0fd9365477ca6fa67100185899704642fac79875..685b82d9da2aeb584ea90ef0f0e490ac74403f26 100644 (file)
@@ -29,6 +29,7 @@
 #include <string.h>
 #include <stdlib.h>
 #include <float.h>
+#include <assert.h>
 
 #include "MEM_guardedalloc.h"
 
@@ -56,6 +57,7 @@
 #include "texture.h"
 
 #include "RE_raytrace.h"
+#include "rayobject.h"
 
 #define RAY_TRA                1
 #define RAY_TRAFLIP    2
 extern struct Render R;
 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
 
-static void vlr_face_coords(RayFace *face, float **v1, float **v2, float **v3, float **v4)
+RayObject *  RE_rayobject_tree_create(int type, int size) __attribute__((noinline));
+
+RayObject *  RE_rayobject_tree_create(int type, int size)
 {
-       VlakRen *vlr= (VlakRen*)face;
+//     if(type == R_RAYTRACE_TREE_BIH)
+       return RE_rayobject_vbvh_create(size);
+
+       if(type == R_RAYTRACE_TREE_BVH)
+               return RE_rayobject_bvh_create(size);
+       if(type == R_RAYTRACE_TREE_BIH)
+               return RE_rayobject_bih_create(size);
+       if(type == R_RAYTRACE_TREE_BLIBVH)
+               return RE_rayobject_blibvh_create(size);
 
-       *v1 = (vlr->v1)? vlr->v1->co: NULL;
-       *v2 = (vlr->v2)? vlr->v2->co: NULL;
-       *v3 = (vlr->v3)? vlr->v3->co: NULL;
-       *v4 = (vlr->v4)? vlr->v4->co: NULL;
 }
 
+#ifdef RE_RAYCOUNTER
+RayCounter re_rc_counter[BLENDER_MAX_THREADS] = {};
+#endif
+
+#if 0
 static int vlr_check_intersect(Isect *is, int ob, RayFace *face)
 {
        ObjectInstanceRen *obi= RAY_OBJECT_GET((Render*)is->userdata, ob);
@@ -94,121 +107,299 @@ static int vlr_check_intersect(Isect *is, int ob, RayFace *face)
        else
                return (is->lay & obi->lay);
 }
+#endif
 
-static float *vlr_get_transform(void *userdata, int i)
+void freeraytree(Render *re)
 {
-       ObjectInstanceRen *obi= RAY_OBJECT_GET((Render*)userdata, i);
+       ObjectInstanceRen *obi;
+       
+       if(re->raytree)
+       {
+               RE_rayobject_free(re->raytree);
+               re->raytree = NULL;
+       }
+       if(re->rayfaces)
+       {
+               MEM_freeN(re->rayfaces);
+               re->rayfaces = NULL;
+       }
 
-       return (obi->flag & R_TRANSFORMED)? (float*)obi->mat: NULL;
+       for(obi=re->instancetable.first; obi; obi=obi->next)
+       {
+               ObjectRen *obr = obi->obr;
+               if(obr->raytree)
+               {
+                       RE_rayobject_free(obr->raytree);
+                       obr->raytree = NULL;
+               }
+               if(obr->rayfaces)
+               {
+                       MEM_freeN(obr->rayfaces);
+                       obr->rayfaces = NULL;
+               }
+               if(obi->raytree)
+               {
+                       RE_rayobject_free(obi->raytree);
+                       obi->raytree = NULL;
+               }
+       }
+       
+#ifdef RE_RAYCOUNTER
+       {
+               RayCounter sum = {};
+               int i;
+               for(i=0; i<BLENDER_MAX_THREADS; i++)
+                       RE_RC_MERGE(&sum, re_rc_counter+i);
+               RE_RC_INFO(&sum);
+       }
+#endif
 }
 
-void freeraytree(Render *re)
+static int is_raytraceable_vlr(Render *re, VlakRen *vlr)
 {
-       if(re->raytree) {
-               RE_ray_tree_free(re->raytree);
-               re->raytree= NULL;
-       }
+       if((re->flag & R_BAKE_TRACE) || (vlr->mat->mode & MA_TRACEBLE))
+       if(vlr->mat->material_type != MA_TYPE_WIRE)
+               return 1;
+       return 0;
 }
 
-void makeraytree(Render *re)
+static int is_raytraceable(Render *re, ObjectInstanceRen *obi)
 {
-       ObjectInstanceRen *obi;
-       ObjectRen *obr;
-       VlakRen *vlr= NULL;
-       float min[3], max[3], co1[3], co2[3], co3[3], co4[3];
-       double lasttime= PIL_check_seconds_timer();
-       int v, totv = 0, totface = 0;
-
-       INIT_MINMAX(min, max);
+       int v;
+       ObjectRen *obr = obi->obr;
 
-       /* first min max raytree space */
-       for(obi=re->instancetable.first; obi; obi=obi->next) {
-               obr= obi->obr;
-
-               if(re->excludeob && obr->ob == re->excludeob)
-                       continue;
-
-               for(v=0;v<obr->totvlak;v++) {
-                       if((v & 255)==0) vlr= obr->vlaknodes[v>>8].vlak;
-                       else vlr++;
-                       /* baking selected to active needs non-traceable too */
-                       if((re->flag & R_BAKE_TRACE) || (vlr->mat->mode & MA_TRACEBLE)) {       
-                               if((vlr->mat->mode & MA_WIRE)==0) {     
-                                       VECCOPY(co1, vlr->v1->co);
-                                       VECCOPY(co2, vlr->v2->co);
-                                       VECCOPY(co3, vlr->v3->co);
-
-                                       if(obi->flag & R_TRANSFORMED) {
-                                               Mat4MulVecfl(obi->mat, co1);
-                                               Mat4MulVecfl(obi->mat, co2);
-                                               Mat4MulVecfl(obi->mat, co3);
-                                       }
+       if(re->excludeob && obr->ob == re->excludeob)
+               return 0;
 
-                                       DO_MINMAX(co1, min, max);
-                                       DO_MINMAX(co2, min, max);
-                                       DO_MINMAX(co3, min, max);
+       for(v=0;v<obr->totvlak;v++)
+       {
+               VlakRen *vlr = obr->vlaknodes[v>>8].vlak + (v&255);
+               if(is_raytraceable_vlr(re, vlr))
+                       return 1;
+       }
+       return 0;
+}
 
-                                       if(vlr->v4) {
-                                               VECCOPY(co4, vlr->v4->co);
-                                               if(obi->flag & R_TRANSFORMED)
-                                                       Mat4MulVecfl(obi->mat, co4);
-                                               DO_MINMAX(co4, min, max);
-                                       }
+RayObject* makeraytree_object(Render *re, ObjectInstanceRen *obi)
+{
+       //TODO
+       // out-of-memory safeproof
+       // break render
+       // update render stats
+       ObjectRen *obr = obi->obr;
+       
+       if(obr->raytree == NULL)
+       {
+               RayObject *raytree;
+               RayFace *face;
+               int v;
+               
+               //Count faces
+               int faces = 0;
+               for(v=0;v<obr->totvlak;v++)
+               {
+                       VlakRen *vlr = obr->vlaknodes[v>>8].vlak + (v&255);
+                       if(is_raytraceable_vlr(re, vlr))
+                               faces++;
+               }
+               assert( faces > 0 );
 
-                                       totface++;
-                               }
+               //Create Ray cast accelaration structure
+               
+               //TODO dynamic ocres
+               if(re->r.raystructure == R_RAYSTRUCTURE_HIER_BVH_OCTREE)
+                       raytree = obr->raytree = RE_rayobject_octree_create( re->r.ocres, faces );
+               else //if(re->r.raystructure == R_RAYSTRUCTURE_HIER_BVH_BVH)
+                       raytree = obr->raytree = RE_rayobject_tree_create( re->r.raytrace_tree_type, faces );
+                       
+               face = obr->rayfaces = (RayFace*)MEM_callocN(faces*sizeof(RayFace), "ObjectRen faces");
+               obr->rayobi = obi;
+               
+               for(v=0;v<obr->totvlak;v++)
+               {
+                       VlakRen *vlr = obr->vlaknodes[v>>8].vlak + (v&255);
+                       if(is_raytraceable_vlr(re, vlr))
+                       {
+                               RE_rayface_from_vlak( face, obi, vlr );                         
+                               RE_rayobject_add( raytree, RayObject_unalignRayFace(face) );
+                               face++;
                        }
                }
+               RE_rayobject_done( raytree );
        }
 
-       re->raytree= RE_ray_tree_create(re->r.ocres, totface, min, max,
-               vlr_face_coords, vlr_check_intersect, vlr_get_transform, re);
 
-       if(min[0] > max[0]) { /* empty raytree */
-               RE_ray_tree_done(re->raytree);
-               return; 
+       if(obi->flag & R_TRANSFORMED)
+       {
+               obi->raytree = RE_rayobject_instance_create( obr->raytree, obi->mat, obi, obi->obr->rayobi );
        }
+       
+       if(obi->raytree) return obi->raytree;
+       return obi->obr->raytree;
+}
 
-       for(obi=re->instancetable.first; obi; obi=obi->next) {
-               obr= obi->obr;
+/*
+ * create an hierarchic raytrace structure with all objects
+ *
+ * R_TRANSFORMED objects instances reuse the same tree by using the rayobject_instance
+ */
+static void makeraytree_hier(Render *re)
+{
+       //TODO
+       // out-of-memory safeproof
+       // break render
+       // update render stats
 
-               if(re->excludeob && obr->ob == re->excludeob)
-                       continue;
+       ObjectInstanceRen *obi;
+       int num_objects = 0;
 
-               for(v=0; v<obr->totvlak; v++, totv++) {
-                       if((v & 255)==0) {
-                               double time= PIL_check_seconds_timer();
+       re->i.infostr="Creating raytrace structure";
+       re->stats_draw(re->sdh, &re->i);
 
-                               vlr= obr->vlaknodes[v>>8].vlak;
-                               if(re->test_break())
-                                       break;
-                               if(time-lasttime>1.0f) {
-                                       char str[32];
-                                       sprintf(str, "Filling Octree: %d", totv);
-                                       re->i.infostr= str;
-                                       re->stats_draw(&re->i);
-                                       re->i.infostr= NULL;
-                                       lasttime= time;
-                               }
+       //Count number of objects
+       for(obi=re->instancetable.first; obi; obi=obi->next)
+       if(is_raytraceable(re, obi))
+               num_objects++;
+
+       //Create raytree
+       re->raytree = RE_rayobject_tree_create( re->r.raytrace_tree_type, num_objects );
+       
+       for(obi=re->instancetable.first; obi; obi=obi->next)
+       if(is_raytraceable(re, obi))
+       {
+               RayObject *obj = makeraytree_object(re, obi);
+               RE_rayobject_add( re->raytree, obj );
+
+               if(re->test_break(re->tbh))
+                       break;
+       }
+
+       if(!re->test_break(re->tbh))
+       {
+               RE_rayobject_done( re->raytree );
+       }
+
+       re->i.infostr= NULL;
+       re->stats_draw(re->sdh, &re->i);
+}
+
+/*
+ * create a single raytrace structure with all faces
+ */
+static void makeraytree_single(Render *re)
+{
+       ObjectInstanceRen *obi;
+       RayObject *raytree;
+       RayFace *face;
+       int faces = 0, obs = 0;
+
+       for(obi=re->instancetable.first; obi; obi=obi->next)
+       if(is_raytraceable(re, obi))
+       {
+               int v;
+               ObjectRen *obr = obi->obr;
+               obs++;
+               
+               if(obi->flag & R_TRANSFORMED)
+               {
+                       faces++;
+               }
+               else
+               {
+                       for(v=0;v<obr->totvlak;v++)
+                       {
+                               VlakRen *vlr = obr->vlaknodes[v>>8].vlak + (v&255);
+                               if(is_raytraceable_vlr(re, vlr))
+                                       faces++;
                        }
-                       else vlr++;
-                       
-                       if((re->flag & R_BAKE_TRACE) || (vlr->mat->mode & MA_TRACEBLE))
-                               if((vlr->mat->mode & MA_WIRE)==0)
-                                       RE_ray_tree_add_face(re->raytree, RAY_OBJECT_SET(re, obi), vlr);
                }
        }
+       
+       //Create raytree
+       if(re->r.raystructure == R_RAYSTRUCTURE_SINGLE_OCTREE)
+               raytree = re->raytree = RE_rayobject_octree_create( re->r.ocres, faces );
+       else //if(re->r.raystructure == R_RAYSTRUCTURE_SINGLE_BVH)
+               raytree = re->raytree = RE_rayobject_tree_create( re->r.raytrace_tree_type, faces );
 
-       RE_ray_tree_done(re->raytree);
+       face    = re->rayfaces  = (RayFace*)MEM_callocN(faces*sizeof(RayFace), "Render ray faces");
        
-       re->i.infostr= NULL;
-       re->stats_draw(&re->i);
+       for(obi=re->instancetable.first; obi; obi=obi->next)
+       if(is_raytraceable(re, obi))
+       {
+               if(obi->flag & R_TRANSFORMED)
+               {
+                       RayObject *obj = makeraytree_object(re, obi);
+                       RE_rayobject_add( re->raytree, obj );
+               }
+               else
+               {
+                       int v;
+                       ObjectRen *obr = obi->obr;
+
+                       for(v=0;v<obr->totvlak;v++)
+                       {
+                               VlakRen *vlr = obr->vlaknodes[v>>8].vlak + (v&255);
+                               if(is_raytraceable_vlr(re, vlr))
+                               {
+                                       RE_rayface_from_vlak(face, obi, vlr);
+                                       RE_rayobject_add( raytree, RayObject_unalignRayFace(face) );
+                                       face++;
+                               }
+                       }
+               }
+       }
+       RE_rayobject_done( raytree );   
 }
 
+void makeraytree(Render *re)
+{
+       float min[3], max[3], sub[3];
+       int i;
+       const char *tree_type = "Tree(unknown)";
+
+       re->r.raystructure = R_RAYSTRUCTURE_SINGLE_BVH;
+#ifdef RE_RAYCOUNTER
+       if(re->r.raytrace_tree_type == R_RAYTRACE_TREE_BVH)
+               tree_type = "BVH";
+       if(re->r.raytrace_tree_type == R_RAYTRACE_TREE_BIH)
+               tree_type = "BIH";
+       if(re->r.raytrace_tree_type == R_RAYTRACE_TREE_BLIBVH)
+               tree_type = "BLIBVH";
+
+       if(re->r.raystructure == R_RAYSTRUCTURE_SINGLE_OCTREE)
+               printf("Building single octree\n");
+       else if(re->r.raystructure == R_RAYSTRUCTURE_SINGLE_BVH)
+               printf("Building single tree(%s)\n", tree_type);
+       else if(re->r.raystructure == R_RAYSTRUCTURE_HIER_BVH_OCTREE)
+               printf("Building tree(%s) of octrees\n", tree_type);
+       else
+               printf("Building tree(%s) of trees(%s)\n", tree_type, tree_type);
+#endif
+
+       if(ELEM(re->r.raystructure, R_RAYSTRUCTURE_SINGLE_BVH, R_RAYSTRUCTURE_SINGLE_OCTREE))
+               BENCH(makeraytree_single(re), tree_build);
+       else
+               BENCH(makeraytree_hier(re), tree_build);
+               
+               
+       //Calculate raytree max_size
+       //This is ONLY needed to kept a bogus behaviour of SUN and HEMI lights
+       RE_rayobject_merge_bb( re->raytree, min, max );
+       for(i=0; i<3; i++)
+       {
+               min[i] += 0.01f;
+               max[i] += 0.01f;
+               sub[i] = max[i]-min[i];
+       }
+       re->maxdist = sqrt( sub[0]*sub[0] + sub[1]*sub[1] + sub[2]*sub[2] );
+}
+
+
+
 static void shade_ray(Isect *is, ShadeInput *shi, ShadeResult *shr)
 {
-       VlakRen *vlr= (VlakRen*)is->face;
-       ObjectInstanceRen *obi= RAY_OBJECT_GET(&R, is->ob);
+       ObjectInstanceRen *obi= (ObjectInstanceRen*)is->hit.ob;
+       VlakRen *vlr= (VlakRen*)is->hit.face;
        int osatex= 0;
        
        /* set up view vector */
@@ -225,8 +416,7 @@ static void shade_ray(Isect *is, ShadeInput *shi, ShadeResult *shr)
        shi->obr= obi->obr;
        shi->vlr= vlr;
        shi->mat= vlr->mat;
-       memcpy(&shi->r, &shi->mat->r, 23*sizeof(float));        // note, keep this synced with render_types.h
-       shi->har= shi->mat->har;
+       shade_input_init_material(shi);
        
        // Osa structs we leave unchanged now
        SWAP(int, osatex, shi->osatex);
@@ -262,13 +452,15 @@ static void shade_ray(Isect *is, ShadeInput *shi, ShadeResult *shr)
 
        shade_input_set_shade_texco(shi);
        
-       if(is->mode==RE_RAY_SHADOW_TRA) 
-               if(shi->mat->nodetree && shi->mat->use_nodes) {
+       if(is->mode==RE_RAY_SHADOW_TRA) {
+               /* temp hack to prevent recursion */
+               if(shi->nodes==0 && shi->mat->nodetree && shi->mat->use_nodes) {
                        ntreeShaderExecTree(shi->mat->nodetree, shi, shr);
                        shi->mat= vlr->mat;             /* shi->mat is being set in nodetree */
                }
                else
                        shade_color(shi, shr);
+       }
        else {
                if(shi->mat->nodetree && shi->mat->use_nodes) {
                        ntreeShaderExecTree(shi->mat->nodetree, shi, shr);
@@ -396,7 +588,8 @@ static void ray_fadeout_endcolor(float *col, ShadeInput *origshi, ShadeInput *sh
                VECCOPY(shi->view, vec);
                Normalize(shi->view);
                
-               shadeSkyView(col, isec->start, shi->view, NULL);
+               shadeSkyView(col, isec->start, shi->view, NULL, shi->thread);
+               shadeSunView(col, shi->view);
        }
 }
 
@@ -419,7 +612,7 @@ static void traceray(ShadeInput *origshi, ShadeResult *origshr, short depth, flo
        ShadeResult shr;
        Isect isec;
        float f, f1, fr, fg, fb;
-       float ref[3], maxsize=RE_ray_tree_max_size(R.raytree);
+       float ref[3];
        float dist_mir = origshi->mat->dist_mir;
 
        /* Warning, This is not that nice, and possibly a bit slow for every ray,
@@ -428,20 +621,17 @@ static void traceray(ShadeInput *origshi, ShadeResult *origshr, short depth, flo
        /* end warning! - Campbell */
        
        VECCOPY(isec.start, start);
-       if (dist_mir > 0.0) {
-               isec.end[0]= start[0]+dist_mir*vec[0];
-               isec.end[1]= start[1]+dist_mir*vec[1];
-               isec.end[2]= start[2]+dist_mir*vec[2];
-       } else {
-               isec.end[0]= start[0]+maxsize*vec[0];
-               isec.end[1]= start[1]+maxsize*vec[1];
-               isec.end[2]= start[2]+maxsize*vec[2];
-       }
+       VECCOPY(isec.vec, vec );
+       isec.labda = dist_mir > 0 ? dist_mir : RE_RAYTRACE_MAXDIST;
        isec.mode= RE_RAY_MIRROR;
-       isec.faceorig= (RayFace*)vlr;
-       isec.oborig= RAY_OBJECT_SET(&R, obi);
+       isec.skip = RE_SKIP_VLR_NEIGHBOUR;
+       isec.hint = 0;
+
+       isec.orig.ob   = obi;
+       isec.orig.face = vlr;
+       RE_RC_INIT(isec, shi);
 
-       if(RE_ray_tree_intersect(R.raytree, &isec)) {
+       if(RE_rayobject_raycast(R.raytree, &isec)) {
                float d= 1.0f;
                
                shi.mask= origshi->mask;
@@ -633,24 +823,27 @@ void init_jitter_plane(LampRen *lar)
        /* at least 4, or max threads+1 tables */
        if(BLENDER_MAX_THREADS < 4) x= 4;
        else x= BLENDER_MAX_THREADS+1;
-       fp= lar->jitter= MEM_mallocN(x*tot*2*sizeof(float), "lamp jitter tab");
+       fp= lar->jitter= MEM_callocN(x*tot*2*sizeof(float), "lamp jitter tab");
        
-       /* set per-lamp fixed seed */
-       BLI_srandom(tot);
-       
-       /* fill table with random locations, area_size large */
-       for(x=0; x<tot; x++, fp+=2) {
-               fp[0]= (BLI_frand()-0.5)*lar->area_size;
-               fp[1]= (BLI_frand()-0.5)*lar->area_sizey;
-       }
-       
-       while(iter--) {
-               fp= lar->jitter;
-               for(x=tot; x>0; x--, fp+=2) {
-                       DP_energy(lar->jitter, fp, tot, lar->area_size, lar->area_sizey);
+       /* if 1 sample, we leave table to be zero's */
+       if(tot>1) {
+               
+               /* set per-lamp fixed seed */
+               BLI_srandom(tot);
+               
+               /* fill table with random locations, area_size large */
+               for(x=0; x<tot; x++, fp+=2) {
+                       fp[0]= (BLI_frand()-0.5)*lar->area_size;
+                       fp[1]= (BLI_frand()-0.5)*lar->area_sizey;
                }
-       }
-       
+               
+               while(iter--) {
+                       fp= lar->jitter;
+                       for(x=tot; x>0; x--, fp+=2) {
+                               DP_energy(lar->jitter, fp, tot, lar->area_size, lar->area_sizey);
+                       }
+               }
+       }       
        /* create the dithered tables (could just check lamp type!) */
        jitter_plane_offset(lar->jitter, lar->jitter+2*tot, tot, lar->area_size, lar->area_sizey, 0.5f, 0.0f);
        jitter_plane_offset(lar->jitter, lar->jitter+4*tot, tot, lar->area_size, lar->area_sizey, 0.5f, 0.5f);
@@ -733,7 +926,7 @@ static void hammersley_create(double *out, int n)
        }
 }
 
-struct QMCSampler *QMC_initSampler(int type, int tot)
+static struct QMCSampler *QMC_initSampler(int type, int tot)
 {      
        QMCSampler *qsa = MEM_callocN(sizeof(QMCSampler), "qmc sampler");
        qsa->samp2d = MEM_callocN(2*sizeof(double)*tot, "qmc sample table");
@@ -882,7 +1075,7 @@ void init_render_qmcsampler(Render *re)
        re->qmcsamplers= MEM_callocN(sizeof(ListBase)*BLENDER_MAX_THREADS, "QMCListBase");
 }
 
-QMCSampler *get_thread_qmcsampler(Render *re, int thread, int type, int tot)
+static QMCSampler *get_thread_qmcsampler(Render *re, int thread, int type, int tot)
 {
        QMCSampler *qsa;
 
@@ -903,7 +1096,7 @@ QMCSampler *get_thread_qmcsampler(Render *re, int thread, int type, int tot)
        return qsa;
 }
 
-void release_thread_qmcsampler(Render *re, int thread, QMCSampler *qsa)
+static void release_thread_qmcsampler(Render *re, int thread, QMCSampler *qsa)
 {
        qsa->used= 0;
 }
@@ -1173,7 +1366,6 @@ static void trace_reflect(float *col, ShadeInput *shi, ShadeResult *shr, float f
 /* extern call from render loop */
 void ray_trace(ShadeInput *shi, ShadeResult *shr)
 {
-       VlakRen *vlr;
        float i, f, f1, fr, fg, fb;
        float mircol[4], tracol[4];
        float diff[3];
@@ -1181,7 +1373,6 @@ void ray_trace(ShadeInput *shi, ShadeResult *shr)
        
        do_tra= ((shi->mat->mode & (MA_RAYTRANSP)) && shr->alpha!=1.0f);
        do_mir= ((shi->mat->mode & MA_RAYMIRROR) && shi->ray_mirror!=0.0f);
-       vlr= shi->vlr;
        
        /* raytrace mirror amd refract like to separate the spec color */
        if(shi->combinedflag & SCE_PASS_SPEC)
@@ -1270,14 +1461,14 @@ static void addAlphaLight(float *shadfac, float *col, float alpha, float filter)
        shadfac[3]= (1.0f-alpha)*shadfac[3];
 }
 
-static void ray_trace_shadow_tra(Isect *is, int depth, int traflag)
+static void ray_trace_shadow_tra(Isect *is, ShadeInput *origshi, int depth, int traflag)
 {
        /* ray to lamp, find first face that intersects, check alpha properties,
           if it has col[3]>0.0f  continue. so exit when alpha is full */
        ShadeInput shi;
        ShadeResult shr;
-
-       if(RE_ray_tree_intersect(R.raytree, is)) {
+       
+       if(RE_rayobject_raycast(R.raytree, is)) {
                float d= 1.0f;
                /* we got a face */
                
@@ -1287,16 +1478,15 @@ static void ray_trace_shadow_tra(Isect *is, int depth, int traflag)
                /* end warning! - Campbell */
                
                shi.depth= 1;                                   /* only used to indicate tracing */
-               shi.mask= 1;
-               
-               /*shi.osatex= 0;
-               shi.thread= shi.sample= 0;
-               shi.lay= 0;
-               shi.passflag= 0;
-               shi.combinedflag= 0;
-               shi.do_preview= 0;
-               shi.light_override= NULL;
-               shi.mat_override= NULL;*/
+               shi.mask= origshi->mask;
+               shi.thread= origshi->thread;
+               shi.passflag= SCE_PASS_COMBINED;
+               shi.combinedflag= 0xFFFFFF;              /* ray trace does all options */
+       
+               shi.xs= origshi->xs;
+               shi.ys= origshi->ys;
+               shi.lay= origshi->lay;
+               shi.nodes= origshi->nodes;
                
                shade_ray(is, &shi, &shr);
                if (traflag & RAY_TRA)
@@ -1309,10 +1499,11 @@ static void ray_trace_shadow_tra(Isect *is, int depth, int traflag)
                        
                        /* adapt isect struct */
                        VECCOPY(is->start, shi.co);
-                       is->oborig= RAY_OBJECT_SET(&R, shi.obi);
-                       is->faceorig= (RayFace*)shi.vlr;
 
-                       ray_trace_shadow_tra(is, depth-1, traflag | RAY_TRA);
+                       is->orig.ob   = shi.obi;
+                       is->orig.face = shi.vlr;
+
+                       ray_trace_shadow_tra(is, origshi, depth-1, traflag | RAY_TRA);
                }
        }
 }
@@ -1326,9 +1517,11 @@ int ray_trace_shadow_rad(ShadeInput *ship, ShadeResult *shr)
        Isect isec;
        ShadeInput shi;
        ShadeResult shr_t;
-       float vec[3], accum[3], div= 0.0f, maxsize= RE_ray_tree_max_size(R.raytree);
+       float vec[3], accum[3], div= 0.0f;
        int a;
        
+       assert(0);
+       
        if(only_one) {
                return 0;
        }
@@ -1336,8 +1529,13 @@ int ray_trace_shadow_rad(ShadeInput *ship, ShadeResult *shr)
        
        accum[0]= accum[1]= accum[2]= 0.0f;
        isec.mode= RE_RAY_MIRROR;
-       isec.faceorig= (RayFace*)ship->vlr;
-       isec.oborig= RAY_OBJECT_SET(&R, ship->obi);
+       isec.orig.ob   = ship->obi;
+       isec.orig.face = ship->vlr;
+       isec.hint = 0;
+
+       VECCOPY(isec.start, ship->co);
+       
+       RE_RC_INIT(isec, shi);
        
        for(a=0; a<8*8; a++) {
                
@@ -1349,12 +1547,11 @@ int ray_trace_shadow_rad(ShadeInput *ship, ShadeResult *shr)
                        vec[1]-= vec[1];
                        vec[2]-= vec[2];
                }
-               VECCOPY(isec.start, ship->co);
-               isec.end[0]= isec.start[0] + maxsize*vec[0];
-               isec.end[1]= isec.start[1] + maxsize*vec[1];
-               isec.end[2]= isec.start[2] + maxsize*vec[2];
-               
-               if(RE_ray_tree_intersect(R.raytree, &isec)) {
+
+               VECCOPY(isec.vec, vec );
+               isec.labda = RE_RAYTRACE_MAXDIST;
+
+               if(RE_rayobject_raycast(R.raytree, &isec)) {
                        float fac;
                        
                        /* Warning, This is not that nice, and possibly a bit slow for every ray,
@@ -1524,18 +1721,18 @@ static float *sphere_sampler(int type, int resol, int thread, int xs, int ys)
        }
 }
 
-void ray_ao_qmc(ShadeInput *shi, float *shadfac)
+static void ray_ao_qmc(ShadeInput *shi, float *shadfac)
 {
        Isect isec;
+       RayHint point_hint;
        QMCSampler *qsa=NULL;
        float samp3d[3];
        float up[3], side[3], dir[3], nrm[3];
        
        float maxdist = R.wrld.aodist;
        float fac=0.0f, prev=0.0f;
-       float adapt_thresh = G.scene->world->ao_adapt_thresh;
-       float adapt_speed_fac = G.scene->world->ao_adapt_speed_fac;
-       float bias = G.scene->world->aobias;
+       float adapt_thresh = R.wrld.ao_adapt_thresh;
+       float adapt_speed_fac = R.wrld.ao_adapt_speed_fac;
        
        int samples=0;
        int max_samples = R.wrld.aosamp*R.wrld.aosamp;
@@ -1543,13 +1740,25 @@ void ray_ao_qmc(ShadeInput *shi, float *shadfac)
        float dxyview[3], skyadded=0, div;
        int aocolor;
        
-       isec.faceorig= (RayFace*)shi->vlr;
-       isec.oborig= RAY_OBJECT_SET(&R, shi->obi);
-       isec.face_last= NULL;
-       isec.ob_last= 0;
+       RE_RC_INIT(isec, *shi);
+       isec.orig.ob   = shi->obi;
+       isec.orig.face = shi->vlr;
+       isec.skip = RE_SKIP_VLR_NEIGHBOUR;
+       isec.hint = 0;
+
+       isec.hit.ob   = 0;
+       isec.hit.face = 0;
+
+       isec.last_hit = NULL;
+       
        isec.mode= (R.wrld.aomode & WO_AODIST)?RE_RAY_SHADOW_TRA:RE_RAY_SHADOW;
        isec.lay= -1;
        
+       VECCOPY(isec.start, shi->co);           
+       RE_rayobject_hint_bb( R.raytree, &point_hint, isec.start, isec.start );
+       isec.hint = &point_hint;
+
+       
        shadfac[0]= shadfac[1]= shadfac[2]= 0.0f;
        
        /* prevent sky colors to be added for only shadow (shadow becomes alpha) */
@@ -1563,13 +1772,10 @@ void ray_ao_qmc(ShadeInput *shi, float *shadfac)
                dxyview[2]= 0.0f;
        }
        
-       /* bias prevents smoothed faces to appear flat */
        if(shi->vlr->flag & R_SMOOTH) {
-               bias= G.scene->world->aobias;
                VECCOPY(nrm, shi->vn);
        }
        else {
-               bias= 0.0f;
                VECCOPY(nrm, shi->facenor);
        }
        
@@ -1590,6 +1796,7 @@ void ray_ao_qmc(ShadeInput *shi, float *shadfac)
 
        QMC_initPixel(qsa, shi->thread);
        
+       
        while (samples < max_samples) {
 
                /* sampling, returns quasi-random vector in unit hemisphere */
@@ -1601,14 +1808,14 @@ void ray_ao_qmc(ShadeInput *shi, float *shadfac)
                
                Normalize(dir);
                        
-               VECCOPY(isec.start, shi->co);
-               isec.end[0] = shi->co[0] - maxdist*dir[0];
-               isec.end[1] = shi->co[1] - maxdist*dir[1];
-               isec.end[2] = shi->co[2] - maxdist*dir[2];
+               isec.vec[0] = -dir[0];
+               isec.vec[1] = -dir[1];
+               isec.vec[2] = -dir[2];
+               isec.labda = maxdist;
                
                prev = fac;
                
-               if(RE_ray_tree_intersect(R.raytree, &isec)) {
+               if(RE_rayobject_raycast(R.raytree, &isec)) {
                        if (R.wrld.aomode & WO_AODIST) fac+= exp(-isec.labda*R.wrld.aodistfac); 
                        else fac+= 1.0f;
                }
@@ -1628,7 +1835,8 @@ void ray_ao_qmc(ShadeInput *shi, float *shadfac)
                                shadfac[2]+= (1.0f-skyfac)*R.wrld.horb + skyfac*R.wrld.zenb;
                        }
                        else {  /* WO_AOSKYTEX */
-                               shadeSkyView(skycol, isec.start, view, dxyview);
+                               shadeSkyView(skycol, isec.start, view, dxyview, shi->thread);
+                               shadeSunView(skycol, shi->view);
                                shadfac[0]+= skycol[0];
                                shadfac[1]+= skycol[1];
                                shadfac[2]+= skycol[2];
@@ -1664,27 +1872,38 @@ void ray_ao_qmc(ShadeInput *shi, float *shadfac)
 }
 
 /* extern call from shade_lamp_loop, ambient occlusion calculus */
-void ray_ao_spheresamp(ShadeInput *shi, float *shadfac)
+static void ray_ao_spheresamp(ShadeInput *shi, float *shadfac)
 {
        Isect isec;
+       RayHint point_hint;
        float *vec, *nrm, div, bias, sh=0.0f;
        float maxdist = R.wrld.aodist;
        float dxyview[3];
        int j= -1, tot, actual=0, skyadded=0, aocolor, resol= R.wrld.aosamp;
        
-       isec.faceorig= (RayFace*)shi->vlr;
-       isec.oborig= RAY_OBJECT_SET(&R, shi->obi);
-       isec.face_last= NULL;
-       isec.ob_last= 0;
+       RE_RC_INIT(isec, *shi);
+       isec.orig.ob   = shi->obi;
+       isec.orig.face = shi->vlr;
+       isec.skip = RE_SKIP_VLR_NEIGHBOUR;
+       isec.hint = 0;
+
+       isec.hit.ob   = 0;
+       isec.hit.face = 0;
+       
+       isec.last_hit = NULL;
+       
        isec.mode= (R.wrld.aomode & WO_AODIST)?RE_RAY_SHADOW_TRA:RE_RAY_SHADOW;
        isec.lay= -1;
 
+       VECCOPY(isec.start, shi->co);           
+       RE_rayobject_hint_bb( R.raytree, &point_hint, isec.start, isec.start );
+       isec.hint = &point_hint;
 
        shadfac[0]= shadfac[1]= shadfac[2]= 0.0f;
 
        /* bias prevents smoothed faces to appear flat */
        if(shi->vlr->flag & R_SMOOTH) {
-               bias= G.scene->world->aobias;
+               bias= R.wrld.aobias;
                nrm= shi->vn;
        }
        else {
@@ -1725,14 +1944,14 @@ void ray_ao_spheresamp(ShadeInput *shi, float *shadfac)
                        
                        actual++;
                        
-                       /* always set start/end, RE_ray_tree_intersect clips it */
-                       VECCOPY(isec.start, shi->co);
-                       isec.end[0] = shi->co[0] - maxdist*vec[0];
-                       isec.end[1] = shi->co[1] - maxdist*vec[1];
-                       isec.end[2] = shi->co[2] - maxdist*vec[2];
+                       /* always set start/vec/labda */
+                       isec.vec[0] = -vec[0];
+                       isec.vec[1] = -vec[1];
+                       isec.vec[2] = -vec[2];
+                       isec.labda = maxdist;
                        
                        /* do the trace */
-                       if(RE_ray_tree_intersect(R.raytree, &isec)) {
+                       if(RE_rayobject_raycast(R.raytree, &isec)) {
                                if (R.wrld.aomode & WO_AODIST) sh+= exp(-isec.labda*R.wrld.aodistfac); 
                                else sh+= 1.0f;
                        }
@@ -1752,7 +1971,8 @@ void ray_ao_spheresamp(ShadeInput *shi, float *shadfac)
                                        shadfac[2]+= (1.0f-fac)*R.wrld.horb + fac*R.wrld.zenb;
                                }
                                else {  /* WO_AOSKYTEX */
-                                       shadeSkyView(skycol, isec.start, view, dxyview);
+                                       shadeSkyView(skycol, isec.start, view, dxyview, shi->thread);
+                                       shadeSunView(skycol, shi->view);
                                        shadfac[0]+= skycol[0];
                                        shadfac[1]+= skycol[1];
                                        shadfac[2]+= skycol[2];
@@ -1791,20 +2011,64 @@ void ray_ao(ShadeInput *shi, float *shadfac)
                ray_ao_spheresamp(shi, shadfac);
 }
 
+static void ray_shadow_jittered_coords(ShadeInput *shi, int max, float jitco[RE_MAX_OSA][3], int *totjitco)
+{
+       /* magic numbers for reordering sample positions to give better
+        * results with adaptive sample, when it usually only takes 4 samples */
+       int order8[8] = {0, 1, 5, 6, 2, 3, 4, 7};
+       int order11[11] = {1, 3, 8, 10, 0, 2, 4, 5, 6, 7, 9};
+       int order16[16] = {1, 3, 9, 12, 0, 6, 7, 8, 13, 2, 4, 5, 10, 11, 14, 15};
+       int count = count_mask(shi->mask);
+
+       /* for better antialising shadow samples are distributed over the subpixel
+        * sample coordinates, this only works for raytracing depth 0 though */
+       if(!shi->strand && shi->depth == 0 && count > 1 && count <= max) {
+               float xs, ys, zs, view[3];
+               int samp, ordsamp, tot= 0;
+
+               for(samp=0; samp<R.osa; samp++) {
+                       if(R.osa == 8) ordsamp = order8[samp];
+                       else if(R.osa == 11) ordsamp = order11[samp];
+                       else if(R.osa == 16) ordsamp = order16[samp];
+                       else ordsamp = samp;
+
+                       if(shi->mask & (1<<ordsamp)) {
+                               /* zbuffer has this inverse corrected, ensures xs,ys are inside pixel */
+                               xs= (float)shi->scanco[0] + R.jit[ordsamp][0] + 0.5f;
+                               ys= (float)shi->scanco[1] + R.jit[ordsamp][1] + 0.5f;
+                               zs= shi->scanco[2];
+
+                               shade_input_calc_viewco(shi, xs, ys, zs, view, NULL, jitco[tot], NULL, NULL);
+                               tot++;
+                       }
+               }
+
+               *totjitco= tot;
+       }
+       else {
+               VECCOPY(jitco[0], shi->co);
+               *totjitco= 1;
+       }
+}
 
 static void ray_shadow_qmc(ShadeInput *shi, LampRen *lar, float *lampco, float *shadfac, Isect *isec)
 {
        QMCSampler *qsa=NULL;
-       QMCSampler *qsa_jit=NULL;
        int samples=0;
-       float samp3d[3], jit[3], jitbias= 0.0f;
+       float samp3d[3];
 
-       float fac=0.0f, vec[3];
+       float fac=0.0f, vec[3], end[3];
        float colsq[4];
        float adapt_thresh = lar->adapt_thresh;
-       int max_samples = lar->ray_totsamp;
-       float pos[3];
-       int do_soft=1, full_osa=0;
+       int min_adapt_samples=4, max_samples = lar->ray_totsamp;
+       float *co;
+       int do_soft=1, full_osa=0, i;
+
+       float min[3], max[3];
+       RayHint bb_hint;
+
+       float jitco[RE_MAX_OSA][3];
+       int totjitco;
 
        colsq[0] = colsq[1] = colsq[2] = 0.0;
        if(isec->mode==RE_RAY_SHADOW_TRA) {
@@ -1822,40 +2086,37 @@ static void ray_shadow_qmc(ShadeInput *shi, LampRen *lar, float *lampco, float *
                if (do_soft) max_samples = lar->ray_totsamp;
                else max_samples = (R.osa > 4)?R.osa:5;
        }
-
-       if(shi->vlr && ((shi->vlr->flag & R_FULL_OSA) == 0))
-               jitbias= 0.5f*(VecLength(shi->dxco) + VecLength(shi->dyco));
+       
+       ray_shadow_jittered_coords(shi, max_samples, jitco, &totjitco);
 
        /* sampling init */
-       if (lar->ray_samp_method==LA_SAMP_HALTON) {
+       if (lar->ray_samp_method==LA_SAMP_HALTON)
                qsa = get_thread_qmcsampler(&R, shi->thread, SAMP_TYPE_HALTON, max_samples);
-               qsa_jit = get_thread_qmcsampler(&R, shi->thread, SAMP_TYPE_HALTON, max_samples);
-       } else if (lar->ray_samp_method==LA_SAMP_HAMMERSLEY) {
+       else if (lar->ray_samp_method==LA_SAMP_HAMMERSLEY)
                qsa = get_thread_qmcsampler(&R, shi->thread, SAMP_TYPE_HAMMERSLEY, max_samples);
-               qsa_jit = get_thread_qmcsampler(&R, shi->thread, SAMP_TYPE_HAMMERSLEY, max_samples);
-       }
        
        QMC_initPixel(qsa, shi->thread);
-       QMC_initPixel(qsa_jit, shi->thread);
+
+       INIT_MINMAX(min, max);
+       for(i=0; i<totjitco; i++)
+       {
+               DO_MINMAX(jitco[i], min, max);
+       }
+       RE_rayobject_hint_bb( R.raytree, &bb_hint, min, max);
        
+       isec->hint = &bb_hint;
+       isec->skip = RE_SKIP_VLR_NEIGHBOUR;
        VECCOPY(vec, lampco);
        
-       
        while (samples < max_samples) {
-               isec->faceorig= (RayFace*)shi->vlr;
-               isec->oborig= RAY_OBJECT_SET(&R, shi->obi);
-               
+
+               isec->orig.ob   = shi->obi;
+               isec->orig.face = shi->vlr;
+
                /* manually jitter the start shading co-ord per sample
                 * based on the pre-generated OSA texture sampling offsets, 
                 * for anti-aliasing sharp shadow edges. */
-               VECCOPY(pos, shi->co);
-               if (shi->vlr && !full_osa) {
-                       QMC_sampleRect(jit, qsa_jit, shi->thread, samples, 1.0, 1.0);
-                       
-                       pos[0] += shi->dxco[0]*jit[0] + shi->dyco[0]*jit[1];
-                       pos[1] += shi->dxco[1]*jit[0] + shi->dyco[1]*jit[1];
-                       pos[2] += shi->dxco[2]*jit[0] + shi->dyco[2]*jit[1];
-               }
+               co = jitco[samples % totjitco];
 
                if (do_soft) {
                        /* sphere shadow source */
@@ -1863,9 +2124,9 @@ static void ray_shadow_qmc(ShadeInput *shi, LampRen *lar, float *lampco, float *
                                float ru[3], rv[3], v[3], s[3];
                                
                                /* calc tangent plane vectors */
-                               v[0] = pos[0] - lampco[0];
-                               v[1] = pos[1] - lampco[1];
-                               v[2] = pos[2] - lampco[2];
+                               v[0] = co[0] - lampco[0];
+                               v[1] = co[1] - lampco[1];
+                               v[2] = co[2] - lampco[2];
                                Normalize(v);
                                VecOrthoBasisf(v, ru, rv);
                                
@@ -1878,13 +2139,6 @@ static void ray_shadow_qmc(ShadeInput *shi, LampRen *lar, float *lampco, float *
                                s[2] = samp3d[0]*ru[2] + samp3d[1]*rv[2];
                                
                                VECCOPY(samp3d, s);
-
-                               if(jitbias != 0.0f) {
-                                       /* bias away somewhat to avoid self intersection */
-                                       pos[0] -= jitbias*v[0];
-                                       pos[1] -= jitbias*v[1];
-                                       pos[2] -= jitbias*v[2];
-                               }
                        }
                        else {
                                /* sampling, returns quasi-random vector in [sizex,sizey]^2 plane */
@@ -1893,34 +2147,38 @@ static void ray_shadow_qmc(ShadeInput *shi, LampRen *lar, float *lampco, float *
                                /* align samples to lamp vector */
                                Mat3MulVecfl(lar->mat, samp3d);
                        }
-                       isec->end[0]= vec[0]+samp3d[0];
-                       isec->end[1]= vec[1]+samp3d[1];
-                       isec->end[2]= vec[2]+samp3d[2];
+                       end[0] = vec[0]+samp3d[0];
+                       end[1] = vec[1]+samp3d[1];
+                       end[2] = vec[2]+samp3d[2];
                } else {
-                       VECCOPY(isec->end, vec);
+                       VECCOPY(end, vec);
                }
 
-               if(jitbias != 0.0f && !(do_soft && lar->type==LA_LOCAL)) {
+               if(shi->strand) {
                        /* bias away somewhat to avoid self intersection */
+                       float jitbias= 0.5f*(VecLength(shi->dxco) + VecLength(shi->dyco));
                        float v[3];
 
-                       VECSUB(v, pos, isec->end);
+                       VECSUB(v, co, end);
                        Normalize(v);
 
-                       pos[0] -= jitbias*v[0];
-                       pos[1] -= jitbias*v[1];
-                       pos[2] -= jitbias*v[2];
+                       co[0] -= jitbias*v[0];
+                       co[1] -= jitbias*v[1];
+                       co[2] -= jitbias*v[2];
                }
 
-               VECCOPY(isec->start, pos);
-               
+               VECCOPY(isec->start, co);
+               isec->vec[0] = end[0]-isec->start[0];
+               isec->vec[1] = end[1]-isec->start[1];
+               isec->vec[2] = end[2]-isec->start[2];
+               isec->labda = 1.0f; // * Normalize(isec->vec);
                
                /* trace the ray */
                if(isec->mode==RE_RAY_SHADOW_TRA) {
                        isec->col[0]= isec->col[1]= isec->col[2]=  1.0f;
                        isec->col[3]= 1.0f;
                        
-                       ray_trace_shadow_tra(isec, DEPTH_SHADOW_TRA, 0);
+                       ray_trace_shadow_tra(isec, shi, DEPTH_SHADOW_TRA, 0);
                        shadfac[0] += isec->col[0];
                        shadfac[1] += isec->col[1];
                        shadfac[2] += isec->col[2];
@@ -1932,7 +2190,7 @@ static void ray_shadow_qmc(ShadeInput *shi, LampRen *lar, float *lampco, float *
                        colsq[2] += isec->col[2]*isec->col[2];
                }
                else {
-                       if( RE_ray_tree_intersect(R.raytree, isec) ) fac+= 1.0f;
+                       if( RE_rayobject_raycast(R.raytree, isec) ) fac+= 1.0f;
                }
                
                samples++;
@@ -1940,7 +2198,7 @@ static void ray_shadow_qmc(ShadeInput *shi, LampRen *lar, float *lampco, float *
                if ((lar->ray_samp_method == LA_SAMP_HALTON)) {
                
                        /* adaptive sampling - consider samples below threshold as in shadow (or vice versa) and exit early */
-                       if ((max_samples > 4) && (adapt_thresh > 0.0) && (samples > max_samples / 3)) {
+                       if ((max_samples > min_adapt_samples) && (adapt_thresh > 0.0) && (samples > max_samples / 3)) {
                                if (isec->mode==RE_RAY_SHADOW_TRA) {
                                        if ((shadfac[3] / samples > (1.0-adapt_thresh)) || (shadfac[3] / samples < adapt_thresh))
                                                break;
@@ -1962,8 +2220,6 @@ static void ray_shadow_qmc(ShadeInput *shi, LampRen *lar, float *lampco, float *
        } else
                shadfac[3]= 1.0f-fac/samples;
 
-       if (qsa_jit)
-               release_thread_qmcsampler(&R, shi->thread, qsa_jit);
        if (qsa)
                release_thread_qmcsampler(&R, shi->thread, qsa);
 }
@@ -1974,6 +2230,7 @@ static void ray_shadow_jitter(ShadeInput *shi, LampRen *lar, float *lampco, floa
        float *jitlamp;
        float fac=0.0f, div=0.0f, vec[3];
        int a, j= -1, mask;
+       RayHint point_hint;
        
        if(isec->mode==RE_RAY_SHADOW_TRA) {
                shadfac[0]= shadfac[1]= shadfac[2]= shadfac[3]= 0.0f;
@@ -1990,6 +2247,12 @@ static void ray_shadow_jitter(ShadeInput *shi, LampRen *lar, float *lampco, floa
        if(a==4) mask |= (mask>>4)|(mask>>8);
        else if(a==9) mask |= (mask>>9);
        
+       VECCOPY(isec->start, shi->co);          
+       isec->orig.ob   = shi->obi;
+       isec->orig.face = shi->vlr;
+       RE_rayobject_hint_bb( R.raytree, &point_hint, isec->start, isec->start );
+       isec->hint = &point_hint;
+       
        while(a--) {
                
                if(R.r.mode & R_OSA) {
@@ -2001,32 +2264,30 @@ static void ray_shadow_jitter(ShadeInput *shi, LampRen *lar, float *lampco, floa
                        }
                }
                
-               isec->faceorig= (RayFace*)shi->vlr;
-               isec->oborig= RAY_OBJECT_SET(&R, shi->obi);
-               
                vec[0]= jitlamp[0];
                vec[1]= jitlamp[1];
                vec[2]= 0.0f;
                Mat3MulVecfl(lar->mat, vec);
                
-               /* set start and end, RE_ray_tree_intersect clips it */
-               VECCOPY(isec->start, shi->co);
-               isec->end[0]= lampco[0]+vec[0];
-               isec->end[1]= lampco[1]+vec[1];
-               isec->end[2]= lampco[2]+vec[2];
+               /* set start and vec */
+               isec->vec[0] = vec[0]+lampco[0]-isec->start[0];
+               isec->vec[1] = vec[1]+lampco[1]-isec->start[1];
+               isec->vec[2] = vec[2]+lampco[2]-isec->start[2];
+               isec->labda = 1.0f;
+               isec->skip = RE_SKIP_VLR_NEIGHBOUR;
                
                if(isec->mode==RE_RAY_SHADOW_TRA) {
                        /* isec.col is like shadfac, so defines amount of light (0.0 is full shadow) */
                        isec->col[0]= isec->col[1]= isec->col[2]=  1.0f;
                        isec->col[3]= 1.0f;
                        
-                       ray_trace_shadow_tra(isec, DEPTH_SHADOW_TRA, 0);
+                       ray_trace_shadow_tra(isec, shi, DEPTH_SHADOW_TRA, 0);
                        shadfac[0] += isec->col[0];
                        shadfac[1] += isec->col[1];
                        shadfac[2] += isec->col[2];
                        shadfac[3] += isec->col[3];
                }
-               else if( RE_ray_tree_intersect(R.raytree, isec) ) fac+= 1.0f;
+               else if( RE_rayobject_raycast(R.raytree, isec) ) fac+= 1.0f;
                
                div+= 1.0f;
                jitlamp+= 2;
@@ -2050,11 +2311,13 @@ static void ray_shadow_jitter(ShadeInput *shi, LampRen *lar, float *lampco, floa
 void ray_shadow(ShadeInput *shi, LampRen *lar, float *shadfac)
 {
        Isect isec;
-       float lampco[3], maxsize;
+       float lampco[3];
 
        /* setup isec */
+       RE_RC_INIT(isec, *shi);
        if(shi->mat->mode & MA_SHADOW_TRA) isec.mode= RE_RAY_SHADOW_TRA;
        else isec.mode= RE_RAY_SHADOW;
+       isec.hint = 0;
        
        if(lar->mode & (LA_LAYER|LA_LAYER_SHADOW))
                isec.lay= lar->lay;
@@ -2063,19 +2326,29 @@ void ray_shadow(ShadeInput *shi, LampRen *lar, float *shadfac)
 
        /* only when not mir tracing, first hit optimm */
        if(shi->depth==0) {
-               isec.face_last= (RayFace*)lar->vlr_last[shi->thread];
-               isec.ob_last= RAY_OBJECT_SET(&R, lar->obi_last[shi->thread]);
+               isec.last_hit = lar->last_hit[shi->thread];
        }
        else {
-               isec.face_last= NULL;
-               isec.ob_last= 0;
+               isec.last_hit = NULL;
        }
        
        if(lar->type==LA_SUN || lar->type==LA_HEMI) {
-               maxsize= RE_ray_tree_max_size(R.raytree);
-               lampco[0]= shi->co[0] - maxsize*lar->vec[0];
-               lampco[1]= shi->co[1] - maxsize*lar->vec[1];
-               lampco[2]= shi->co[2] - maxsize*lar->vec[2];
+               /* jitter and QMC sampling add a displace vector to the lamp position
+                * that's incorrect because a SUN lamp does not has an exact position
+                * and the displace should be done at the ray vector instead of the
+                * lamp position.
+                * This is easily verified by noticing that shadows of SUN lights change
+                * with the scene BB.
+                * 
+                * This was detected during SoC 2009 - Raytrace Optimization, but to keep
+                * consistency with older render code it wasn't removed.
+                * 
+                * If the render code goes through some recode/serious bug-fix then this
+                * is something to consider!
+                */
+               lampco[0]= shi->co[0] - R.maxdist*lar->vec[0];
+               lampco[1]= shi->co[1] - R.maxdist*lar->vec[1];
+               lampco[2]= shi->co[2] - R.maxdist*lar->vec[2];
        }
        else {
                VECCOPY(lampco, lar->co);
@@ -2088,23 +2361,26 @@ void ray_shadow(ShadeInput *shi, LampRen *lar, float *shadfac)
        } else {
                if(lar->ray_totsamp<2) {
                        
-                       isec.faceorig= (RayFace*)shi->vlr;
-                       isec.oborig= RAY_OBJECT_SET(&R, shi->obi);
+                       isec.orig.ob   = shi->obi;
+                       isec.orig.face = shi->vlr;
+                       
                        shadfac[3]= 1.0f; // 1.0=full light
                        
                        /* set up isec vec */
                        VECCOPY(isec.start, shi->co);
-                       VECCOPY(isec.end, lampco);
+                       VECSUB(isec.vec, lampco, isec.start);
+                       isec.labda = 1.0f;
 
                        if(isec.mode==RE_RAY_SHADOW_TRA) {
                                /* isec.col is like shadfac, so defines amount of light (0.0 is full shadow) */
                                isec.col[0]= isec.col[1]= isec.col[2]=  1.0f;
                                isec.col[3]= 1.0f;
 
-                               ray_trace_shadow_tra(&isec, DEPTH_SHADOW_TRA, 0);
+                               ray_trace_shadow_tra(&isec, shi, DEPTH_SHADOW_TRA, 0);
                                QUATCOPY(shadfac, isec.col);
                        }
-                       else if(RE_ray_tree_intersect(R.raytree, &isec)) shadfac[3]= 0.0f;
+                       else if(RE_rayobject_raycast(R.raytree, &isec))
+                               shadfac[3]= 0.0f;
                }
                else {
                        ray_shadow_jitter(shi, lar, lampco, shadfac, &isec);
@@ -2113,41 +2389,44 @@ void ray_shadow(ShadeInput *shi, LampRen *lar, float *shadfac)
                
        /* for first hit optim, set last interesected shadow face */
        if(shi->depth==0) {
-               lar->vlr_last[shi->thread]= (VlakRen*)isec.face_last;
-               lar->obi_last[shi->thread]= RAY_OBJECT_GET(&R, isec.ob_last);
+               lar->last_hit[shi->thread] = isec.last_hit;
        }
 
 }
 
+#if 0
 /* only when face points away from lamp, in direction of lamp, trace ray and find first exit point */
-void ray_translucent(ShadeInput *shi, LampRen *lar, float *distfac, float *co)
+static void ray_translucent(ShadeInput *shi, LampRen *lar, float *distfac, float *co)
 {
        Isect isec;
-       float lampco[3], maxsize;
+       float lampco[3];
+       
+       assert(0);
        
        /* setup isec */
+       RE_RC_INIT(isec, *shi);
        isec.mode= RE_RAY_SHADOW_TRA;
+       isec.hint = 0;
        
        if(lar->mode & LA_LAYER) isec.lay= lar->lay; else isec.lay= -1;
        
        if(lar->type==LA_SUN || lar->type==LA_HEMI) {
-               maxsize= RE_ray_tree_max_size(R.raytree);
-               lampco[0]= shi->co[0] - maxsize*lar->vec[0];
-               lampco[1]= shi->co[1] - maxsize*lar->vec[1];
-               lampco[2]= shi->co[2] - maxsize*lar->vec[2];
+               lampco[0]= shi->co[0] - RE_RAYTRACE_MAXDIST*lar->vec[0];
+               lampco[1]= shi->co[1] - RE_RAYTRACE_MAXDIST*lar->vec[1];
+               lampco[2]= shi->co[2] - RE_RAYTRACE_MAXDIST*lar->vec[2];
        }
        else {
                VECCOPY(lampco, lar->co);
        }
        
-       isec.faceorig= (RayFace*)shi->vlr;
-       isec.oborig= RAY_OBJECT_SET(&R, shi->obi);
+       isec.orig.ob   = shi->obi;
+       isec.orig.face = shi->vlr;
        
        /* set up isec vec */
        VECCOPY(isec.start, shi->co);
        VECCOPY(isec.end, lampco);
        
-       if(RE_ray_tree_intersect(R.raytree, &isec)) {
+       if(RE_rayobject_raycast(R.raytree, &isec)) {
                /* we got a face */
                
                /* render co */
@@ -2161,4 +2440,5 @@ void ray_translucent(ShadeInput *shi, LampRen *lar, float *distfac, float *co)
                *distfac= 0.0f;
 }
 
+#endif