svn merge -r 21508:22111 https://svn.blender.org/svnroot/bf-blender/branches/blender2...
[blender.git] / source / blender / render / intern / source / rayshade.c
index 010930fcb85d858e0e9ae928cf55c883c9c3ddb2..f6ba45308a5dc5e17c64991dc3d0ce5b289b067e 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,297 @@ 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;
+       int v;
+       ObjectRen *obr = obi->obr;
 
-       INIT_MINMAX(min, max);
-
-       /* 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->material_type != MA_TYPE_WIRE) {
-                                       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))
+                       {
+                               face->v1 = vlr->v1->co;
+                               face->v2 = vlr->v2->co;
+                               face->v3 = vlr->v3->co;
+                               face->v4 = vlr->v4 ? vlr->v4->co : NULL;
+                               
+                               face->ob   = obi;
+                               face->face = 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(re->tbh))
-                                       break;
-                               if(time-lasttime>1.0f) {
-                                       char str[32];
-                                       sprintf(str, "Filling Octree: %d", totv);
-                                       re->i.infostr= str;
-                                       re->stats_draw(re->sdh, &re->i);
-                                       re->i.infostr= NULL;
-                                       lasttime= time;
-                               }
-                       }
-                       else vlr++;
-                       
-                       if((re->flag & R_BAKE_TRACE) || (vlr->mat->mode & MA_TRACEBLE))
-                               if(vlr->mat->material_type != MA_TYPE_WIRE)
-                                       RE_ray_tree_add_face(re->raytree, RAY_OBJECT_SET(re, obi), vlr);
-               }
-       }
+       //Count number of objects
+       for(obi=re->instancetable.first; obi; obi=obi->next)
+       if(is_raytraceable(re, obi))
+               num_objects++;
 
-       RE_ray_tree_done(re->raytree);
+       //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++;
+               
+               assert((obi->flag & R_TRANSFORMED) == 0); //Not suported
+       
+               for(v=0;v<obr->totvlak;v++)
+               {
+                       VlakRen *vlr = obr->vlaknodes[v>>8].vlak + (v&255);
+                       if(is_raytraceable_vlr(re, vlr))
+                               faces++;
+               }
+       }
+       
+       //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 );
+
+       face    = re->rayfaces  = (RayFace*)MEM_callocN(faces*sizeof(RayFace), "Render ray faces");
+       
+       for(obi=re->instancetable.first; obi; obi=obi->next)
+       if(is_raytraceable(re, obi))
+       {
+               int v;
+               ObjectRen *obr = obi->obr;
+
+               for(v=0;v<obr->totvlak;v++)
+               {
+                       VlakRen *vlr = obr->vlaknodes[v>>8].vlak + (v&255);
+                       face->v1 = vlr->v1->co;
+                       face->v2 = vlr->v2->co;
+                       face->v3 = vlr->v3->co;
+                       face->v4 = vlr->v4 ? vlr->v4->co : NULL;
+                       
+                       face->ob   = obi;
+                       face->face = 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)";
+
+#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 */
@@ -421,7 +610,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,
@@ -430,20 +619,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;
@@ -1185,7 +1371,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);
-
        
        /* raytrace mirror amd refract like to separate the spec color */
        if(shi->combinedflag & SCE_PASS_SPEC)
@@ -1280,8 +1465,8 @@ static void ray_trace_shadow_tra(Isect *is, ShadeInput *origshi, int depth, int
           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 */
                
@@ -1312,8 +1497,9 @@ static void ray_trace_shadow_tra(Isect *is, ShadeInput *origshi, int depth, int
                        
                        /* adapt isect struct */
                        VECCOPY(is->start, shi.co);
-                       is->oborig= RAY_OBJECT_SET(&R, shi.obi);
-                       is->faceorig= (RayFace*)shi.vlr;
+
+                       is->orig.ob   = shi.obi;
+                       is->orig.face = shi.vlr;
 
                        ray_trace_shadow_tra(is, origshi, depth-1, traflag | RAY_TRA);
                }
@@ -1329,9 +1515,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;
        }
@@ -1339,8 +1527,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++) {
                
@@ -1352,12 +1545,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,
@@ -1530,6 +1722,7 @@ static float *sphere_sampler(int type, int resol, int thread, int xs, int ys)
 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];
@@ -1545,13 +1738,25 @@ static 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) */
@@ -1589,6 +1794,7 @@ static 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 */
@@ -1600,14 +1806,14 @@ static 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;
                }
@@ -1667,18 +1873,29 @@ static void ray_ao_qmc(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;
 
@@ -1725,14 +1942,14 @@ static 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;
                        }
@@ -1838,12 +2055,15 @@ static void ray_shadow_qmc(ShadeInput *shi, LampRen *lar, float *lampco, float *
        int samples=0;
        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 min_adapt_samples=4, max_samples = lar->ray_totsamp;
        float *co;
-       int do_soft=1, full_osa=0;
+       int do_soft=1, full_osa=0, i;
+
+       float min[3], max[3];
+       RayHint bb_hint;
 
        float jitco[RE_MAX_OSA][3];
        int totjitco;
@@ -1874,13 +2094,22 @@ static void ray_shadow_qmc(ShadeInput *shi, LampRen *lar, float *lampco, float *
                qsa = get_thread_qmcsampler(&R, shi->thread, SAMP_TYPE_HAMMERSLEY, max_samples);
        
        QMC_initPixel(qsa, 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, 
@@ -1916,11 +2145,11 @@ 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(shi->strand) {
@@ -1928,7 +2157,7 @@ static void ray_shadow_qmc(ShadeInput *shi, LampRen *lar, float *lampco, float *
                        float jitbias= 0.5f*(VecLength(shi->dxco) + VecLength(shi->dyco));
                        float v[3];
 
-                       VECSUB(v, co, isec->end);
+                       VECSUB(v, co, end);
                        Normalize(v);
 
                        co[0] -= jitbias*v[0];
@@ -1937,6 +2166,10 @@ static void ray_shadow_qmc(ShadeInput *shi, LampRen *lar, float *lampco, float *
                }
 
                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) {
@@ -1955,7 +2188,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++;
@@ -1995,6 +2228,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;
@@ -2011,6 +2245,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) {
@@ -2022,19 +2262,17 @@ 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) */
@@ -2047,7 +2285,7 @@ static void ray_shadow_jitter(ShadeInput *shi, LampRen *lar, float *lampco, floa
                        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;
@@ -2071,11 +2309,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;
@@ -2084,19 +2324,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);
@@ -2109,13 +2359,15 @@ 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) */
@@ -2125,7 +2377,8 @@ void ray_shadow(ShadeInput *shi, LampRen *lar, float *shadfac)
                                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);
@@ -2134,8 +2387,7 @@ 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;
        }
 
 }
@@ -2145,31 +2397,34 @@ void ray_shadow(ShadeInput *shi, LampRen *lar, float *shadfac)
 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 */