doxygen: prevent GPL license block from being parsed as doxygen comment.
[blender.git] / source / blender / render / intern / source / rendercore.c
index 6b6a736..2901573 100644 (file)
@@ -1,4 +1,4 @@
-/**
+/*
  * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
@@ -15,7 +15,7 @@
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  *
  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
  * All rights reserved.
 #include <math.h>
 #include <float.h>
 #include <string.h>
+#include <assert.h>
 
 /* External modules: */
 #include "MEM_guardedalloc.h"
 
-#include "BLI_arithb.h"
+#include "BLI_math.h"
 #include "BLI_blenlib.h"
 #include "BLI_jitter.h"
 #include "BLI_rand.h"
 #include "BLI_threads.h"
+#include "BLI_utildefines.h"
+
 
-#include "BKE_utildefines.h"
 
 #include "DNA_image_types.h"
 #include "DNA_lamp_types.h"
@@ -59,6 +61,8 @@
 #include "IMB_imbuf.h"
 
 /* local include */
+#include "rayintersection.h"
+#include "rayobject.h"
 #include "renderpipeline.h"
 #include "render_types.h"
 #include "renderdatabase.h"
@@ -69,7 +73,6 @@
 #include "shading.h"
 #include "sss.h"
 #include "zbuf.h"
-#include "RE_raytrace.h"
 
 #include "PIL_time.h"
 
@@ -95,8 +98,9 @@ void calc_view_vector(float *view, float x, float y)
        }
        else {
                
-               if(R.r.mode & R_PANORAMA)
+               if(R.r.mode & R_PANORAMA) {
                        x-= R.panodxp;
+               }
                
                /* move x and y to real viewplane coords */
                x= (x/(float)R.winx);
@@ -314,7 +318,7 @@ static void halo_tile(RenderPart *pa, RenderLayer *rl)
                                }
                        }
                }
-               if(R.test_break() ) break; 
+               if(R.test_break(R.tbh) ) break; 
        }
 }
 
@@ -430,7 +434,7 @@ static void lamphalo_tile(RenderPart *pa, RenderLayer *rl)
                        if(rd) rd++;
                }
                if(y&1)
-                       if(R.test_break()) break; 
+                       if(R.test_break(R.tbh)) break; 
        }
 }                              
 
@@ -458,6 +462,9 @@ static void add_filt_passes(RenderLayer *rl, int curmask, int rectx, int offset,
                                col= shr->col;
                                pixsize= 4;
                                break;
+                       case SCE_PASS_EMIT:
+                               col= shr->emit;
+                               break;
                        case SCE_PASS_DIFFUSE:
                                col= shr->diff;
                                break;
@@ -470,15 +477,18 @@ static void add_filt_passes(RenderLayer *rl, int curmask, int rectx, int offset,
                        case SCE_PASS_AO:
                                col= shr->ao;
                                break;
+                       case SCE_PASS_ENVIRONMENT:
+                               col= shr->env;
+                               break;
+                       case SCE_PASS_INDIRECT:
+                               col= shr->indirect;
+                               break;
                        case SCE_PASS_REFLECT:
                                col= shr->refl;
                                break;
                        case SCE_PASS_REFRACT:
                                col= shr->refr;
                                break;
-                       case SCE_PASS_RADIO:
-                               col= shr->rad;
-                               break;
                        case SCE_PASS_NORMAL:
                                col= shr->nor;
                                break;
@@ -520,6 +530,12 @@ static void add_filt_passes(RenderLayer *rl, int curmask, int rectx, int offset,
                                }
                        }
                                break;
+
+                       case SCE_PASS_RAYHITS:
+                               /*  */
+                               col= shr->rayhits;
+                               pixsize= 4;
+                               break;
                }
                if(col) {
                        fp= rpass->rect + pixsize*offset;
@@ -550,6 +566,9 @@ static void add_passes(RenderLayer *rl, int offset, ShadeInput *shi, ShadeResult
                                col= shr->col;
                                pixsize= 4;
                                break;
+                       case SCE_PASS_EMIT:
+                               col= shr->emit;
+                               break;
                        case SCE_PASS_DIFFUSE:
                                col= shr->diff;
                                break;
@@ -562,15 +581,18 @@ static void add_passes(RenderLayer *rl, int offset, ShadeInput *shi, ShadeResult
                        case SCE_PASS_AO:
                                col= shr->ao;
                                break;
+                       case SCE_PASS_ENVIRONMENT:
+                               col= shr->env;
+                               break;
+                       case SCE_PASS_INDIRECT:
+                               col= shr->indirect;
+                               break;
                        case SCE_PASS_REFLECT:
                                col= shr->refl;
                                break;
                        case SCE_PASS_REFRACT:
                                col= shr->refr;
                                break;
-                       case SCE_PASS_RADIO:
-                               col= shr->rad;
-                               break;
                        case SCE_PASS_NORMAL:
                                col= shr->nor;
                                break;
@@ -596,6 +618,10 @@ static void add_passes(RenderLayer *rl, int offset, ShadeInput *shi, ShadeResult
                                fp= rpass->rect + offset;
                                *fp= shr->mist;
                                break;
+                       case SCE_PASS_RAYHITS:
+                               col= shr->rayhits;
+                               pixsize= 4;
+                               break;
                }
                if(col) {
                        fp= rpass->rect + pixsize*offset;
@@ -662,7 +688,7 @@ static void sky_tile(RenderPart *pa, RenderLayer *rl)
                }
                
                if(y&1)
-                       if(R.test_break()) break; 
+                       if(R.test_break(R.tbh)) break; 
        }
 }
 
@@ -703,7 +729,7 @@ static void atm_tile(RenderPart *pa, RenderLayer *rl)
                        for(sample=0; sample<totsample; sample++) {
                                float *zrect= RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_Z) + od;
                                float *rgbrect = rlpp[sample]->rectf + 4*od;
-                               float rgb[3];
+                               float rgb[3] = {0};
                                int done= 0;
                                
                                for(go=R.lights.first; go; go= go->next) {
@@ -716,10 +742,15 @@ static void atm_tile(RenderPart *pa, RenderLayer *rl)
                                                if(*zrect >= 9.9e10 || rgbrect[3]==0.0f) {
                                                        continue;
                                                }
-                                               
+                                                                                               
                                                if((lar->sunsky->effect_type & LA_SUN_EFFECT_AP)) {     
                                                        float tmp_rgb[3];
                                                        
+                                                       /* skip if worldspace lamp vector is below horizon */
+                                                       if(go->ob->obmat[2][2] < 0.f) {
+                                                               continue;
+                                                       }
+                                                       
                                                        VECCOPY(tmp_rgb, rgbrect);
                                                        if(rgbrect[3]!=1.0f) {  /* de-premul */
                                                                float div= 1.0f/rgbrect[3];
@@ -760,7 +791,7 @@ static void shadeDA_tile(RenderPart *pa, RenderLayer *rl)
        int samp;
        int x, y, seed, crop=0, offs=0, od;
        
-       if(R.test_break()) return; 
+       if(R.test_break(R.tbh)) return; 
        
        /* irregular shadowb buffer creation */
        if(R.r.mode & R_SHADOW)
@@ -821,7 +852,7 @@ static void shadeDA_tile(RenderPart *pa, RenderLayer *rl)
                rectdaps+= pa->rectx;
                offs+= pa->rectx;
                
-               if(y&1) if(R.test_break()) break; 
+               if(y&1) if(R.test_break(R.tbh)) break; 
        }
        
        /* disable scanline updating */
@@ -1005,7 +1036,7 @@ void edge_enhance_tile(RenderPart *pa, float *rectf, int *rectz)
 static void reset_sky_speed(RenderPart *pa, RenderLayer *rl)
 {
        /* for all pixels with max speed, set to zero */
-    RenderLayer *rlpp[RE_MAX_OSA];
+       RenderLayer *rlpp[RE_MAX_OSA];
        float *fp;
        int a, sample, totsample;
        
@@ -1022,9 +1053,9 @@ static void reset_sky_speed(RenderPart *pa, RenderLayer *rl)
 
 static unsigned short *make_solid_mask(RenderPart *pa)
 { 
-       intptr_t *rd= pa->rectdaps;
-       unsigned short *solidmask, *sp;
-       int x;
+        intptr_t *rd= pa->rectdaps;
+        unsigned short *solidmask, *sp;
+        int x;
        
        if(rd==NULL) return NULL;
        
@@ -1069,7 +1100,7 @@ static void addAlphaOverFloatMask(float *dest, float *source, unsigned short dma
                dest[3]+= source[3];
                
                return;
-       }
+        }
 
        dest[0]= (mul*dest[0]) + source[0];
        dest[1]= (mul*dest[1]) + source[1];
@@ -1142,7 +1173,7 @@ void zbufshadeDA_tile(RenderPart *pa)
                        sdata.psmlist= &psmlist;
                        sdata.edgerect= edgerect;
                        zbuffer_solid(pa, rl, make_pixelstructs, &sdata);
-                       if(R.test_break()) break; 
+                       if(R.test_break(R.tbh)) break; 
                }
                
                /* shades solid */
@@ -1280,7 +1311,7 @@ void zbufshade_tile(RenderPart *pa)
                
                zbuffer_solid(pa, rl, NULL, NULL);
                
-               if(!R.test_break()) {   /* NOTE: this if() is not consistant */
+               if(!R.test_break(R.tbh)) {      /* NOTE: this if() is not consistent */
                        
                        /* edges only for solid part, ztransp doesn't support it yet anti-aliased */
                        if(rl->layflag & SCE_LAY_EDGE) {
@@ -1325,7 +1356,7 @@ void zbufshade_tile(RenderPart *pa)
                                                }
                                        }
                                        if(y&1)
-                                               if(R.test_break()) break; 
+                                               if(R.test_break(R.tbh)) break; 
                                }
                                
                                if(R.occlusiontree)
@@ -1377,7 +1408,7 @@ void zbufshade_tile(RenderPart *pa)
                if(rl->layflag & SCE_LAY_SKY)
                        sky_tile(pa, rl);
                
-               if(!R.test_break()) {
+               if(!R.test_break(R.tbh)) {
                        if(rl->layflag & SCE_LAY_EDGE) 
                                if(R.r.mode & R_EDGE)
                                        edge_enhance_add(pa, rl->rectf, edgerect);
@@ -1487,13 +1518,13 @@ static void shade_sample_sss(ShadeSample *ssamp, Material *mat, ObjectInstanceRe
 
        VECCOPY(nor, shi->facenor);
        calc_view_vector(shi->facenor, sx, sy);
-       Normalize(shi->facenor);
+       normalize_v3(shi->facenor);
        shade_input_set_viewco(shi, x, y, sx, sy, z);
-       orthoarea= VecLength(shi->dxco)*VecLength(shi->dyco);
+       orthoarea= len_v3(shi->dxco)*len_v3(shi->dyco);
 
        VECCOPY(shi->facenor, nor);
        shade_input_set_viewco(shi, x, y, sx, sy, z);
-       *area= VecLength(shi->dxco)*VecLength(shi->dyco);
+       *area= len_v3(shi->dxco)*len_v3(shi->dyco);
        *area= MIN2(*area, 2.0f*orthoarea);
 
        shade_input_set_uv(shi);
@@ -1505,8 +1536,8 @@ static void shade_sample_sss(ShadeSample *ssamp, Material *mat, ObjectInstanceRe
 
        /* not a pretty solution, but fixes common cases */
        if(shi->obr->ob && shi->obr->ob->transflag & OB_NEG_SCALE) {
-               VecNegf(shi->vn);
-               VecNegf(shi->vno);
+               negate_v3(shi->vn);
+               negate_v3(shi->vno);
        }
 
        /* if nodetree, use the material that we are currently preprocessing
@@ -1515,9 +1546,7 @@ static void shade_sample_sss(ShadeSample *ssamp, Material *mat, ObjectInstanceRe
                shi->mat= mat;
 
        /* init material vars */
-       // note, keep this synced with render_types.h
-       memcpy(&shi->r, &shi->mat->r, 23*sizeof(float));
-       shi->har= shi->mat->har;
+       shade_input_init_material(shi);
        
        /* render */
        shade_input_set_shade_texco(shi);
@@ -1717,7 +1746,7 @@ void zbufshade_sss_tile(RenderPart *pa)
                }
 
                if(y&1)
-                       if(re->test_break()) break; 
+                       if(re->test_break(re->tbh)) break; 
        }
 
        /* note: after adding we do not free these arrays, sss keeps them */
@@ -1797,7 +1826,7 @@ static void renderhalo_post(RenderResult *rr, float *rectf, HaloRen *har) /* pos
        
                                rectft+= 4*rr->rectx;
                                
-                               if(R.test_break()) break; 
+                               if(R.test_break(R.tbh)) break; 
                        }
                }
        }
@@ -1915,7 +1944,7 @@ void add_halo_flare(Render *re)
        if(do_draw) {
                /* weak... the display callback wants an active renderlayer pointer... */
                rr->renlay= rl;
-               re->display_draw(rr, NULL);
+               re->display_draw(re->ddh, rr, NULL);
        }
        
        R.r.mode= mode; 
@@ -1950,10 +1979,7 @@ void RE_shade_external(Render *re, ShadeInput *shi, ShadeResult *shr)
        if(shi->mat->nodetree && shi->mat->use_nodes)
                ntreeShaderExecTree(shi->mat->nodetree, shi, shr);
        else {
-               /* copy all relevant material vars, note, keep this synced with render_types.h */
-               memcpy(&shi->r, &shi->mat->r, 23*sizeof(float));
-               shi->har= shi->mat->har;
-               
+               shade_input_init_material(shi);
                shade_material_loop(shi, shr);
        }
 }
@@ -1982,6 +2008,8 @@ typedef struct BakeShade {
        char *rect_mask; /* bake pixel mask */
 
        float dxco[3], dyco[3];
+
+       short *do_update;
 } BakeShade;
 
 /* bake uses a char mask to know what has been baked */
@@ -2054,24 +2082,10 @@ static void bake_mask_clear( ImBuf *ibuf, char *mask, char val )
 
 static void bake_set_shade_input(ObjectInstanceRen *obi, VlakRen *vlr, ShadeInput *shi, int quad, int isect, int x, int y, float u, float v)
 {
-       if(isect) {
-               /* raytrace intersection with different u,v than scanconvert */
-               if(vlr->v4) {
-                       if(quad)
-                               shade_input_set_triangle_i(shi, obi, vlr, 2, 1, 3);
-                       else
-                               shade_input_set_triangle_i(shi, obi, vlr, 0, 1, 3);
-               }
-               else
-                       shade_input_set_triangle_i(shi, obi, vlr, 0, 1, 2);
-       }
-       else {
-               /* regular scanconvert */
-               if(quad) 
-                       shade_input_set_triangle_i(shi, obi, vlr, 0, 2, 3);
-               else
-                       shade_input_set_triangle_i(shi, obi, vlr, 0, 1, 2);
-       }
+       if(quad) 
+               shade_input_set_triangle_i(shi, obi, vlr, 0, 2, 3);
+       else
+               shade_input_set_triangle_i(shi, obi, vlr, 0, 1, 2);
                
        /* cache for shadow */
        shi->samplenr= R.shadowsamplenr[shi->thread]++;
@@ -2104,17 +2118,18 @@ static void bake_shade(void *handle, Object *ob, ShadeInput *shi, int quad, int
        ShadeResult shr;
        VlakRen *vlr= shi->vlr;
        
-       /* init material vars */
-       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);
        
        if(bs->type==RE_BAKE_AO) {
                ambient_occlusion(shi);
 
-               if(R.r.bake_flag & R_BAKE_NORMALIZE)
-                       VECCOPY(shr.combined, shi->ao)
-               else
-                       ambient_occlusion_to_diffuse(shi, shr.combined);
+               if(R.r.bake_flag & R_BAKE_NORMALIZE) {
+                       copy_v3_v3(shr.combined, shi->ao);
+               }
+               else {
+                       zero_v3(shr.combined);
+                       environment_lighting_apply(shi, &shr);
+               }
        }
        else {
                if (bs->type==RE_BAKE_SHADOW) /* Why do shadows set the color anyhow?, ignore material color for baking */
@@ -2144,24 +2159,26 @@ static void bake_shade(void *handle, Object *ob, ShadeInput *shi, int quad, int
                                /* bitangent */
                                if(tvn && ttang) {
                                        VECCOPY(mat[0], ttang);
-                                       Crossf(mat[1], tvn, ttang);
+                                       cross_v3_v3v3(mat[1], tvn, ttang);
+                                       mul_v3_fl(mat[1], ttang[3]);
                                        VECCOPY(mat[2], tvn);
                                }
                                else {
                                        VECCOPY(mat[0], shi->nmaptang);
-                                       Crossf(mat[1], shi->vn, shi->nmaptang);
-                                       VECCOPY(mat[2], shi->vn);
+                                       cross_v3_v3v3(mat[1], shi->nmapnorm, shi->nmaptang);
+                                       mul_v3_fl(mat[1], shi->nmaptang[3]);
+                                       VECCOPY(mat[2], shi->nmapnorm);
                                }
 
-                               Mat3Inv(imat, mat);
-                               Mat3MulVecfl(imat, nor);
+                               invert_m3_m3(imat, mat);
+                               mul_m3_v3(imat, nor);
                        }
                        else if(R.r.bake_normal_space == R_BAKE_SPACE_OBJECT)
-                               Mat4Mul3Vecfl(ob->imat, nor); /* ob->imat includes viewinv! */
+                               mul_mat3_m4_v3(ob->imat, nor); /* ob->imat includes viewinv! */
                        else if(R.r.bake_normal_space == R_BAKE_SPACE_WORLD)
-                               Mat4Mul3Vecfl(R.viewinv, nor);
+                               mul_mat3_m4_v3(R.viewinv, nor);
 
-                       Normalize(nor); /* in case object has scaling */
+                       normalize_v3(nor); /* in case object has scaling */
 
                        shr.combined[0]= nor[0]/2.0f + 0.5f;
                        shr.combined[1]= 0.5f - nor[1]/2.0f;
@@ -2190,12 +2207,23 @@ static void bake_shade(void *handle, Object *ob, ShadeInput *shi, int quad, int
        }
        else {
                char *col= (char *)(bs->rect + bs->rectx*y + x);
-               col[0]= FTOCHAR(shr.combined[0]);
-               col[1]= FTOCHAR(shr.combined[1]);
-               col[2]= FTOCHAR(shr.combined[2]);
-               
+
+               if (ELEM(bs->type, RE_BAKE_ALL, RE_BAKE_TEXTURE) &&     (R.r.color_mgt_flag & R_COLOR_MANAGEMENT)) {
+                       float srgb[3];
+                       srgb[0]= linearrgb_to_srgb(shr.combined[0]);
+                       srgb[1]= linearrgb_to_srgb(shr.combined[1]);
+                       srgb[2]= linearrgb_to_srgb(shr.combined[2]);
+                       
+                       col[0]= FTOCHAR(srgb[0]);
+                       col[1]= FTOCHAR(srgb[1]);
+                       col[2]= FTOCHAR(srgb[2]);
+               } else {
+                       col[0]= FTOCHAR(shr.combined[0]);
+                       col[1]= FTOCHAR(shr.combined[1]);
+                       col[2]= FTOCHAR(shr.combined[2]);
+               }
                
-               if (bs->type==RE_BAKE_ALL || bs->type==RE_BAKE_TEXTURE) {
+               if (ELEM(bs->type, RE_BAKE_ALL, RE_BAKE_TEXTURE)) {
                        col[3]= FTOCHAR(shr.alpha);
                } else {
                        col[3]= 255;
@@ -2234,17 +2262,7 @@ static void bake_displacement(void *handle, ShadeInput *shi, float dist, int x,
        }
 }
 
-static int bake_check_intersect(Isect *is, int ob, RayFace *face)
-{
-       BakeShade *bs = (BakeShade*)is->userdata;
-       
-       /* no direction checking for now, doesn't always improve the result
-        * (INPR(shi->facenor, bs->dir) > 0.0f); */
-
-       return (R.objectinstance[ob & ~RE_RAY_TRANSFORM_OFFS].obr->ob != bs->actob);
-}
-
-static int bake_intersect_tree(RayTree* raytree, Isect* isect, float *start, float *dir, float sign, float *hitco, float *dist)
+static int bake_intersect_tree(RayObject* raytree, Isect* isect, float *start, float *dir, float sign, float *hitco, float *dist)
 {
        float maxdist;
        int hit;
@@ -2253,21 +2271,24 @@ static int bake_intersect_tree(RayTree* raytree, Isect* isect, float *start, flo
        if(R.r.bake_maxdist > 0.0f)
                maxdist= R.r.bake_maxdist;
        else
-               maxdist= RE_ray_tree_max_size(R.raytree) + R.r.bake_biasdist;
+               maxdist= RE_RAYTRACE_MAXDIST + R.r.bake_biasdist;
        
-       VECADDFAC(isect->start, start, dir, -R.r.bake_biasdist);
+       /* 'dir' is always normalized */
+       VECADDFAC(isect->start, start, dir, -R.r.bake_biasdist);                                        
+
+       isect->dir[0] = dir[0]*sign;
+       isect->dir[1] = dir[1]*sign;
+       isect->dir[2] = dir[2]*sign;
 
-       isect->end[0] = isect->start[0] + dir[0]*maxdist*sign;
-       isect->end[1] = isect->start[1] + dir[1]*maxdist*sign;
-       isect->end[2] = isect->start[2] + dir[2]*maxdist*sign;
+       isect->dist = maxdist;
 
-       hit = RE_ray_tree_intersect_check(R.raytree, isect, bake_check_intersect);
+       hit = RE_rayobject_raycast(raytree, isect);
        if(hit) {
-               hitco[0] = isect->start[0] + isect->labda*isect->vec[0];
-               hitco[1] = isect->start[1] + isect->labda*isect->vec[1];
-               hitco[2] = isect->start[2] + isect->labda*isect->vec[2];
+               hitco[0] = isect->start[0] + isect->dist*isect->dir[0];
+               hitco[1] = isect->start[1] + isect->dist*isect->dir[1];
+               hitco[2] = isect->start[2] + isect->dist*isect->dir[2];
 
-               *dist= VecLenf(start, hitco);
+               *dist= isect->dist;
        }
 
        return hit;
@@ -2317,8 +2338,8 @@ static void bake_set_vlr_dxyco(BakeShade *bs, float *uv1, float *uv2, float *uv3
        }
 
        if(bs->obi->flag & R_TRANSFORMED) {
-               Mat3MulVecfl(bs->obi->nmat, bs->dxco);
-               Mat3MulVecfl(bs->obi->nmat, bs->dyco);
+               mul_m3_v3(bs->obi->nmat, bs->dxco);
+               mul_m3_v3(bs->obi->nmat, bs->dyco);
        }
 }
 
@@ -2328,13 +2349,13 @@ static void do_bake_shade(void *handle, int x, int y, float u, float v)
        VlakRen *vlr= bs->vlr;
        ObjectInstanceRen *obi= bs->obi;
        Object *ob= obi->obr->ob;
-       float l, *v1, *v2, *v3, tvn[3], ttang[3];
+       float l, *v1, *v2, *v3, tvn[3], ttang[4];
        int quad;
        ShadeSample *ssamp= &bs->ssamp;
        ShadeInput *shi= ssamp->shi;
        
        /* fast threadsafe break test */
-       if(R.test_break())
+       if(R.test_break(R.tbh))
                return;
        
        /* setup render coordinates */
@@ -2357,7 +2378,7 @@ static void do_bake_shade(void *handle, int x, int y, float u, float v)
        shi->co[2]= l*v3[2]+u*v1[2]+v*v2[2];
        
        if(obi->flag & R_TRANSFORMED)
-               Mat4MulVecfl(obi->mat, shi->co);
+               mul_m4_v3(obi->mat, shi->co);
        
        VECCOPY(shi->dxco, bs->dxco);
        VECCOPY(shi->dyco, bs->dyco);
@@ -2367,8 +2388,8 @@ static void do_bake_shade(void *handle, int x, int y, float u, float v)
 
        if(bs->type==RE_BAKE_NORMALS && R.r.bake_normal_space==R_BAKE_SPACE_TANGENT) {
                shade_input_set_shade_texco(shi);
-               VECCOPY(tvn, shi->vn);
-               VECCOPY(ttang, shi->nmaptang);
+               VECCOPY(tvn, shi->nmapnorm);
+               QUATCOPY(ttang, shi->nmaptang);
        }
 
        /* if we are doing selected to active baking, find point on other face */
@@ -2387,12 +2408,15 @@ static void do_bake_shade(void *handle, int x, int y, float u, float v)
                for(sign=-1; sign<=1; sign+=2) {
                        memset(&isec, 0, sizeof(isec));
                        isec.mode= RE_RAY_MIRROR;
-                       isec.faceorig= (RayFace*)vlr;
-                       isec.oborig= RAY_OBJECT_SET(&R, obi);
-                       isec.userdata= bs;
+
+                       isec.orig.ob   = obi;
+                       isec.orig.face = vlr;
+                       isec.userdata= bs->actob;
+                       isec.check = RE_CHECK_VLR_BAKE;
+                       isec.skip = RE_SKIP_VLR_NEIGHBOUR;
                        
                        if(bake_intersect_tree(R.raytree, &isec, shi->co, shi->vn, sign, co, &dist)) {
-                               if(!hit || VecLenf(shi->co, co) < VecLenf(shi->co, minco)) {
+                               if(!hit || len_v3v3(shi->co, co) < len_v3v3(shi->co, minco)) {
                                        minisec= isec;
                                        mindist= dist;
                                        VECCOPY(minco, co);
@@ -2412,8 +2436,8 @@ static void do_bake_shade(void *handle, int x, int y, float u, float v)
 
                /* if hit, we shade from the new point, otherwise from point one starting face */
                if(hit) {
-                       vlr= (VlakRen*)minisec.face;
-                       obi= RAY_OBJECT_GET(&R, minisec.ob);
+                       obi= (ObjectInstanceRen*)minisec.hit.ob;
+                       vlr= (VlakRen*)minisec.hit.face;
                        quad= (minisec.isect == 2);
                        VECCOPY(shi->co, minco);
                        
@@ -2530,10 +2554,9 @@ static void shade_tface(BakeShade *bs)
        if (bs->usemask) {
                if (bs->ibuf->userdata==NULL) {
                        BLI_lock_thread(LOCK_CUSTOM1);
-                       if (bs->ibuf->userdata==NULL) /* since the thread was locked, its possible another thread alloced the value */
+                       if (bs->ibuf->userdata==NULL) /* since the thread was locked, its possible another thread alloced the value */
                                bs->ibuf->userdata = (void *)MEM_callocN(sizeof(char)*bs->rectx*bs->recty, "BakeMask");
-                               bs->rect_mask= (char *)bs->ibuf->userdata;
-                       }
+                       bs->rect_mask= (char *)bs->ibuf->userdata;
                        BLI_unlock_thread(LOCK_CUSTOM1);
                } else {
                        bs->rect_mask= (char *)bs->ibuf->userdata;
@@ -2543,7 +2566,7 @@ static void shade_tface(BakeShade *bs)
        /* get pixel level vertex coordinates */
        for(a=0; a<4; a++) {
                /* Note, workaround for pixel aligned UVs which are common and can screw up our intersection tests
-                * where a pixel gets inbetween 2 faces or the middle of a quad,
+                * where a pixel gets in between 2 faces or the middle of a quad,
                 * camera aligned quads also have this problem but they are less common.
                 * Add a small offset to the UVs, fixes bug #18685 - Campbell */
                vec[a][0]= tface->uv[a][0]*(float)bs->rectx - (0.5f + 0.001);
@@ -2571,8 +2594,13 @@ static void *do_bake_thread(void *bs_v)
                shade_tface(bs);
                
                /* fast threadsafe break test */
-               if(R.test_break())
+               if(R.test_break(R.tbh))
                        break;
+
+               /* access is not threadsafe but since its just true/false probably ok
+                * only used for interactive baking */
+               if(bs->do_update)
+                       *bs->do_update= TRUE;
        }
        bs->ready= 1;
        
@@ -2582,9 +2610,9 @@ static void *do_bake_thread(void *bs_v)
 /* using object selection tags, the faces with UV maps get baked */
 /* render should have been setup */
 /* returns 0 if nothing was handled */
-int RE_bake_shade_all_selected(Render *re, int type, Object *actob)
+int RE_bake_shade_all_selected(Render *re, int type, Object *actob, short *do_update, float *progress)
 {
-       BakeShade handles[BLENDER_MAX_THREADS];
+       BakeShade *handles;
        ListBase threads;
        Image *ima;
        int a, vdone=0, usemask=0;
@@ -2597,25 +2625,28 @@ int RE_bake_shade_all_selected(Render *re, int type, Object *actob)
        get_next_bake_face(NULL);
        
        /* do we need a mask? */
-       if (re->r.bake_filter && (re->r.bake_flag & R_BAKE_CLEAR)==0)
+       if (re->r.bake_filter)
                usemask = 1;
        
        /* baker uses this flag to detect if image was initialized */
        for(ima= G.main->image.first; ima; ima= ima->id.next) {
                ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL);
                ima->id.flag |= LIB_DOIT;
-               if (ibuf)
+               if(ibuf) {
                        ibuf->userdata = NULL; /* use for masking if needed */
+                       if(ibuf->rect_float)
+                               ibuf->profile = IB_PROFILE_LINEAR_RGB;
+               }
        }
        
        BLI_init_threads(&threads, do_bake_thread, re->r.threads);
 
+       handles= MEM_callocN(sizeof(BakeShade)*re->r.threads, "BakeShade");
+
        /* get the threads running */
        for(a=0; a<re->r.threads; a++) {
                /* set defaults in handles */
-               memset(&handles[a], 0, sizeof(BakeShade));
-               
-               handles[a].ssamp.shi[0].lay= re->scene->lay;
+               handles[a].ssamp.shi[0].lay= re->lay;
                
                if (type==RE_BAKE_SHADOW) {
                        handles[a].ssamp.shi[0].passflag= SCE_PASS_SHADOW;
@@ -2631,6 +2662,8 @@ int RE_bake_shade_all_selected(Render *re, int type, Object *actob)
                handles[a].zspan= MEM_callocN(sizeof(ZSpan), "zspan for bake");
                
                handles[a].usemask = usemask;
+
+               handles[a].do_update = do_update; /* use to tell the view to update */
                
                BLI_insert_thread(&threads, &handles[a]);
        }
@@ -2638,19 +2671,29 @@ int RE_bake_shade_all_selected(Render *re, int type, Object *actob)
        /* wait for everything to be done */
        a= 0;
        while(a!=re->r.threads) {
-               
                PIL_sleep_ms(50);
 
-               for(a=0; a<re->r.threads; a++)
+               /* calculate progress */
+               for(vdone=0, a=0; a<re->r.threads; a++)
+                       vdone+= handles[a].vdone;
+               if (progress)
+                       *progress = (float)(vdone / (float)re->totvlak);
+               
+               for(a=0; a<re->r.threads; a++) {
                        if(handles[a].ready==0)
                                break;
+               }
        }
        
        /* filter and refresh images */
        for(ima= G.main->image.first; ima; ima= ima->id.next) {
                if((ima->id.flag & LIB_DOIT)==0) {
                        ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL);
-                       if (re->r.bake_filter) {
+
+                       if(!ibuf)
+                               continue;
+
+                       if(re->r.bake_filter) {
                                if (usemask) {
                                        /* extend the mask +2 pixels from the image,
                                         * this is so colors dont blend in from outside */
@@ -2680,20 +2723,22 @@ int RE_bake_shade_all_selected(Render *re, int type, Object *actob)
                                        ibuf->userdata= NULL;
                                }
                        }
+
                        ibuf->userflags |= IB_BITMAPDIRTY;
                        if (ibuf->rect_float) IMB_rect_from_float(ibuf);
                }
        }
        
        /* calculate return value */
-       for(a=0; a<re->r.threads; a++) {
-               vdone+= handles[a].vdone;
-               
+       for(a=0; a<re->r.threads; a++) {
                zbuf_free_span(handles[a].zspan);
                MEM_freeN(handles[a].zspan);
-       }
+       }
+
+       MEM_freeN(handles);
        
        BLI_end_threads(&threads);
+
        return vdone;
 }