doxygen: prevent GPL license block from being parsed as doxygen comment.
[blender.git] / source / blender / render / intern / source / rendercore.c
index dec826f..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.
@@ -41,8 +41,9 @@
 #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"
@@ -60,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"
@@ -70,7 +73,6 @@
 #include "shading.h"
 #include "sss.h"
 #include "zbuf.h"
-#include "RE_raytrace.h"
 
 #include "PIL_time.h"
 
@@ -96,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);
@@ -486,9 +489,6 @@ static void add_filt_passes(RenderLayer *rl, int curmask, int rectx, int offset,
                        case SCE_PASS_REFRACT:
                                col= shr->refr;
                                break;
-                       case SCE_PASS_RADIO:
-                               col= NULL; // removed shr->rad;
-                               break;
                        case SCE_PASS_NORMAL:
                                col= shr->nor;
                                break;
@@ -593,9 +593,6 @@ static void add_passes(RenderLayer *rl, int offset, ShadeInput *shi, ShadeResult
                        case SCE_PASS_REFRACT:
                                col= shr->refr;
                                break;
-                       case SCE_PASS_RADIO:
-                               col= NULL; // removed shr->rad;
-                               break;
                        case SCE_PASS_NORMAL:
                                col= shr->nor;
                                break;
@@ -745,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];
@@ -1034,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;
        
@@ -1051,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;
        
@@ -1098,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];
@@ -2080,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]++;
@@ -2135,7 +2123,13 @@ static void bake_shade(void *handle, Object *ob, ShadeInput *shi, int quad, int
        if(bs->type==RE_BAKE_AO) {
                ambient_occlusion(shi);
 
-               VECCOPY(shr.combined, shi->ao)
+               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 */
@@ -2166,12 +2160,14 @@ static void bake_shade(void *handle, Object *ob, ShadeInput *shi, int quad, int
                                if(tvn && ttang) {
                                        VECCOPY(mat[0], 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);
-                                       cross_v3_v3v3(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);
                                }
 
                                invert_m3_m3(imat, mat);
@@ -2211,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;
@@ -2255,21 +2262,8 @@ static void bake_displacement(void *handle, ShadeInput *shi, float dist, int x,
        }
 }
 
-#if 0
-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);
-}
-#endif
-
 static int bake_intersect_tree(RayObject* raytree, Isect* isect, float *start, float *dir, float sign, float *hitco, float *dist)
 {
-       //TODO, validate against blender 2.4x, results may have changed.
        float maxdist;
        int hit;
 
@@ -2277,28 +2271,24 @@ static int bake_intersect_tree(RayObject* raytree, Isect* isect, float *start, f
        if(R.r.bake_maxdist > 0.0f)
                maxdist= R.r.bake_maxdist;
        else
-               maxdist= FLT_MAX + R.r.bake_biasdist;
+               maxdist= RE_RAYTRACE_MAXDIST + R.r.bake_biasdist;
        
        /* 'dir' is always normalized */
        VECADDFAC(isect->start, start, dir, -R.r.bake_biasdist);                                        
 
-       isect->vec[0] = dir[0]*maxdist*sign;
-       isect->vec[1] = dir[1]*maxdist*sign;
-       isect->vec[2] = dir[2]*maxdist*sign;
+       isect->dir[0] = dir[0]*sign;
+       isect->dir[1] = dir[1]*sign;
+       isect->dir[2] = dir[2]*sign;
 
-       isect->labda = maxdist;
+       isect->dist = maxdist;
 
-       /* TODO, 2.4x had this...
-       hit = RE_ray_tree_intersect_check(R.raytree, isect, bake_check_intersect);
-       ...the active object may NOT be ignored in some cases.
-       */
        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= len_v3v3(start, hitco);
+               *dist= isect->dist;
        }
 
        return hit;
@@ -2359,7 +2349,7 @@ 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;
@@ -2398,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 */
@@ -2421,7 +2411,9 @@ static void do_bake_shade(void *handle, int x, int y, float u, float v)
 
                        isec.orig.ob   = obi;
                        isec.orig.face = vlr;
-                       isec.userdata= bs;
+                       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 || len_v3v3(shi->co, co) < len_v3v3(shi->co, minco)) {
@@ -2562,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;
@@ -2575,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);
@@ -2619,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, short *do_update)
+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;
@@ -2634,25 +2625,28 @@ int RE_bake_shade_all_selected(Render *re, int type, Object *actob, short *do_up
        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;
@@ -2677,19 +2671,29 @@ int RE_bake_shade_all_selected(Render *re, int type, Object *actob, short *do_up
        /* 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 */
@@ -2719,20 +2723,22 @@ int RE_bake_shade_all_selected(Render *re, int type, Object *actob, short *do_up
                                        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;
 }