2.5:
[blender.git] / source / blender / render / intern / source / occlusion.c
index c03c655d87dd8242141951c2875ad449fa97d98d..feef3dd424a81176a2a73bf2ab238f0661a73f18 100644 (file)
@@ -42,6 +42,7 @@
 #include "BLI_threads.h"
 
 #include "BKE_global.h"
+#include "BKE_scene.h"
 #include "BKE_utildefines.h"
 
 #include "RE_shader_ext.h"
@@ -180,8 +181,8 @@ static void occ_shade(ShadeSample *ssamp, ObjectInstanceRen *obi, VlakRen *vlr,
 
        /* not a pretty solution, but fixes common cases */
        if(shi->obr->ob && shi->obr->ob->transflag & OB_NEG_SCALE) {
-               VecMulf(shi->vn, -1.0f);
-               VecMulf(shi->vno, -1.0f);
+               VecNegf(shi->vn);
+               VecNegf(shi->vno);
        }
 
        /* init material vars */
@@ -323,17 +324,8 @@ static void occ_face(const OccFace *face, float *co, float *normal, float *area)
                normal[1]= -vlr->n[1];
                normal[2]= -vlr->n[2];
 
-               if(obi->flag & R_TRANSFORMED) {
-                       float xn, yn, zn, (*imat)[3]= obi->imat;
-
-                       xn= normal[0];
-                       yn= normal[1];
-                       zn= normal[2];
-
-                       normal[0]= imat[0][0]*xn + imat[0][1]*yn + imat[0][2]*zn;
-                       normal[1]= imat[1][0]*xn + imat[1][1]*yn + imat[1][2]*zn;
-                       normal[2]= imat[2][0]*xn + imat[2][1]*yn + imat[2][2]*zn;
-               }
+               if(obi->flag & R_TRANSFORMED)
+                       Mat3MulVecfl(obi->nmat, normal);
        }
 
        if(area) {
@@ -410,7 +402,7 @@ static int occ_find_bbox_axis(OcclusionTree *tree, int begin, int end, float *mi
        return axis;
 }
 
-void occ_node_from_face(OccFace *face, OccNode *node)
+static void occ_node_from_face(OccFace *face, OccNode *node)
 {
        float n[3];
 
@@ -522,10 +514,6 @@ static void occ_build_recursive(OcclusionTree *tree, OccNode *node, int begin, i
        OccFace *face;
        int a, b, totthread=0, offset[TOTCHILD], count[TOTCHILD];
 
-       /* keep track of maximum depth for stack */
-       if(depth > tree->maxdepth)
-               tree->maxdepth= depth;
-
        /* add a new node */
        node->occlusion= 1.0f;
 
@@ -560,6 +548,10 @@ static void occ_build_recursive(OcclusionTree *tree, OccNode *node, int begin, i
                                child= BLI_memarena_alloc(tree->arena, sizeof(OccNode));
                                node->child[b].node= child;
 
+                               /* keep track of maximum depth for stack */
+                               if(depth+1 > tree->maxdepth)
+                                       tree->maxdepth= depth+1;
+
                                if(tree->dothreadedbuild)
                                        BLI_unlock_thread(LOCK_CUSTOM1);
 
@@ -650,7 +642,7 @@ static OcclusionTree *occ_tree_build(Render *re)
        tree->totface= totface;
 
        /* parameters */
-       tree->error= re->wrld.ao_approx_error;
+       tree->error= get_render_aosss_error(&re->r, re->wrld.ao_approx_error);
        tree->distfac= (re->wrld.aomode & WO_AODIST)? re->wrld.aodistfac: 0.0f;
 
        /* allocation */
@@ -687,6 +679,7 @@ static OcclusionTree *occ_tree_build(Render *re)
 
        /* recurse */
        tree->root= BLI_memarena_alloc(tree->arena, sizeof(OccNode));
+       tree->maxdepth= 1;
        occ_build_recursive(tree, tree->root, 0, totface, 1);
 
 #if 0
@@ -761,9 +754,9 @@ static int occ_visible_quad(float *p, float *n, float *v0, float *v1, float *v2,
        sd[1]= INPR(n, v1) - c;
        sd[2]= INPR(n, v2) - c;
 
-       if(fabs(sd[0]) < epsilon) sd[0] = 0.0f;
-       if(fabs(sd[1]) < epsilon) sd[1] = 0.0f;
-       if(fabs(sd[2]) < epsilon) sd[2] = 0.0f;
+       if(fabsf(sd[0]) < epsilon) sd[0] = 0.0f;
+       if(fabsf(sd[1]) < epsilon) sd[1] = 0.0f;
+       if(fabsf(sd[2]) < epsilon) sd[2] = 0.0f;
 
        if(sd[0] > 0) {
                if(sd[1] > 0) {
@@ -1093,13 +1086,6 @@ static float occ_quad_form_factor(float *p, float *n, float *q0, float *q1, floa
 
 #endif
 
-static float saacosf(float fac)
-{
-       if(fac<= -1.0f) return (float)M_PI;
-       else if(fac>=1.0f) return 0.0f;
-       else return acos(fac); /* acosf(fac) */
-}
-
 static void normalizef(float *n)
 {
        float d;
@@ -1107,7 +1093,7 @@ static void normalizef(float *n)
        d= INPR(n, n);
 
        if(d > 1.0e-35F) {
-               d= 1.0f/sqrt(d); /* sqrtf(d) */
+               d= 1.0f/sqrtf(d);
 
                n[0] *= d; 
                n[1] *= d; 
@@ -1151,7 +1137,7 @@ static float occ_quad_form_factor(float *p, float *n, float *q0, float *q1, floa
        return result;
 }
 
-float occ_form_factor(OccFace *face, float *p, float *n)
+static float occ_form_factor(OccFace *face, float *p, float *n)
 {
        ObjectInstanceRen *obi;
        VlakRen *vlr;
@@ -1229,7 +1215,7 @@ static void occ_lookup(OcclusionTree *tree, int thread, OccFace *exclude, float
                                fac= 1.0f;
 
                        /* accumulate occlusion from spherical harmonics */
-                       invd2 = 1.0f/sqrt(d2);
+                       invd2 = 1.0f/sqrtf(d2);
                        weight= occ_solid_angle(node, v, d2, invd2, n);
                        weight *= node->occlusion;
 
@@ -1265,7 +1251,7 @@ static void occ_lookup(OcclusionTree *tree, int thread, OccFace *exclude, float
                                                weight *= tree->occlusion[node->child[b].face];
 
                                                if(bentn) {
-                                                       invd2= 1.0f/sqrt(d2);
+                                                       invd2= 1.0f/sqrtf(d2);
                                                        bentn[0] -= weight*invd2*v[0];
                                                        bentn[1] -= weight*invd2*v[1];
                                                        bentn[2] -= weight*invd2*v[2];
@@ -1283,6 +1269,7 @@ static void occ_lookup(OcclusionTree *tree, int thread, OccFace *exclude, float
        }
 
        if(occ) *occ= resultocc;
+       if(bentn) Normalize(bentn);
 }
 
 static void occ_compute_passes(Render *re, OcclusionTree *tree, int totpass)
@@ -1295,15 +1282,15 @@ static void occ_compute_passes(Render *re, OcclusionTree *tree, int totpass)
        for(pass=0; pass<totpass; pass++) {
                for(i=0; i<tree->totface; i++) {
                        occ_face(&tree->face[i], co, n, NULL);
-                       VecMulf(n, -1.0f);
+                       VecNegf(n);
                        VECADDFAC(co, co, n, 1e-8f);
 
                        occ_lookup(tree, 0, &tree->face[i], co, n, &occ[i], NULL);
-                       if(re->test_break())
+                       if(re->test_break(re->tbh))
                                break;
                }
 
-               if(re->test_break())
+               if(re->test_break(re->tbh))
                        break;
 
                for(i=0; i<tree->totface; i++) {
@@ -1320,7 +1307,7 @@ static void occ_compute_passes(Render *re, OcclusionTree *tree, int totpass)
 
 static void sample_occ_tree(Render *re, OcclusionTree *tree, OccFace *exclude, float *co, float *n, int thread, int onlyshadow, float *skycol)
 {
-       float nn[3], bn[3], dxyview[3], fac, occ, occlusion, correction;
+       float nn[3], bn[3], fac, occ, occlusion, correction;
        int aocolor;
 
        aocolor= re->wrld.aocolor;
@@ -1328,7 +1315,7 @@ static void sample_occ_tree(Render *re, OcclusionTree *tree, OccFace *exclude, f
                aocolor= WO_AOPLAIN;
 
        VECCOPY(nn, n);
-       VecMulf(nn, -1.0f);
+       VecNegf(nn);
 
        occ_lookup(tree, thread, exclude, co, nn, &occ, (aocolor)? bn: NULL);
 
@@ -1341,18 +1328,24 @@ static void sample_occ_tree(Render *re, OcclusionTree *tree, OccFace *exclude, f
 
        if(aocolor) {
                /* sky shading using bent normal */
-               if(aocolor==WO_AOSKYCOL) {
+               if(ELEM(aocolor, WO_AOSKYCOL, WO_AOSKYTEX)) {
                        fac= 0.5*(1.0f+bn[0]*re->grvec[0]+ bn[1]*re->grvec[1]+ bn[2]*re->grvec[2]);
                        skycol[0]= (1.0f-fac)*re->wrld.horr + fac*re->wrld.zenr;
                        skycol[1]= (1.0f-fac)*re->wrld.horg + fac*re->wrld.zeng;
                        skycol[2]= (1.0f-fac)*re->wrld.horb + fac*re->wrld.zenb;
                }
+#if 0
                else {  /* WO_AOSKYTEX */
+                       float dxyview[3];
+                       bn[0]= -bn[0];
+                       bn[1]= -bn[1];
+                       bn[2]= -bn[2];
                        dxyview[0]= 1.0f;
                        dxyview[1]= 1.0f;
                        dxyview[2]= 0.0f;
                        shadeSkyView(skycol, co, bn, dxyview);
                }
+#endif
 
                VecMulf(skycol, occlusion);
        }
@@ -1476,7 +1469,7 @@ static void sample_occ_surface(ShadeInput *shi)
        int *face, *index = RE_strandren_get_face(shi->obr, strand, 0);
        float w[4], *co1, *co2, *co3, *co4;
 
-       if(mesh && index) {
+       if(mesh && mesh->face && mesh->co && mesh->col && index) {
                face= mesh->face[*index];
 
                co1= mesh->co[face[0]];
@@ -1526,7 +1519,7 @@ static void *exec_strandsurface_sample(void *data)
                        CalcCent3f(co, co1, co2, co3);
                        CalcNormFloat(co1, co2, co3, n);
                }
-               VecMulf(n, -1.0f);
+               VecNegf(n);
 
                sample_occ_tree(re, re->occlusiontree, NULL, co, n, othread->thread, 0, col);
                VECCOPY(othread->facecol[a], col);
@@ -1547,7 +1540,7 @@ void make_occ_tree(Render *re)
        R= *re;
 
        re->i.infostr= "Occlusion preprocessing";
-       re->stats_draw(&re->i);
+       re->stats_draw(re->sdh, &re->i);
        
        re->occlusiontree= occ_tree_build(re);
        
@@ -1556,6 +1549,9 @@ void make_occ_tree(Render *re)
                        occ_compute_passes(re, re->occlusiontree, re->wrld.ao_approx_passes);
 
                for(mesh=re->strandsurface.first; mesh; mesh=mesh->next) {
+                       if(!mesh->face || !mesh->co || !mesh->col)
+                               continue;
+
                        count= MEM_callocN(sizeof(int)*mesh->totvert, "OcclusionCount");
                        facecol= MEM_callocN(sizeof(float)*3*mesh->totface, "StrandSurfFaceCol");
 
@@ -1630,16 +1626,13 @@ void sample_occ(Render *re, ShadeInput *shi)
                        sample_occ_surface(shi);
                }
                /* try to get result from the cache if possible */
-               else if(!sample_occ_cache(tree, shi->co, shi->vno, shi->xs, shi->ys, shi->thread, shi->ao)) {
+               else if(shi->depth!=0 || !sample_occ_cache(tree, shi->co, shi->vno, shi->xs, shi->ys, shi->thread, shi->ao)) {
                        /* no luck, let's sample the occlusion */
                        exclude.obi= shi->obi - re->objectinstance;
                        exclude.facenr= shi->vlr->index;
                        onlyshadow= (shi->mat->mode & MA_ONLYSHADOW);
                        sample_occ_tree(re, tree, &exclude, shi->co, shi->vno, shi->thread, onlyshadow, shi->ao);
 
-                       if(G.rt & 32)
-                               shi->ao[2] *= 2.0f;
-
                        /* fill result into sample, each time */
                        if(tree->cache) {
                                cache= &tree->cache[shi->thread];
@@ -1671,7 +1664,8 @@ void cache_occ_samples(Render *re, RenderPart *pa, ShadeSample *ssamp)
        OcclusionCacheSample *sample;
        OccFace exclude;
        ShadeInput *shi;
-       int *ro, *rp, *rz, onlyshadow;
+       intptr_t *rd=NULL;
+       int *ro=NULL, *rp=NULL, *rz=NULL, onlyshadow;
        int x, y, step = CACHE_STEP;
 
        if(!tree->cache)
@@ -1686,45 +1680,60 @@ void cache_occ_samples(Render *re, RenderPart *pa, ShadeSample *ssamp)
        cache->sample= MEM_callocN(sizeof(OcclusionCacheSample)*cache->w*cache->h, "OcclusionCacheSample");
        sample= cache->sample;
 
-       ps.next= NULL;
-       ps.mask= (1<<re->osa);
+       if(re->osa) {
+               rd= pa->rectdaps;
+       }
+       else {
+               /* fake pixel struct for non-osa */
+               ps.next= NULL;
+               ps.mask= 0xFFFF;
 
-       ro= pa->recto;
-       rp= pa->rectp;
-       rz= pa->rectz;
+               ro= pa->recto;
+               rp= pa->rectp;
+               rz= pa->rectz;
+       }
 
        /* compute a sample at every step pixels */
        for(y=pa->disprect.ymin; y<pa->disprect.ymax; y++) {
-               for(x=pa->disprect.xmin; x<pa->disprect.xmax; x++, ro++, rp++, rz++, sample++) {
-                       if((((x - pa->disprect.xmin + step) % step) == 0 || x == pa->disprect.xmax-1) && (((y - pa->disprect.ymin + step) % step) == 0 || y == pa->disprect.ymax-1)) {
-                               if(*rp) {
-                                       ps.obi= *ro;
-                                       ps.facenr= *rp;
-                                       ps.z= *rz;
-
-                                       shade_samples_fill_with_ps(ssamp, &ps, x, y);
-                                       shi= ssamp->shi;
-                                       if(!shi->vlr)
-                                               continue;
-
-                                       onlyshadow= (shi->mat->mode & MA_ONLYSHADOW);
-                                       exclude.obi= shi->obi - re->objectinstance;
-                                       exclude.facenr= shi->vlr->index;
-                                       sample_occ_tree(re, tree, &exclude, shi->co, shi->vno, shi->thread, onlyshadow, shi->ao);
+               for(x=pa->disprect.xmin; x<pa->disprect.xmax; x++, sample++, rd++, ro++, rp++, rz++) {
+                       if(!(((x - pa->disprect.xmin + step) % step) == 0 || x == pa->disprect.xmax-1))
+                               continue;
+                       if(!(((y - pa->disprect.ymin + step) % step) == 0 || y == pa->disprect.ymax-1))
+                               continue;
 
-                                       VECCOPY(sample->co, shi->co);
-                                       VECCOPY(sample->n, shi->vno);
-                                       VECCOPY(sample->col, shi->ao);
-                                       sample->intensity= MAX3(sample->col[0], sample->col[1], sample->col[2]);
-                                       sample->dist2= INPR(shi->dxco, shi->dxco) + INPR(shi->dyco, shi->dyco);
-                                       sample->x= shi->xs;
-                                       sample->y= shi->ys;
-                                       sample->filled= 1;
-                               }
+                       if(re->osa) {
+                               if(!*rd) continue;
 
-                               if(re->test_break())
-                                       break;
+                               shade_samples_fill_with_ps(ssamp, (PixStr *)(*rd), x, y);
                        }
+                       else {
+                               if(!*rp) continue;
+
+                               ps.obi= *ro;
+                               ps.facenr= *rp;
+                               ps.z= *rz;
+                               shade_samples_fill_with_ps(ssamp, &ps, x, y);
+                       }
+
+                       shi= ssamp->shi;
+                       if(shi->vlr) {
+                               onlyshadow= (shi->mat->mode & MA_ONLYSHADOW);
+                               exclude.obi= shi->obi - re->objectinstance;
+                               exclude.facenr= shi->vlr->index;
+                               sample_occ_tree(re, tree, &exclude, shi->co, shi->vno, shi->thread, onlyshadow, shi->ao);
+
+                               VECCOPY(sample->co, shi->co);
+                               VECCOPY(sample->n, shi->vno);
+                               VECCOPY(sample->col, shi->ao);
+                               sample->intensity= MAX3(sample->col[0], sample->col[1], sample->col[2]);
+                               sample->dist2= INPR(shi->dxco, shi->dxco) + INPR(shi->dyco, shi->dyco);
+                               sample->x= shi->xs;
+                               sample->y= shi->ys;
+                               sample->filled= 1;
+                       }
+
+                       if(re->test_break(re->tbh))
+                               break;
                }
        }
 }