Blender V2.61 - r43446

occlusion.c

Go to the documentation of this file.
00001 /* 
00002  *
00003  * ***** BEGIN GPL LICENSE BLOCK *****
00004  *
00005  * This program is free software; you can redistribute it and/or
00006  * modify it under the terms of the GNU General Public License
00007  * as published by the Free Software Foundation; either version 2
00008  * of the License, or (at your option) any later version.
00009  *
00010  * This program is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  * GNU General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU General Public License
00016  * along with this program; if not, write to the Free Software Foundation,
00017  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00018  *
00019  * The Original Code is Copyright (C) 2008 Blender Foundation.
00020  * All rights reserved.
00021  *
00022  * The Original Code is: all of this file.
00023  *
00024  * Contributor(s): Brecht Van Lommel.
00025  *
00026  * ***** END GPL LICENSE BLOCK *****
00027  */
00028 
00034 #include <math.h>
00035 #include <stdio.h>
00036 #include <stdlib.h>
00037 #include <string.h>
00038 
00039 #include "MEM_guardedalloc.h"
00040 
00041 #include "DNA_material_types.h"
00042 
00043 #include "BLI_math.h"
00044 #include "BLI_blenlib.h"
00045 #include "BLI_memarena.h"
00046 #include "BLI_threads.h"
00047 #include "BLI_utildefines.h"
00048 
00049 #include "BKE_global.h"
00050 #include "BKE_scene.h"
00051 
00052 
00053 #include "RE_shader_ext.h"
00054 
00055 /* local includes */
00056 #include "occlusion.h"
00057 #include "render_types.h"
00058 #include "rendercore.h"
00059 #include "renderdatabase.h"
00060 #include "pixelshading.h"
00061 #include "shading.h"
00062 #include "zbuf.h"
00063 
00064 /* ------------------------- Declarations --------------------------- */
00065 
00066 #define INVALID_INDEX ((int)(~0))
00067 #define INVPI 0.31830988618379069f
00068 #define TOTCHILD 8
00069 #define CACHE_STEP 3
00070 
00071 typedef struct OcclusionCacheSample {
00072     float co[3], n[3], ao[3], env[3], indirect[3], intensity, dist2;
00073     int x, y, filled;
00074 } OcclusionCacheSample;
00075 
00076 typedef struct OcclusionCache {
00077     OcclusionCacheSample *sample;
00078     int x, y, w, h, step;
00079 } OcclusionCache;
00080 
00081 typedef struct OccFace {
00082     int obi;
00083     int facenr;
00084 } OccFace;
00085 
00086 typedef struct OccNode {
00087     float co[3], area;
00088     float sh[9], dco;
00089     float occlusion, rad[3];
00090     int childflag;
00091     union {
00092         //OccFace face;
00093         int face;
00094         struct OccNode *node;
00095     } child[TOTCHILD];
00096 } OccNode;
00097 
00098 typedef struct OcclusionTree {
00099     MemArena *arena;
00100 
00101     float (*co)[3];     /* temporary during build */
00102 
00103     OccFace *face;      /* instance and face indices */
00104     float *occlusion;   /* occlusion for faces */
00105     float (*rad)[3];    /* radiance for faces */
00106     
00107     OccNode *root;
00108 
00109     OccNode **stack[BLENDER_MAX_THREADS];
00110     int maxdepth;
00111 
00112     int totface;
00113 
00114     float error;
00115     float distfac;
00116 
00117     int dothreadedbuild;
00118     int totbuildthread;
00119     int doindirect;
00120 
00121     OcclusionCache *cache;
00122 } OcclusionTree;
00123 
00124 typedef struct OcclusionThread {
00125     Render *re;
00126     StrandSurface *mesh;
00127     float (*faceao)[3];
00128     float (*faceenv)[3];
00129     float (*faceindirect)[3];
00130     int begin, end;
00131     int thread;
00132 } OcclusionThread;
00133 
00134 typedef struct OcclusionBuildThread {
00135     OcclusionTree *tree;
00136     int begin, end, depth;
00137     OccNode *node;
00138 } OcclusionBuildThread;
00139 
00140 /* ------------------------- Shading --------------------------- */
00141 
00142 extern Render R; // meh
00143 
00144 static void occ_shade(ShadeSample *ssamp, ObjectInstanceRen *obi, VlakRen *vlr, float *rad)
00145 {
00146     ShadeInput *shi= ssamp->shi;
00147     ShadeResult *shr= ssamp->shr;
00148     float l, u, v, *v1, *v2, *v3;
00149     
00150     /* init */
00151     if(vlr->v4) {
00152         shi->u= u= 0.5f;
00153         shi->v= v= 0.5f;
00154     }
00155     else {
00156         shi->u= u= 1.0f/3.0f;
00157         shi->v= v= 1.0f/3.0f;
00158     }
00159 
00160     /* setup render coordinates */
00161     v1= vlr->v1->co;
00162     v2= vlr->v2->co;
00163     v3= vlr->v3->co;
00164     
00165     /* renderco */
00166     l= 1.0f-u-v;
00167     
00168     shi->co[0]= l*v3[0]+u*v1[0]+v*v2[0];
00169     shi->co[1]= l*v3[1]+u*v1[1]+v*v2[1];
00170     shi->co[2]= l*v3[2]+u*v1[2]+v*v2[2];
00171 
00172     shade_input_set_triangle_i(shi, obi, vlr, 0, 1, 2);
00173 
00174     /* set up view vector */
00175     copy_v3_v3(shi->view, shi->co);
00176     normalize_v3(shi->view);
00177     
00178     /* cache for shadow */
00179     shi->samplenr++;
00180     
00181     shi->xs= 0; // TODO
00182     shi->ys= 0;
00183     
00184     shade_input_set_normals(shi);
00185 
00186     /* no normal flip */
00187     if(shi->flippednor)
00188         shade_input_flip_normals(shi);
00189 
00190     madd_v3_v3fl(shi->co, shi->vn, 0.0001f); /* ugly.. */
00191 
00192     /* not a pretty solution, but fixes common cases */
00193     if(shi->obr->ob && shi->obr->ob->transflag & OB_NEG_SCALE) {
00194         negate_v3(shi->vn);
00195         negate_v3(shi->vno);
00196         negate_v3(shi->nmapnorm);
00197     }
00198 
00199     /* init material vars */
00200     // note, keep this synced with render_types.h
00201     memcpy(&shi->r, &shi->mat->r, 23*sizeof(float));
00202     shi->har= shi->mat->har;
00203     
00204     /* render */
00205     shade_input_set_shade_texco(shi);
00206     shade_material_loop(shi, shr); /* todo: nodes */
00207     
00208     copy_v3_v3(rad, shr->combined);
00209 }
00210 
00211 static void occ_build_shade(Render *re, OcclusionTree *tree)
00212 {
00213     ShadeSample ssamp;
00214     ObjectInstanceRen *obi;
00215     VlakRen *vlr;
00216     int a;
00217 
00218     R= *re;
00219 
00220     /* setup shade sample with correct passes */
00221     memset(&ssamp, 0, sizeof(ShadeSample));
00222     ssamp.shi[0].lay= re->lay;
00223     ssamp.shi[0].passflag= SCE_PASS_DIFFUSE|SCE_PASS_RGBA;
00224     ssamp.shi[0].combinedflag= ~(SCE_PASS_SPEC);
00225     ssamp.tot= 1;
00226 
00227     for(a=0; a<tree->totface; a++) {
00228         obi= &R.objectinstance[tree->face[a].obi];
00229         vlr= RE_findOrAddVlak(obi->obr, tree->face[a].facenr);
00230 
00231         occ_shade(&ssamp, obi, vlr, tree->rad[a]);
00232     }
00233 }
00234 
00235 /* ------------------------- Spherical Harmonics --------------------------- */
00236 
00237 /* Use 2nd order SH => 9 coefficients, stored in this order:
00238    0 = (0,0),
00239    1 = (1,-1), 2 = (1,0), 3 = (1,1),
00240    4 = (2,-2), 5 = (2,-1), 6 = (2,0), 7 = (2,1), 8 = (2,2) */
00241 
00242 static void sh_copy(float *shresult, float *sh)
00243 {
00244     memcpy(shresult, sh, sizeof(float)*9);
00245 }
00246 
00247 static void sh_mul(float *sh, float f)
00248 {
00249     int i;
00250 
00251     for(i=0; i<9; i++)
00252         sh[i] *= f;
00253 }
00254 
00255 static void sh_add(float *shresult, float *sh1, float *sh2)
00256 {
00257     int i;
00258 
00259     for(i=0; i<9; i++)
00260         shresult[i]= sh1[i] + sh2[i];
00261 }
00262 
00263 static void sh_from_disc(float *n, float area, float *shresult)
00264 {
00265     /* See formula (3) in:
00266        "An Efficient Representation for Irradiance Environment Maps" */
00267     float sh[9], x, y, z;
00268 
00269     x= n[0];
00270     y= n[1];
00271     z= n[2];
00272 
00273     sh[0]= 0.282095f;
00274 
00275     sh[1]= 0.488603f*y;
00276     sh[2]= 0.488603f*z;
00277     sh[3]= 0.488603f*x;
00278     
00279     sh[4]= 1.092548f*x*y;
00280     sh[5]= 1.092548f*y*z;
00281     sh[6]= 0.315392f*(3.0f*z*z - 1.0f);
00282     sh[7]= 1.092548f*x*z;
00283     sh[8]= 0.546274f*(x*x - y*y);
00284 
00285     sh_mul(sh, area);
00286     sh_copy(shresult, sh);
00287 }
00288 
00289 static float sh_eval(float *sh, float *v)
00290 {
00291     /* See formula (13) in:
00292        "An Efficient Representation for Irradiance Environment Maps" */
00293     static const float c1 = 0.429043f, c2 = 0.511664f, c3 = 0.743125f;
00294     static const float c4 = 0.886227f, c5 = 0.247708f;
00295     float x, y, z, sum;
00296 
00297     x= v[0];
00298     y= v[1];
00299     z= v[2];
00300 
00301     sum= c1*sh[8]*(x*x - y*y);
00302     sum += c3*sh[6]*z*z;
00303     sum += c4*sh[0];
00304     sum += -c5*sh[6];
00305     sum += 2.0f*c1*(sh[4]*x*y + sh[7]*x*z + sh[5]*y*z);
00306     sum += 2.0f*c2*(sh[3]*x + sh[1]*y + sh[2]*z);
00307 
00308     return sum;
00309 }
00310 
00311 /* ------------------------------ Building --------------------------------- */
00312 
00313 static void occ_face(const OccFace *face, float co[3], float normal[3], float *area)
00314 {
00315     ObjectInstanceRen *obi;
00316     VlakRen *vlr;
00317     float v1[3], v2[3], v3[3], v4[3];
00318 
00319     obi= &R.objectinstance[face->obi];
00320     vlr= RE_findOrAddVlak(obi->obr, face->facenr);
00321     
00322     if(co) {
00323         if(vlr->v4)
00324             mid_v3_v3v3(co, vlr->v1->co, vlr->v3->co);
00325         else
00326             cent_tri_v3(co, vlr->v1->co, vlr->v2->co, vlr->v3->co);
00327 
00328         if(obi->flag & R_TRANSFORMED)
00329             mul_m4_v3(obi->mat, co);
00330     }
00331     
00332     if(normal) {
00333         normal[0]= -vlr->n[0];
00334         normal[1]= -vlr->n[1];
00335         normal[2]= -vlr->n[2];
00336 
00337         if(obi->flag & R_TRANSFORMED)
00338             mul_m3_v3(obi->nmat, normal);
00339     }
00340 
00341     if(area) {
00342         copy_v3_v3(v1, vlr->v1->co);
00343         copy_v3_v3(v2, vlr->v2->co);
00344         copy_v3_v3(v3, vlr->v3->co);
00345         if(vlr->v4) copy_v3_v3(v4, vlr->v4->co);
00346 
00347         if(obi->flag & R_TRANSFORMED) {
00348             mul_m4_v3(obi->mat, v1);
00349             mul_m4_v3(obi->mat, v2);
00350             mul_m4_v3(obi->mat, v3);
00351             if(vlr->v4) mul_m4_v3(obi->mat, v4);
00352         }
00353 
00354         /* todo: correct area for instances */
00355         if(vlr->v4)
00356             *area= area_quad_v3(v1, v2, v3, v4);
00357         else
00358             *area= area_tri_v3(v1, v2, v3);
00359     }
00360 }
00361 
00362 static void occ_sum_occlusion(OcclusionTree *tree, OccNode *node)
00363 {
00364     OccNode *child;
00365     float occ, area, totarea, rad[3];
00366     int a, b, indirect= tree->doindirect;
00367 
00368     occ= 0.0f;
00369     totarea= 0.0f;
00370     if(indirect) zero_v3(rad);
00371 
00372     for(b=0; b<TOTCHILD; b++) {
00373         if(node->childflag & (1<<b)) {
00374             a= node->child[b].face;
00375             occ_face(&tree->face[a], 0, 0, &area);
00376             occ += area*tree->occlusion[a];
00377             if(indirect) madd_v3_v3fl(rad, tree->rad[a], area);
00378             totarea += area;
00379         }
00380         else if(node->child[b].node) {
00381             child= node->child[b].node;
00382             occ_sum_occlusion(tree, child);
00383 
00384             occ += child->area*child->occlusion;
00385             if(indirect) madd_v3_v3fl(rad, child->rad, child->area);
00386             totarea += child->area;
00387         }
00388     }
00389 
00390     if(totarea != 0.0f) {
00391         occ /= totarea;
00392         if(indirect) mul_v3_fl(rad, 1.0f/totarea);
00393     }
00394     
00395     node->occlusion= occ;
00396     if(indirect) copy_v3_v3(node->rad, rad);
00397 }
00398 
00399 static int occ_find_bbox_axis(OcclusionTree *tree, int begin, int end, float *min, float *max)
00400 {
00401     float len, maxlen= -1.0f;
00402     int a, axis = 0;
00403 
00404     INIT_MINMAX(min, max);
00405 
00406     for(a=begin; a<end; a++)
00407         DO_MINMAX(tree->co[a], min, max)
00408 
00409     for(a=0; a<3; a++) {
00410         len= max[a] - min[a];
00411 
00412         if(len > maxlen) {
00413             maxlen= len;
00414             axis= a;
00415         }
00416     }
00417 
00418     return axis;
00419 }
00420 
00421 static void occ_node_from_face(OccFace *face, OccNode *node)
00422 {
00423     float n[3];
00424 
00425     occ_face(face, node->co, n, &node->area);
00426     node->dco= 0.0f;
00427     sh_from_disc(n, node->area, node->sh);
00428 }
00429 
00430 static void occ_build_dco(OcclusionTree *tree, OccNode *node, const float co[3], float *dco)
00431 {
00432     int b;
00433     for(b=0; b<TOTCHILD; b++) {
00434         float dist, d[3], nco[3];
00435 
00436         if(node->childflag & (1<<b)) {
00437             occ_face(tree->face+node->child[b].face, nco, NULL, NULL);
00438         }
00439         else if(node->child[b].node) {
00440             OccNode *child= node->child[b].node;
00441             occ_build_dco(tree, child, co, dco);
00442             copy_v3_v3(nco, child->co);
00443         }
00444         else {
00445             continue;
00446         }
00447 
00448         sub_v3_v3v3(d, nco, co);
00449         dist= dot_v3v3(d, d);
00450         if(dist > *dco)
00451             *dco= dist;
00452     }
00453 }
00454 
00455 static void occ_build_split(OcclusionTree *tree, int begin, int end, int *split)
00456 {
00457     float min[3], max[3], mid;
00458     int axis, a, enda;
00459 
00460     /* split in middle of boundbox. this seems faster than median split
00461      * on complex scenes, possibly since it avoids two distant faces to
00462      * be in the same node better? */
00463     axis= occ_find_bbox_axis(tree, begin, end, min, max);
00464     mid= 0.5f*(min[axis]+max[axis]);
00465 
00466     a= begin;
00467     enda= end;
00468     while(a<enda) {
00469         if(tree->co[a][axis] > mid) {
00470             enda--;
00471             SWAP(OccFace, tree->face[a], tree->face[enda]);
00472             SWAP(float, tree->co[a][0], tree->co[enda][0]);
00473             SWAP(float, tree->co[a][1], tree->co[enda][1]);
00474             SWAP(float, tree->co[a][2], tree->co[enda][2]);
00475         }
00476         else
00477             a++;
00478     }
00479 
00480     *split= enda;
00481 }
00482 
00483 static void occ_build_8_split(OcclusionTree *tree, int begin, int end, int *offset, int *count)
00484 {
00485     /* split faces into eight groups */
00486     int b, splitx, splity[2], splitz[4];
00487 
00488     occ_build_split(tree, begin, end, &splitx);
00489 
00490     /* force split if none found, to deal with degenerate geometry */
00491     if(splitx == begin || splitx == end)
00492         splitx= (begin+end)/2;
00493 
00494     occ_build_split(tree, begin, splitx, &splity[0]);
00495     occ_build_split(tree, splitx, end, &splity[1]);
00496 
00497     occ_build_split(tree, begin, splity[0], &splitz[0]);
00498     occ_build_split(tree, splity[0], splitx, &splitz[1]);
00499     occ_build_split(tree, splitx, splity[1], &splitz[2]);
00500     occ_build_split(tree, splity[1], end, &splitz[3]);
00501 
00502     offset[0]= begin;
00503     offset[1]= splitz[0];
00504     offset[2]= splity[0];
00505     offset[3]= splitz[1];
00506     offset[4]= splitx;
00507     offset[5]= splitz[2];
00508     offset[6]= splity[1];
00509     offset[7]= splitz[3];
00510 
00511     for(b=0; b<7; b++)
00512         count[b]= offset[b+1] - offset[b];
00513     count[7]= end - offset[7];
00514 }
00515 
00516 static void occ_build_recursive(OcclusionTree *tree, OccNode *node, int begin, int end, int depth);
00517 
00518 static void *exec_occ_build(void *data)
00519 {
00520     OcclusionBuildThread *othread= (OcclusionBuildThread*)data;
00521 
00522     occ_build_recursive(othread->tree, othread->node, othread->begin, othread->end, othread->depth);
00523 
00524     return 0;
00525 }
00526 
00527 static void occ_build_recursive(OcclusionTree *tree, OccNode *node, int begin, int end, int depth)
00528 {
00529     ListBase threads;
00530     OcclusionBuildThread othreads[BLENDER_MAX_THREADS];
00531     OccNode *child, tmpnode;
00532     /* OccFace *face; */
00533     int a, b, totthread=0, offset[TOTCHILD], count[TOTCHILD];
00534 
00535     /* add a new node */
00536     node->occlusion= 1.0f;
00537 
00538     /* leaf node with only children */
00539     if(end - begin <= TOTCHILD) {
00540         for(a=begin, b=0; a<end; a++, b++) {
00541             /* face= &tree->face[a]; */
00542             node->child[b].face= a;
00543             node->childflag |= (1<<b);
00544         }
00545     }
00546     else {
00547         /* order faces */
00548         occ_build_8_split(tree, begin, end, offset, count);
00549 
00550         if(depth == 1 && tree->dothreadedbuild)
00551             BLI_init_threads(&threads, exec_occ_build, tree->totbuildthread);
00552 
00553         for(b=0; b<TOTCHILD; b++) {
00554             if(count[b] == 0) {
00555                 node->child[b].node= NULL;
00556             }
00557             else if(count[b] == 1) {
00558                 /* face= &tree->face[offset[b]]; */
00559                 node->child[b].face= offset[b];
00560                 node->childflag |= (1<<b);
00561             }
00562             else {
00563                 if(tree->dothreadedbuild)
00564                     BLI_lock_thread(LOCK_CUSTOM1);
00565 
00566                 child= BLI_memarena_alloc(tree->arena, sizeof(OccNode));
00567                 node->child[b].node= child;
00568 
00569                 /* keep track of maximum depth for stack */
00570                 if(depth+1 > tree->maxdepth)
00571                     tree->maxdepth= depth+1;
00572 
00573                 if(tree->dothreadedbuild)
00574                     BLI_unlock_thread(LOCK_CUSTOM1);
00575 
00576                 if(depth == 1 && tree->dothreadedbuild) {
00577                     othreads[totthread].tree= tree;
00578                     othreads[totthread].node= child;
00579                     othreads[totthread].begin= offset[b];
00580                     othreads[totthread].end= offset[b]+count[b];
00581                     othreads[totthread].depth= depth+1;
00582                     BLI_insert_thread(&threads, &othreads[totthread]);
00583                     totthread++;
00584                 }
00585                 else
00586                     occ_build_recursive(tree, child, offset[b], offset[b]+count[b], depth+1);
00587             }
00588         }
00589 
00590         if(depth == 1 && tree->dothreadedbuild)
00591             BLI_end_threads(&threads);
00592     }
00593 
00594     /* combine area, position and sh */
00595     for(b=0; b<TOTCHILD; b++) {
00596         if(node->childflag & (1<<b)) {
00597             child= &tmpnode;
00598             occ_node_from_face(tree->face+node->child[b].face, &tmpnode);
00599         }
00600         else {
00601             child= node->child[b].node;
00602         }
00603 
00604         if(child) {
00605             node->area += child->area;
00606             sh_add(node->sh, node->sh, child->sh);
00607             madd_v3_v3fl(node->co, child->co, child->area);
00608         }
00609     }
00610 
00611     if(node->area != 0.0f)
00612         mul_v3_fl(node->co, 1.0f/node->area);
00613 
00614     /* compute maximum distance from center */
00615     node->dco= 0.0f;
00616     if(node->area > 0.0f)
00617         occ_build_dco(tree, node, node->co, &node->dco);
00618 }
00619 
00620 static void occ_build_sh_normalize(OccNode *node)
00621 {
00622     /* normalize spherical harmonics to not include area, so
00623      * we can clamp the dot product and then mutliply by area */
00624     int b;
00625 
00626     if(node->area != 0.0f)
00627         sh_mul(node->sh, 1.0f/node->area);
00628 
00629     for(b=0; b<TOTCHILD; b++) {
00630         if(node->childflag & (1<<b));
00631         else if(node->child[b].node)
00632             occ_build_sh_normalize(node->child[b].node);
00633     }
00634 }
00635 
00636 static OcclusionTree *occ_tree_build(Render *re)
00637 {
00638     OcclusionTree *tree;
00639     ObjectInstanceRen *obi;
00640     ObjectRen *obr;
00641     Material *ma;
00642     VlakRen *vlr= NULL;
00643     int a, b, c, totface;
00644 
00645     /* count */
00646     totface= 0;
00647     for(obi=re->instancetable.first; obi; obi=obi->next) {
00648         obr= obi->obr;
00649         for(a=0; a<obr->totvlak; a++) {
00650             if((a & 255)==0) vlr= obr->vlaknodes[a>>8].vlak;
00651             else vlr++;
00652 
00653             ma= vlr->mat;
00654 
00655             if((ma->shade_flag & MA_APPROX_OCCLUSION) && (ma->material_type == MA_TYPE_SURFACE))
00656                 totface++;
00657         }
00658     }
00659 
00660     if(totface == 0)
00661         return NULL;
00662     
00663     tree= MEM_callocN(sizeof(OcclusionTree), "OcclusionTree");
00664     tree->totface= totface;
00665 
00666     /* parameters */
00667     tree->error= get_render_aosss_error(&re->r, re->wrld.ao_approx_error);
00668     tree->distfac= (re->wrld.aomode & WO_AODIST)? re->wrld.aodistfac: 0.0f;
00669     tree->doindirect= (re->wrld.ao_indirect_energy > 0.0f && re->wrld.ao_indirect_bounces > 0);
00670 
00671     /* allocation */
00672     tree->arena= BLI_memarena_new(0x8000 * sizeof(OccNode), "occ tree arena");
00673     BLI_memarena_use_calloc(tree->arena);
00674 
00675     if(re->wrld.aomode & WO_AOCACHE)
00676         tree->cache= MEM_callocN(sizeof(OcclusionCache)*BLENDER_MAX_THREADS, "OcclusionCache");
00677 
00678     tree->face= MEM_callocN(sizeof(OccFace)*totface, "OcclusionFace");
00679     tree->co= MEM_callocN(sizeof(float)*3*totface, "OcclusionCo");
00680     tree->occlusion= MEM_callocN(sizeof(float)*totface, "OcclusionOcclusion");
00681 
00682     if(tree->doindirect)
00683         tree->rad= MEM_callocN(sizeof(float)*3*totface, "OcclusionRad");
00684 
00685     /* make array of face pointers */
00686     for(b=0, c=0, obi=re->instancetable.first; obi; obi=obi->next, c++) {
00687         obr= obi->obr;
00688         for(a=0; a<obr->totvlak; a++) {
00689             if((a & 255)==0) vlr= obr->vlaknodes[a>>8].vlak;
00690             else vlr++;
00691 
00692             ma= vlr->mat;
00693 
00694             if((ma->shade_flag & MA_APPROX_OCCLUSION) && (ma->material_type == MA_TYPE_SURFACE)) {
00695                 tree->face[b].obi= c;
00696                 tree->face[b].facenr= a;
00697                 tree->occlusion[b]= 1.0f;
00698                 occ_face(&tree->face[b], tree->co[b], NULL, NULL); 
00699                 b++;
00700             }
00701         }
00702     }
00703 
00704     /* threads */
00705     tree->totbuildthread= (re->r.threads > 1 && totface > 10000)? 8: 1;
00706     tree->dothreadedbuild= (tree->totbuildthread > 1);
00707 
00708     /* recurse */
00709     tree->root= BLI_memarena_alloc(tree->arena, sizeof(OccNode));
00710     tree->maxdepth= 1;
00711     occ_build_recursive(tree, tree->root, 0, totface, 1);
00712 
00713     if(tree->doindirect) {
00714         occ_build_shade(re, tree);
00715         occ_sum_occlusion(tree, tree->root);
00716     }
00717     
00718     MEM_freeN(tree->co);
00719     tree->co= NULL;
00720 
00721     occ_build_sh_normalize(tree->root);
00722 
00723     for(a=0; a<BLENDER_MAX_THREADS; a++)
00724         tree->stack[a]= MEM_callocN(sizeof(OccNode)*TOTCHILD*(tree->maxdepth+1), "OccStack");
00725 
00726     return tree;
00727 }
00728 
00729 static void occ_free_tree(OcclusionTree *tree)
00730 {
00731     int a;
00732 
00733     if(tree) {
00734         if(tree->arena) BLI_memarena_free(tree->arena);
00735         for(a=0; a<BLENDER_MAX_THREADS; a++)
00736             if(tree->stack[a])
00737                 MEM_freeN(tree->stack[a]);
00738         if(tree->occlusion) MEM_freeN(tree->occlusion);
00739         if(tree->cache) MEM_freeN(tree->cache);
00740         if(tree->face) MEM_freeN(tree->face);
00741         if(tree->rad) MEM_freeN(tree->rad);
00742         MEM_freeN(tree);
00743     }
00744 }
00745 
00746 /* ------------------------- Traversal --------------------------- */
00747 
00748 static float occ_solid_angle(OccNode *node, const float v[3], float d2, float invd2, const float receivenormal[3])
00749 {
00750     float dotreceive, dotemit;
00751     float ev[3];
00752 
00753     ev[0]= -v[0]*invd2;
00754     ev[1]= -v[1]*invd2;
00755     ev[2]= -v[2]*invd2;
00756     dotemit= sh_eval(node->sh, ev);
00757     dotreceive= dot_v3v3(receivenormal, v)*invd2;
00758 
00759     CLAMP(dotemit, 0.0f, 1.0f);
00760     CLAMP(dotreceive, 0.0f, 1.0f);
00761     
00762     return ((node->area*dotemit*dotreceive)/(d2 + node->area*INVPI))*INVPI;
00763 }
00764 
00765 static void VecAddDir(float result[3], const float v1[3], const float v2[3], const float fac)
00766 {
00767     result[0]= v1[0] + fac*(v2[0] - v1[0]);
00768     result[1]= v1[1] + fac*(v2[1] - v1[1]);
00769     result[2]= v1[2] + fac*(v2[2] - v1[2]);
00770 }
00771 
00772 static int occ_visible_quad(float *p, const float n[3], const float v0[3], const float *v1, const float *v2, float q0[3], float q1[3], float q2[3], float q3[3])
00773 {
00774     static const float epsilon = 1e-6f;
00775     float c, sd[3];
00776     
00777     c= dot_v3v3(n, p);
00778 
00779     /* signed distances from the vertices to the plane. */
00780     sd[0]= dot_v3v3(n, v0) - c;
00781     sd[1]= dot_v3v3(n, v1) - c;
00782     sd[2]= dot_v3v3(n, v2) - c;
00783 
00784     if(fabsf(sd[0]) < epsilon) sd[0] = 0.0f;
00785     if(fabsf(sd[1]) < epsilon) sd[1] = 0.0f;
00786     if(fabsf(sd[2]) < epsilon) sd[2] = 0.0f;
00787 
00788     if(sd[0] > 0) {
00789         if(sd[1] > 0) {
00790             if(sd[2] > 0) {
00791                 // +++
00792                 copy_v3_v3(q0, v0);
00793                 copy_v3_v3(q1, v1);
00794                 copy_v3_v3(q2, v2);
00795                 copy_v3_v3(q3, q2);
00796             }
00797             else if(sd[2] < 0) {
00798                 // ++-
00799                 copy_v3_v3(q0, v0);
00800                 copy_v3_v3(q1, v1);
00801                 VecAddDir(q2, v1, v2, (sd[1]/(sd[1]-sd[2])));
00802                 VecAddDir(q3, v0, v2, (sd[0]/(sd[0]-sd[2])));
00803             }
00804             else {
00805                 // ++0
00806                 copy_v3_v3(q0, v0);
00807                 copy_v3_v3(q1, v1);
00808                 copy_v3_v3(q2, v2);
00809                 copy_v3_v3(q3, q2);
00810             }
00811         }
00812         else if(sd[1] < 0) {
00813             if(sd[2] > 0) {
00814                 // +-+
00815                 copy_v3_v3(q0, v0);
00816                 VecAddDir(q1, v0, v1, (sd[0]/(sd[0]-sd[1])));
00817                 VecAddDir(q2, v1, v2, (sd[1]/(sd[1]-sd[2])));
00818                 copy_v3_v3(q3, v2);
00819             }
00820             else if(sd[2] < 0) {
00821                 // +--
00822                 copy_v3_v3(q0, v0);
00823                 VecAddDir(q1, v0, v1, (sd[0]/(sd[0]-sd[1])));
00824                 VecAddDir(q2, v0, v2, (sd[0]/(sd[0]-sd[2])));
00825                 copy_v3_v3(q3, q2);
00826             }
00827             else {
00828                 // +-0
00829                 copy_v3_v3(q0, v0);
00830                 VecAddDir(q1, v0, v1, (sd[0]/(sd[0]-sd[1])));
00831                 copy_v3_v3(q2, v2);
00832                 copy_v3_v3(q3, q2);
00833             }
00834         }
00835         else {
00836             if(sd[2] > 0) {
00837                 // +0+
00838                 copy_v3_v3(q0, v0);
00839                 copy_v3_v3(q1, v1);
00840                 copy_v3_v3(q2, v2);
00841                 copy_v3_v3(q3, q2);
00842             }
00843             else if(sd[2] < 0) {
00844                 // +0-
00845                 copy_v3_v3(q0, v0);
00846                 copy_v3_v3(q1, v1);
00847                 VecAddDir(q2, v0, v2, (sd[0]/(sd[0]-sd[2])));
00848                 copy_v3_v3(q3, q2);
00849             }
00850             else {
00851                 // +00
00852                 copy_v3_v3(q0, v0);
00853                 copy_v3_v3(q1, v1);
00854                 copy_v3_v3(q2, v2);
00855                 copy_v3_v3(q3, q2);
00856             }
00857         }
00858     }
00859     else if(sd[0] < 0) {
00860         if(sd[1] > 0) {
00861             if(sd[2] > 0) {
00862                 // -++
00863                 VecAddDir(q0, v0, v1, (sd[0]/(sd[0]-sd[1])));
00864                 copy_v3_v3(q1, v1);
00865                 copy_v3_v3(q2, v2);
00866                 VecAddDir(q3, v0, v2, (sd[0]/(sd[0]-sd[2])));
00867             }
00868             else if(sd[2] < 0) {
00869                 // -+-
00870                 VecAddDir(q0, v0, v1, (sd[0]/(sd[0]-sd[1])));
00871                 copy_v3_v3(q1, v1);
00872                 VecAddDir(q2, v1, v2, (sd[1]/(sd[1]-sd[2])));
00873                 copy_v3_v3(q3, q2);
00874             }
00875             else {
00876                 // -+0
00877                 VecAddDir(q0, v0, v1, (sd[0]/(sd[0]-sd[1])));
00878                 copy_v3_v3(q1, v1);
00879                 copy_v3_v3(q2, v2);
00880                 copy_v3_v3(q3, q2);
00881             }
00882         }
00883         else if(sd[1] < 0) {
00884             if(sd[2] > 0) {
00885                 // --+
00886                 VecAddDir(q0, v0, v2, (sd[0]/(sd[0]-sd[2])));
00887                 VecAddDir(q1, v1, v2, (sd[1]/(sd[1]-sd[2])));
00888                 copy_v3_v3(q2, v2);
00889                 copy_v3_v3(q3, q2);
00890             }
00891             else if(sd[2] < 0) {
00892                 // ---
00893                 return 0;
00894             }
00895             else {
00896                 // --0
00897                 return 0;
00898             }
00899         }
00900         else {
00901             if(sd[2] > 0) {
00902                 // -0+
00903                 VecAddDir(q0, v0, v2, (sd[0]/(sd[0]-sd[2])));
00904                 copy_v3_v3(q1, v1);
00905                 copy_v3_v3(q2, v2);
00906                 copy_v3_v3(q3, q2);
00907             }
00908             else if(sd[2] < 0) {
00909                 // -0-
00910                 return 0;
00911             }
00912             else {
00913                 // -00
00914                 return 0;
00915             }
00916         }
00917     }
00918     else {
00919         if(sd[1] > 0) {
00920             if(sd[2] > 0) {
00921                 // 0++
00922                 copy_v3_v3(q0, v0);
00923                 copy_v3_v3(q1, v1);
00924                 copy_v3_v3(q2, v2);
00925                 copy_v3_v3(q3, q2);
00926             }
00927             else if(sd[2] < 0) {
00928                 // 0+-
00929                 copy_v3_v3(q0, v0);
00930                 copy_v3_v3(q1, v1);
00931                 VecAddDir(q2, v1, v2, (sd[1]/(sd[1]-sd[2])));
00932                 copy_v3_v3(q3, q2);
00933             }
00934             else {
00935                 // 0+0
00936                 copy_v3_v3(q0, v0);
00937                 copy_v3_v3(q1, v1);
00938                 copy_v3_v3(q2, v2);
00939                 copy_v3_v3(q3, q2);
00940             }
00941         }
00942         else if(sd[1] < 0) {
00943             if(sd[2] > 0) {
00944                 // 0-+
00945                 copy_v3_v3(q0, v0);
00946                 VecAddDir(q1, v1, v2, (sd[1]/(sd[1]-sd[2])));
00947                 copy_v3_v3(q2, v2);
00948                 copy_v3_v3(q3, q2);
00949             }
00950             else if(sd[2] < 0) {
00951                 // 0--
00952                 return 0;
00953             }
00954             else {
00955                 // 0-0
00956                 return 0;
00957             }
00958         }
00959         else {
00960             if(sd[2] > 0) {
00961                 // 00+
00962                 copy_v3_v3(q0, v0);
00963                 copy_v3_v3(q1, v1);
00964                 copy_v3_v3(q2, v2);
00965                 copy_v3_v3(q3, q2);
00966             }
00967             else if(sd[2] < 0) {
00968                 // 00-
00969                 return 0;
00970             }
00971             else {
00972                 // 000
00973                 return 0;
00974             }
00975         }
00976     }
00977 
00978     return 1;
00979 }
00980 
00981 /* altivec optimization, this works, but is unused */
00982 
00983 #if 0
00984 #include <Accelerate/Accelerate.h>
00985 
00986 typedef union {
00987     vFloat v;
00988     float f[4];
00989 } vFloatResult;
00990 
00991 static vFloat vec_splat_float(float val)
00992 {
00993     return (vFloat){val, val, val, val};
00994 }
00995 
00996 static float occ_quad_form_factor(float *p, float *n, float *q0, float *q1, float *q2, float *q3)
00997 {
00998     vFloat vcos, rlen, vrx, vry, vrz, vsrx, vsry, vsrz, gx, gy, gz, vangle;
00999     vUInt8 rotate = (vUInt8){4,5,6,7,8,9,10,11,12,13,14,15,0,1,2,3};
01000     vFloatResult vresult;
01001     float result;
01002 
01003     /* compute r* */
01004     vrx = (vFloat){q0[0], q1[0], q2[0], q3[0]} - vec_splat_float(p[0]);
01005     vry = (vFloat){q0[1], q1[1], q2[1], q3[1]} - vec_splat_float(p[1]);
01006     vrz = (vFloat){q0[2], q1[2], q2[2], q3[2]} - vec_splat_float(p[2]);
01007 
01008     /* normalize r* */
01009     rlen = vec_rsqrte(vrx*vrx + vry*vry + vrz*vrz + vec_splat_float(1e-16f));
01010     vrx = vrx*rlen;
01011     vry = vry*rlen;
01012     vrz = vrz*rlen;
01013 
01014     /* rotate r* for cross and dot */
01015     vsrx= vec_perm(vrx, vrx, rotate);
01016     vsry= vec_perm(vry, vry, rotate);
01017     vsrz= vec_perm(vrz, vrz, rotate);
01018 
01019     /* cross product */
01020     gx = vsry*vrz - vsrz*vry;
01021     gy = vsrz*vrx - vsrx*vrz;
01022     gz = vsrx*vry - vsry*vrx;
01023 
01024     /* normalize */
01025     rlen = vec_rsqrte(gx*gx + gy*gy + gz*gz + vec_splat_float(1e-16f));
01026     gx = gx*rlen;
01027     gy = gy*rlen;
01028     gz = gz*rlen;
01029 
01030     /* angle */
01031     vcos = vrx*vsrx + vry*vsry + vrz*vsrz;
01032     vcos= vec_max(vec_min(vcos, vec_splat_float(1.0f)), vec_splat_float(-1.0f));
01033     vangle= vacosf(vcos);
01034 
01035     /* dot */
01036     vresult.v = (vec_splat_float(n[0])*gx +
01037                  vec_splat_float(n[1])*gy +
01038                  vec_splat_float(n[2])*gz)*vangle;
01039 
01040     result= (vresult.f[0] + vresult.f[1] + vresult.f[2] + vresult.f[3])*(0.5f/(float)M_PI);
01041     result= MAX2(result, 0.0f);
01042 
01043     return result;
01044 }
01045 
01046 #endif
01047 
01048 /* SSE optimization, acos code doesn't work */
01049 
01050 #if 0
01051 
01052 #include <xmmintrin.h>
01053 
01054 static __m128 sse_approx_acos(__m128 x)
01055 {
01056     /* needs a better approximation than taylor expansion of acos, since that
01057      * gives big erros for near 1.0 values, sqrt(2*x)*acos(1-x) should work
01058      * better, see http://www.tom.womack.net/projects/sse-fast-arctrig.html */
01059 
01060     return _mm_set_ps1(1.0f);
01061 }
01062 
01063 static float occ_quad_form_factor(float *p, float *n, float *q0, float *q1, float *q2, float *q3)
01064 {
01065     float r0[3], r1[3], r2[3], r3[3], g0[3], g1[3], g2[3], g3[3];
01066     float a1, a2, a3, a4, dot1, dot2, dot3, dot4, result;
01067     float fresult[4] __attribute__((aligned(16)));
01068     __m128 qx, qy, qz, rx, ry, rz, rlen, srx, sry, srz, gx, gy, gz, glen, rcos, angle, aresult;
01069 
01070     /* compute r */
01071     qx = _mm_set_ps(q3[0], q2[0], q1[0], q0[0]);
01072     qy = _mm_set_ps(q3[1], q2[1], q1[1], q0[1]);
01073     qz = _mm_set_ps(q3[2], q2[2], q1[2], q0[2]);
01074 
01075     rx = qx - _mm_set_ps1(p[0]);
01076     ry = qy - _mm_set_ps1(p[1]);
01077     rz = qz - _mm_set_ps1(p[2]);
01078 
01079     /* normalize r */
01080     rlen = _mm_rsqrt_ps(rx*rx + ry*ry + rz*rz + _mm_set_ps1(1e-16f));
01081     rx = rx*rlen;
01082     ry = ry*rlen;
01083     rz = rz*rlen;
01084 
01085     /* cross product */
01086     srx = _mm_shuffle_ps(rx, rx, _MM_SHUFFLE(0,3,2,1));
01087     sry = _mm_shuffle_ps(ry, ry, _MM_SHUFFLE(0,3,2,1));
01088     srz = _mm_shuffle_ps(rz, rz, _MM_SHUFFLE(0,3,2,1));
01089 
01090     gx = sry*rz - srz*ry;
01091     gy = srz*rx - srx*rz;
01092     gz = srx*ry - sry*rx;
01093 
01094     /* normalize g */
01095     glen = _mm_rsqrt_ps(gx*gx + gy*gy + gz*gz + _mm_set_ps1(1e-16f));
01096     gx = gx*glen;
01097     gy = gy*glen;
01098     gz = gz*glen;
01099 
01100     /* compute angle */
01101     rcos = rx*srx + ry*sry + rz*srz;
01102     rcos= _mm_max_ps(_mm_min_ps(rcos, _mm_set_ps1(1.0f)), _mm_set_ps1(-1.0f));
01103 
01104     angle = sse_approx_cos(rcos);
01105     aresult = (_mm_set_ps1(n[0])*gx + _mm_set_ps1(n[1])*gy + _mm_set_ps1(n[2])*gz)*angle;
01106 
01107     /* sum together */
01108     result= (fresult[0] + fresult[1] + fresult[2] + fresult[3])*(0.5f/(float)M_PI);
01109     result= MAX2(result, 0.0f);
01110 
01111     return result;
01112 }
01113 
01114 #endif
01115 
01116 static void normalizef(float *n)
01117 {
01118     float d;
01119     
01120     d= dot_v3v3(n, n);
01121 
01122     if(d > 1.0e-35F) {
01123         d= 1.0f/sqrtf(d);
01124 
01125         n[0] *= d; 
01126         n[1] *= d; 
01127         n[2] *= d;
01128     } 
01129 }
01130 
01131 static float occ_quad_form_factor(const float p[3], const float n[3], const float q0[3], const float q1[3], const float q2[3], const float q3[3])
01132 {
01133     float r0[3], r1[3], r2[3], r3[3], g0[3], g1[3], g2[3], g3[3];
01134     float a1, a2, a3, a4, dot1, dot2, dot3, dot4, result;
01135 
01136     sub_v3_v3v3(r0, q0, p);
01137     sub_v3_v3v3(r1, q1, p);
01138     sub_v3_v3v3(r2, q2, p);
01139     sub_v3_v3v3(r3, q3, p);
01140 
01141     normalizef(r0);
01142     normalizef(r1);
01143     normalizef(r2);
01144     normalizef(r3);
01145 
01146     cross_v3_v3v3(g0, r1, r0); normalizef(g0);
01147     cross_v3_v3v3(g1, r2, r1); normalizef(g1);
01148     cross_v3_v3v3(g2, r3, r2); normalizef(g2);
01149     cross_v3_v3v3(g3, r0, r3); normalizef(g3);
01150 
01151     a1= saacosf(dot_v3v3(r0, r1));
01152     a2= saacosf(dot_v3v3(r1, r2));
01153     a3= saacosf(dot_v3v3(r2, r3));
01154     a4= saacosf(dot_v3v3(r3, r0));
01155 
01156     dot1= dot_v3v3(n, g0);
01157     dot2= dot_v3v3(n, g1);
01158     dot3= dot_v3v3(n, g2);
01159     dot4= dot_v3v3(n, g3);
01160 
01161     result= (a1*dot1 + a2*dot2 + a3*dot3 + a4*dot4)*0.5f/(float)M_PI;
01162     result= MAX2(result, 0.0f);
01163 
01164     return result;
01165 }
01166 
01167 static float occ_form_factor(OccFace *face, float *p, float *n)
01168 {
01169     ObjectInstanceRen *obi;
01170     VlakRen *vlr;
01171     float v1[3], v2[3], v3[3], v4[3], q0[3], q1[3], q2[3], q3[3], contrib= 0.0f;
01172 
01173     obi= &R.objectinstance[face->obi];
01174     vlr= RE_findOrAddVlak(obi->obr, face->facenr);
01175 
01176     copy_v3_v3(v1, vlr->v1->co);
01177     copy_v3_v3(v2, vlr->v2->co);
01178     copy_v3_v3(v3, vlr->v3->co);
01179 
01180     if(obi->flag & R_TRANSFORMED) {
01181         mul_m4_v3(obi->mat, v1);
01182         mul_m4_v3(obi->mat, v2);
01183         mul_m4_v3(obi->mat, v3);
01184     }
01185 
01186     if(occ_visible_quad(p, n, v1, v2, v3, q0, q1, q2, q3))
01187         contrib += occ_quad_form_factor(p, n, q0, q1, q2, q3);
01188 
01189     if(vlr->v4) {
01190         copy_v3_v3(v4, vlr->v4->co);
01191         if(obi->flag & R_TRANSFORMED)
01192             mul_m4_v3(obi->mat, v4);
01193 
01194         if(occ_visible_quad(p, n, v1, v3, v4, q0, q1, q2, q3))
01195             contrib += occ_quad_form_factor(p, n, q0, q1, q2, q3);
01196     }
01197 
01198     return contrib;
01199 }
01200 
01201 static void occ_lookup(OcclusionTree *tree, int thread, OccFace *exclude, float *pp, float *pn, float *occ, float rad[3], float bentn[3])
01202 {
01203     OccNode *node, **stack;
01204     OccFace *face;
01205     float resultocc, resultrad[3], v[3], p[3], n[3], co[3], invd2;
01206     float distfac, fac, error, d2, weight, emitarea;
01207     int b, f, totstack;
01208 
01209     /* init variables */
01210     copy_v3_v3(p, pp);
01211     copy_v3_v3(n, pn);
01212     madd_v3_v3fl(p, n, 1e-4f);
01213 
01214     if(bentn)
01215         copy_v3_v3(bentn, n);
01216     
01217     error= tree->error;
01218     distfac= tree->distfac;
01219 
01220     resultocc= 0.0f;
01221     zero_v3(resultrad);
01222 
01223     /* init stack */
01224     stack= tree->stack[thread];
01225     stack[0]= tree->root;
01226     totstack= 1;
01227 
01228     while(totstack) {
01229         /* pop point off the stack */
01230         node= stack[--totstack];
01231 
01232         sub_v3_v3v3(v, node->co, p);
01233         d2= dot_v3v3(v, v) + 1e-16f;
01234         emitarea= MAX2(node->area, node->dco);
01235 
01236         if(d2*error > emitarea) {
01237             if(distfac != 0.0f) {
01238                 fac= 1.0f/(1.0f + distfac*d2);
01239                 if(fac < 0.01f)
01240                     continue;
01241             }
01242             else
01243                 fac= 1.0f;
01244 
01245             /* accumulate occlusion from spherical harmonics */
01246             invd2 = 1.0f/sqrtf(d2);
01247             weight= occ_solid_angle(node, v, d2, invd2, n);
01248 
01249             if(rad)
01250                 madd_v3_v3fl(resultrad, node->rad, weight*fac);
01251 
01252             weight *= node->occlusion;
01253 
01254             if(bentn) {
01255                 bentn[0] -= weight*invd2*v[0];
01256                 bentn[1] -= weight*invd2*v[1];
01257                 bentn[2] -= weight*invd2*v[2];
01258             }
01259 
01260             resultocc += weight*fac;
01261         }
01262         else {
01263             /* traverse into children */
01264             for(b=0; b<TOTCHILD; b++) {
01265                 if(node->childflag & (1<<b)) {
01266                     f= node->child[b].face;
01267                     face= &tree->face[f];
01268 
01269                     /* accumulate occlusion with face form factor */
01270                     if(!exclude || !(face->obi == exclude->obi && face->facenr == exclude->facenr)) {
01271                         if(bentn || distfac != 0.0f) {
01272                             occ_face(face, co, NULL, NULL); 
01273                             sub_v3_v3v3(v, co, p);
01274                             d2= dot_v3v3(v, v) + 1e-16f;
01275 
01276                             fac= (distfac == 0.0f)? 1.0f: 1.0f/(1.0f + distfac*d2);
01277                             if(fac < 0.01f)
01278                                 continue;
01279                         }
01280                         else
01281                             fac= 1.0f;
01282 
01283                         weight= occ_form_factor(face, p, n);
01284 
01285                         if(rad)
01286                             madd_v3_v3fl(resultrad, tree->rad[f], weight*fac);
01287 
01288                         weight *= tree->occlusion[f];
01289 
01290                         if(bentn) {
01291                             invd2= 1.0f/sqrtf(d2);
01292                             bentn[0] -= weight*invd2*v[0];
01293                             bentn[1] -= weight*invd2*v[1];
01294                             bentn[2] -= weight*invd2*v[2];
01295                         }
01296 
01297                         resultocc += weight*fac;
01298                     }
01299                 }
01300                 else if(node->child[b].node) {
01301                     /* push child on the stack */
01302                     stack[totstack++]= node->child[b].node;
01303                 }
01304             }
01305         }
01306     }
01307 
01308     if(occ) *occ= resultocc;
01309     if(rad) copy_v3_v3(rad, resultrad);
01310     /*if(rad && exclude) {
01311         int a;
01312         for(a=0; a<tree->totface; a++)
01313             if((tree->face[a].obi == exclude->obi && tree->face[a].facenr == exclude->facenr))
01314                 copy_v3_v3(rad, tree->rad[a]);
01315     }*/
01316     if(bentn) normalize_v3(bentn);
01317 }
01318 
01319 static void occ_compute_bounces(Render *re, OcclusionTree *tree, int totbounce)
01320 {
01321     float (*rad)[3], (*sum)[3], (*tmp)[3], co[3], n[3], occ;
01322     int bounce, i;
01323 
01324     rad= MEM_callocN(sizeof(float)*3*tree->totface, "OcclusionBounceRad");
01325     sum= MEM_dupallocN(tree->rad);
01326 
01327     for(bounce=1; bounce<totbounce; bounce++) {
01328         for(i=0; i<tree->totface; i++) {
01329             occ_face(&tree->face[i], co, n, NULL);
01330             madd_v3_v3fl(co, n, 1e-8f);
01331 
01332             occ_lookup(tree, 0, &tree->face[i], co, n, &occ, rad[i], NULL);
01333             rad[i][0]= MAX2(rad[i][0], 0.0f);
01334             rad[i][1]= MAX2(rad[i][1], 0.0f);
01335             rad[i][2]= MAX2(rad[i][2], 0.0f);
01336             add_v3_v3(sum[i], rad[i]);
01337 
01338             if(re->test_break(re->tbh))
01339                 break;
01340         }
01341 
01342         if(re->test_break(re->tbh))
01343             break;
01344 
01345         tmp= tree->rad;
01346         tree->rad= rad;
01347         rad= tmp;
01348 
01349         occ_sum_occlusion(tree, tree->root);
01350     }
01351 
01352     MEM_freeN(rad);
01353     MEM_freeN(tree->rad);
01354     tree->rad= sum;
01355 
01356     if(!re->test_break(re->tbh))
01357         occ_sum_occlusion(tree, tree->root);
01358 }
01359 
01360 static void occ_compute_passes(Render *re, OcclusionTree *tree, int totpass)
01361 {
01362     float *occ, co[3], n[3];
01363     int pass, i;
01364     
01365     occ= MEM_callocN(sizeof(float)*tree->totface, "OcclusionPassOcc");
01366 
01367     for(pass=0; pass<totpass; pass++) {
01368         for(i=0; i<tree->totface; i++) {
01369             occ_face(&tree->face[i], co, n, NULL);
01370             negate_v3(n);
01371             madd_v3_v3fl(co, n, 1e-8f);
01372 
01373             occ_lookup(tree, 0, &tree->face[i], co, n, &occ[i], NULL, NULL);
01374             if(re->test_break(re->tbh))
01375                 break;
01376         }
01377 
01378         if(re->test_break(re->tbh))
01379             break;
01380 
01381         for(i=0; i<tree->totface; i++) {
01382             tree->occlusion[i] -= occ[i]; //MAX2(1.0f-occ[i], 0.0f);
01383             if(tree->occlusion[i] < 0.0f)
01384                 tree->occlusion[i]= 0.0f;
01385         }
01386 
01387         occ_sum_occlusion(tree, tree->root);
01388     }
01389 
01390     MEM_freeN(occ);
01391 }
01392 
01393 static void sample_occ_tree(Render *re, OcclusionTree *tree, OccFace *exclude, float *co, float *n, int thread, int onlyshadow, float *ao, float *env, float *indirect)
01394 {
01395     float nn[3], bn[3], fac, occ, occlusion, correction, rad[3];
01396     int envcolor;
01397 
01398     envcolor= re->wrld.aocolor;
01399     if(onlyshadow)
01400         envcolor= WO_AOPLAIN;
01401 
01402     negate_v3_v3(nn, n);
01403 
01404     occ_lookup(tree, thread, exclude, co, nn, &occ, (tree->doindirect)? rad: NULL, (env && envcolor)? bn: NULL);
01405 
01406     correction= re->wrld.ao_approx_correction;
01407 
01408     occlusion= (1.0f-correction)*(1.0f-occ);
01409     CLAMP(occlusion, 0.0f, 1.0f);
01410     if(correction != 0.0f)
01411         occlusion += correction*exp(-occ);
01412 
01413     if(env) {
01414         /* sky shading using bent normal */
01415         if(ELEM(envcolor, WO_AOSKYCOL, WO_AOSKYTEX)) {
01416             fac= 0.5f*(1.0f+bn[0]*re->grvec[0]+ bn[1]*re->grvec[1]+ bn[2]*re->grvec[2]);
01417             env[0]= (1.0f-fac)*re->wrld.horr + fac*re->wrld.zenr;
01418             env[1]= (1.0f-fac)*re->wrld.horg + fac*re->wrld.zeng;
01419             env[2]= (1.0f-fac)*re->wrld.horb + fac*re->wrld.zenb;
01420 
01421             mul_v3_fl(env, occlusion);
01422         }
01423         else {
01424             env[0]= occlusion;
01425             env[1]= occlusion;
01426             env[2]= occlusion;
01427         }
01428 #if 0
01429         else {  /* WO_AOSKYTEX */
01430             float dxyview[3];
01431             bn[0]= -bn[0];
01432             bn[1]= -bn[1];
01433             bn[2]= -bn[2];
01434             dxyview[0]= 1.0f;
01435             dxyview[1]= 1.0f;
01436             dxyview[2]= 0.0f;
01437             shadeSkyView(ao, co, bn, dxyview);
01438         }
01439 #endif
01440     }
01441 
01442     if(ao) {
01443         ao[0]= occlusion;
01444         ao[1]= occlusion;
01445         ao[2]= occlusion;
01446     }
01447 
01448     if(tree->doindirect) copy_v3_v3(indirect, rad);
01449     else zero_v3(indirect);
01450 }
01451 
01452 /* ---------------------------- Caching ------------------------------- */
01453 
01454 static OcclusionCacheSample *find_occ_sample(OcclusionCache *cache, int x, int y)
01455 {
01456     x -= cache->x;
01457     y -= cache->y;
01458 
01459     x /= cache->step;
01460     y /= cache->step;
01461     x *= cache->step;
01462     y *= cache->step;
01463 
01464     if(x < 0 || x >= cache->w || y < 0 || y >= cache->h)
01465         return NULL;
01466     else
01467         return &cache->sample[y*cache->w + x];
01468 }
01469 
01470 static int sample_occ_cache(OcclusionTree *tree, float *co, float *n, int x, int y, int thread, float *ao, float *env, float *indirect)
01471 {
01472     OcclusionCache *cache;
01473     OcclusionCacheSample *samples[4], *sample;
01474     float wn[4], wz[4], wb[4], tx, ty, w, totw, mino, maxo;
01475     float d[3], dist2;
01476     int i, x1, y1, x2, y2;
01477 
01478     if(!tree->cache)
01479         return 0;
01480     
01481     /* first try to find a sample in the same pixel */
01482     cache= &tree->cache[thread];
01483 
01484     if(cache->sample && cache->step) {
01485         sample= &cache->sample[(y-cache->y)*cache->w + (x-cache->x)];
01486         if(sample->filled) {
01487             sub_v3_v3v3(d, sample->co, co);
01488             dist2= dot_v3v3(d, d);
01489             if(dist2 < 0.5f*sample->dist2 && dot_v3v3(sample->n, n) > 0.98f) {
01490                 copy_v3_v3(ao, sample->ao);
01491                 copy_v3_v3(env, sample->env);
01492                 copy_v3_v3(indirect, sample->indirect);
01493                 return 1;
01494             }
01495         }
01496     }
01497     else
01498         return 0;
01499 
01500     /* try to interpolate between 4 neighbouring pixels */
01501     samples[0]= find_occ_sample(cache, x, y);
01502     samples[1]= find_occ_sample(cache, x+cache->step, y);
01503     samples[2]= find_occ_sample(cache, x, y+cache->step);
01504     samples[3]= find_occ_sample(cache, x+cache->step, y+cache->step);
01505 
01506     for(i=0; i<4; i++)
01507         if(!samples[i] || !samples[i]->filled)
01508             return 0;
01509 
01510     /* require intensities not being too different */
01511     mino= MIN4(samples[0]->intensity, samples[1]->intensity, samples[2]->intensity, samples[3]->intensity);
01512     maxo= MAX4(samples[0]->intensity, samples[1]->intensity, samples[2]->intensity, samples[3]->intensity);
01513 
01514     if(maxo - mino > 0.05f)
01515         return 0;
01516 
01517     /* compute weighted interpolation between samples */
01518     zero_v3(ao);
01519     zero_v3(env);
01520     zero_v3(indirect);
01521     totw= 0.0f;
01522 
01523     x1= samples[0]->x;
01524     y1= samples[0]->y;
01525     x2= samples[3]->x;
01526     y2= samples[3]->y;
01527 
01528     tx= (float)(x2 - x)/(float)(x2 - x1);
01529     ty= (float)(y2 - y)/(float)(y2 - y1);
01530 
01531     wb[3]= (1.0f-tx)*(1.0f-ty);
01532     wb[2]= (tx)*(1.0f-ty);
01533     wb[1]= (1.0f-tx)*(ty);
01534     wb[0]= tx*ty;
01535 
01536     for(i=0; i<4; i++) {
01537         sub_v3_v3v3(d, samples[i]->co, co);
01538         //dist2= dot_v3v3(d, d);
01539 
01540         wz[i]= 1.0f; //(samples[i]->dist2/(1e-4f + dist2));
01541         wn[i]= pow(dot_v3v3(samples[i]->n, n), 32.0f);
01542 
01543         w= wb[i]*wn[i]*wz[i];
01544 
01545         totw += w;
01546         madd_v3_v3fl(ao, samples[i]->ao, w);
01547         madd_v3_v3fl(env, samples[i]->env, w);
01548         madd_v3_v3fl(indirect, samples[i]->indirect, w);
01549     }
01550 
01551     if(totw >= 0.9f) {
01552         totw= 1.0f/totw;
01553         mul_v3_fl(ao, totw);
01554         mul_v3_fl(env, totw);
01555         mul_v3_fl(indirect, totw);
01556         return 1;
01557     }
01558 
01559     return 0;
01560 }
01561 
01562 static void sample_occ_surface(ShadeInput *shi)
01563 {
01564     StrandRen *strand= shi->strand;
01565     StrandSurface *mesh= strand->buffer->surface;
01566     int *face, *index = RE_strandren_get_face(shi->obr, strand, 0);
01567     float w[4], *co1, *co2, *co3, *co4;
01568 
01569     if(mesh && mesh->face && mesh->co && mesh->ao && index) {
01570         face= mesh->face[*index];
01571 
01572         co1= mesh->co[face[0]];
01573         co2= mesh->co[face[1]];
01574         co3= mesh->co[face[2]];
01575         co4= (face[3])? mesh->co[face[3]]: NULL;
01576 
01577         interp_weights_face_v3(w, co1, co2, co3, co4, strand->vert->co);
01578 
01579         zero_v3(shi->ao);
01580         zero_v3(shi->env);
01581         zero_v3(shi->indirect);
01582 
01583         madd_v3_v3fl(shi->ao, mesh->ao[face[0]], w[0]);
01584         madd_v3_v3fl(shi->env, mesh->env[face[0]], w[0]);
01585         madd_v3_v3fl(shi->indirect, mesh->indirect[face[0]], w[0]);
01586         madd_v3_v3fl(shi->ao, mesh->ao[face[1]], w[1]);
01587         madd_v3_v3fl(shi->env, mesh->env[face[1]], w[1]);
01588         madd_v3_v3fl(shi->indirect, mesh->indirect[face[1]], w[1]);
01589         madd_v3_v3fl(shi->ao, mesh->ao[face[2]], w[2]);
01590         madd_v3_v3fl(shi->env, mesh->env[face[2]], w[2]);
01591         madd_v3_v3fl(shi->indirect, mesh->indirect[face[2]], w[2]);
01592         if(face[3]) {
01593             madd_v3_v3fl(shi->ao, mesh->ao[face[3]], w[3]);
01594             madd_v3_v3fl(shi->env, mesh->env[face[3]], w[3]);
01595             madd_v3_v3fl(shi->indirect, mesh->indirect[face[3]], w[3]);
01596         }
01597     }
01598     else {
01599         shi->ao[0]= 1.0f;
01600         shi->ao[1]= 1.0f;
01601         shi->ao[2]= 1.0f;
01602         zero_v3(shi->env);
01603         zero_v3(shi->indirect);
01604     }
01605 }
01606 
01607 /* ------------------------- External Functions --------------------------- */
01608 
01609 static void *exec_strandsurface_sample(void *data)
01610 {
01611     OcclusionThread *othread= (OcclusionThread*)data;
01612     Render *re= othread->re;
01613     StrandSurface *mesh= othread->mesh;
01614     float ao[3], env[3], indirect[3], co[3], n[3], *co1, *co2, *co3, *co4;
01615     int a, *face;
01616 
01617     for(a=othread->begin; a<othread->end; a++) {
01618         face= mesh->face[a];
01619         co1= mesh->co[face[0]];
01620         co2= mesh->co[face[1]];
01621         co3= mesh->co[face[2]];
01622 
01623         if(face[3]) {
01624             co4= mesh->co[face[3]];
01625 
01626             mid_v3_v3v3(co, co1, co3);
01627             normal_quad_v3( n,co1, co2, co3, co4);
01628         }
01629         else {
01630             cent_tri_v3(co, co1, co2, co3);
01631             normal_tri_v3( n,co1, co2, co3);
01632         }
01633         negate_v3(n);
01634 
01635         sample_occ_tree(re, re->occlusiontree, NULL, co, n, othread->thread, 0, ao, env, indirect);
01636         copy_v3_v3(othread->faceao[a], ao);
01637         copy_v3_v3(othread->faceenv[a], env);
01638         copy_v3_v3(othread->faceindirect[a], indirect);
01639     }
01640 
01641     return 0;
01642 }
01643 
01644 void make_occ_tree(Render *re)
01645 {
01646     OcclusionThread othreads[BLENDER_MAX_THREADS];
01647     OcclusionTree *tree;
01648     StrandSurface *mesh;
01649     ListBase threads;
01650     float ao[3], env[3], indirect[3], (*faceao)[3], (*faceenv)[3], (*faceindirect)[3];
01651     int a, totface, totthread, *face, *count;
01652 
01653     /* ugly, needed for occ_face */
01654     R= *re;
01655 
01656     re->i.infostr= "Occlusion preprocessing";
01657     re->stats_draw(re->sdh, &re->i);
01658     
01659     re->occlusiontree= tree= occ_tree_build(re);
01660     
01661     if(tree) {
01662         if(re->wrld.ao_approx_passes > 0)
01663             occ_compute_passes(re, tree, re->wrld.ao_approx_passes);
01664         if(tree->doindirect && (re->wrld.mode & WO_INDIRECT_LIGHT))
01665             occ_compute_bounces(re, tree, re->wrld.ao_indirect_bounces);
01666 
01667         for(mesh=re->strandsurface.first; mesh; mesh=mesh->next) {
01668             if(!mesh->face || !mesh->co || !mesh->ao)
01669                 continue;
01670 
01671             count= MEM_callocN(sizeof(int)*mesh->totvert, "OcclusionCount");
01672             faceao= MEM_callocN(sizeof(float)*3*mesh->totface, "StrandSurfFaceAO");
01673             faceenv= MEM_callocN(sizeof(float)*3*mesh->totface, "StrandSurfFaceEnv");
01674             faceindirect= MEM_callocN(sizeof(float)*3*mesh->totface, "StrandSurfFaceIndirect");
01675 
01676             totthread= (mesh->totface > 10000)? re->r.threads: 1;
01677             totface= mesh->totface/totthread;
01678             for(a=0; a<totthread; a++) {
01679                 othreads[a].re= re;
01680                 othreads[a].faceao= faceao;
01681                 othreads[a].faceenv= faceenv;
01682                 othreads[a].faceindirect= faceindirect;
01683                 othreads[a].thread= a;
01684                 othreads[a].mesh= mesh;
01685                 othreads[a].begin= a*totface;
01686                 othreads[a].end= (a == totthread-1)? mesh->totface: (a+1)*totface;
01687             }
01688 
01689             if(totthread == 1) {
01690                 exec_strandsurface_sample(&othreads[0]);
01691             }
01692             else {
01693                 BLI_init_threads(&threads, exec_strandsurface_sample, totthread);
01694 
01695                 for(a=0; a<totthread; a++)
01696                     BLI_insert_thread(&threads, &othreads[a]);
01697 
01698                 BLI_end_threads(&threads);
01699             }
01700 
01701             for(a=0; a<mesh->totface; a++) {
01702                 face= mesh->face[a];
01703 
01704                 copy_v3_v3(ao, faceao[a]);
01705                 copy_v3_v3(env, faceenv[a]);
01706                 copy_v3_v3(indirect, faceindirect[a]);
01707 
01708                 add_v3_v3(mesh->ao[face[0]], ao);
01709                 add_v3_v3(mesh->env[face[0]], env);
01710                 add_v3_v3(mesh->indirect[face[0]], indirect);
01711                 count[face[0]]++;
01712                 add_v3_v3(mesh->ao[face[1]], ao);
01713                 add_v3_v3(mesh->env[face[1]], env);
01714                 add_v3_v3(mesh->indirect[face[1]], indirect);
01715                 count[face[1]]++;
01716                 add_v3_v3(mesh->ao[face[2]], ao);
01717                 add_v3_v3(mesh->env[face[2]], env);
01718                 add_v3_v3(mesh->indirect[face[2]], indirect);
01719                 count[face[2]]++;
01720 
01721                 if(face[3]) {
01722                     add_v3_v3(mesh->ao[face[3]], ao);
01723                     add_v3_v3(mesh->env[face[3]], env);
01724                     add_v3_v3(mesh->indirect[face[3]], indirect);
01725                     count[face[3]]++;
01726                 }
01727             }
01728 
01729             for(a=0; a<mesh->totvert; a++) {
01730                 if(count[a]) {
01731                     mul_v3_fl(mesh->ao[a], 1.0f/count[a]);
01732                     mul_v3_fl(mesh->env[a], 1.0f/count[a]);
01733                     mul_v3_fl(mesh->indirect[a], 1.0f/count[a]);
01734                 }
01735             }
01736 
01737             MEM_freeN(count);
01738             MEM_freeN(faceao);
01739             MEM_freeN(faceenv);
01740             MEM_freeN(faceindirect);
01741         }
01742     }
01743 }
01744 
01745 void free_occ(Render *re)
01746 {
01747     if(re->occlusiontree) {
01748         occ_free_tree(re->occlusiontree);
01749         re->occlusiontree = NULL;
01750     }
01751 }
01752 
01753 void sample_occ(Render *re, ShadeInput *shi)
01754 {
01755     OcclusionTree *tree= re->occlusiontree;
01756     OcclusionCache *cache;
01757     OcclusionCacheSample *sample;
01758     OccFace exclude;
01759     int onlyshadow;
01760 
01761     if(tree) {
01762         if(shi->strand) {
01763             sample_occ_surface(shi);
01764         }
01765         /* try to get result from the cache if possible */
01766         else if(shi->depth!=0 || !sample_occ_cache(tree, shi->co, shi->vno, shi->xs, shi->ys, shi->thread, shi->ao, shi->env, shi->indirect)) {
01767             /* no luck, let's sample the occlusion */
01768             exclude.obi= shi->obi - re->objectinstance;
01769             exclude.facenr= shi->vlr->index;
01770             onlyshadow= (shi->mat->mode & MA_ONLYSHADOW);
01771             sample_occ_tree(re, tree, &exclude, shi->co, shi->vno, shi->thread, onlyshadow, shi->ao, shi->env, shi->indirect);
01772 
01773             /* fill result into sample, each time */
01774             if(tree->cache) {
01775                 cache= &tree->cache[shi->thread];
01776 
01777                 if(cache->sample && cache->step) {
01778                     sample= &cache->sample[(shi->ys-cache->y)*cache->w + (shi->xs-cache->x)];
01779                     copy_v3_v3(sample->co, shi->co);
01780                     copy_v3_v3(sample->n, shi->vno);
01781                     copy_v3_v3(sample->ao, shi->ao);
01782                     copy_v3_v3(sample->env, shi->env);
01783                     copy_v3_v3(sample->indirect, shi->indirect);
01784                     sample->intensity= MAX3(sample->ao[0], sample->ao[1], sample->ao[2]);
01785                     sample->intensity= MAX2(sample->intensity, MAX3(sample->env[0], sample->env[1], sample->env[2]));
01786                     sample->intensity= MAX2(sample->intensity, MAX3(sample->indirect[0], sample->indirect[1], sample->indirect[2]));
01787                     sample->dist2= dot_v3v3(shi->dxco, shi->dxco) + dot_v3v3(shi->dyco, shi->dyco);
01788                     sample->filled= 1;
01789                 }
01790             }
01791         }
01792     }
01793     else {
01794         shi->ao[0]= 1.0f;
01795         shi->ao[1]= 1.0f;
01796         shi->ao[2]= 1.0f;
01797 
01798         shi->env[0]= 0.0f;
01799         shi->env[1]= 0.0f;
01800         shi->env[2]= 0.0f;
01801 
01802         shi->indirect[0]= 0.0f;
01803         shi->indirect[1]= 0.0f;
01804         shi->indirect[2]= 0.0f;
01805     }
01806 }
01807 
01808 void cache_occ_samples(Render *re, RenderPart *pa, ShadeSample *ssamp)
01809 {
01810     OcclusionTree *tree= re->occlusiontree;
01811     PixStr ps;
01812     OcclusionCache *cache;
01813     OcclusionCacheSample *sample;
01814     OccFace exclude;
01815     ShadeInput *shi;
01816     intptr_t *rd=NULL;
01817     int *ro=NULL, *rp=NULL, *rz=NULL, onlyshadow;
01818     int x, y, step = CACHE_STEP;
01819 
01820     if(!tree->cache)
01821         return;
01822 
01823     cache= &tree->cache[pa->thread];
01824     cache->w= pa->rectx;
01825     cache->h= pa->recty;
01826     cache->x= pa->disprect.xmin;
01827     cache->y= pa->disprect.ymin;
01828     cache->step= step;
01829     cache->sample= MEM_callocN(sizeof(OcclusionCacheSample)*cache->w*cache->h, "OcclusionCacheSample");
01830     sample= cache->sample;
01831 
01832     if(re->osa) {
01833         rd= pa->rectdaps;
01834     }
01835     else {
01836         /* fake pixel struct for non-osa */
01837         ps.next= NULL;
01838         ps.mask= 0xFFFF;
01839 
01840         ro= pa->recto;
01841         rp= pa->rectp;
01842         rz= pa->rectz;
01843     }
01844 
01845     /* compute a sample at every step pixels */
01846     for(y=pa->disprect.ymin; y<pa->disprect.ymax; y++) {
01847         for(x=pa->disprect.xmin; x<pa->disprect.xmax; x++, sample++, rd++, ro++, rp++, rz++) {
01848             if(!(((x - pa->disprect.xmin + step) % step) == 0 || x == pa->disprect.xmax-1))
01849                 continue;
01850             if(!(((y - pa->disprect.ymin + step) % step) == 0 || y == pa->disprect.ymax-1))
01851                 continue;
01852 
01853             if(re->osa) {
01854                 if(!*rd) continue;
01855 
01856                 shade_samples_fill_with_ps(ssamp, (PixStr *)(*rd), x, y);
01857             }
01858             else {
01859                 if(!*rp) continue;
01860 
01861                 ps.obi= *ro;
01862                 ps.facenr= *rp;
01863                 ps.z= *rz;
01864                 shade_samples_fill_with_ps(ssamp, &ps, x, y);
01865             }
01866 
01867             shi= ssamp->shi;
01868             if(shi->vlr) {
01869                 onlyshadow= (shi->mat->mode & MA_ONLYSHADOW);
01870                 exclude.obi= shi->obi - re->objectinstance;
01871                 exclude.facenr= shi->vlr->index;
01872                 sample_occ_tree(re, tree, &exclude, shi->co, shi->vno, shi->thread, onlyshadow, shi->ao, shi->env, shi->indirect);
01873 
01874                 copy_v3_v3(sample->co, shi->co);
01875                 copy_v3_v3(sample->n, shi->vno);
01876                 copy_v3_v3(sample->ao, shi->ao);
01877                 copy_v3_v3(sample->env, shi->env);
01878                 copy_v3_v3(sample->indirect, shi->indirect);
01879                 sample->intensity= MAX3(sample->ao[0], sample->ao[1], sample->ao[2]);
01880                 sample->intensity= MAX2(sample->intensity, MAX3(sample->env[0], sample->env[1], sample->env[2]));
01881                 sample->intensity= MAX2(sample->intensity, MAX3(sample->indirect[0], sample->indirect[1], sample->indirect[2]));
01882                 sample->dist2= dot_v3v3(shi->dxco, shi->dxco) + dot_v3v3(shi->dyco, shi->dyco);
01883                 sample->x= shi->xs;
01884                 sample->y= shi->ys;
01885                 sample->filled= 1;
01886             }
01887 
01888             if(re->test_break(re->tbh))
01889                 break;
01890         }
01891     }
01892 }
01893 
01894 void free_occ_samples(Render *re, RenderPart *pa)
01895 {
01896     OcclusionTree *tree= re->occlusiontree;
01897     OcclusionCache *cache;
01898 
01899     if(tree->cache) {
01900         cache= &tree->cache[pa->thread];
01901 
01902         if(cache->sample)
01903             MEM_freeN(cache->sample);
01904 
01905         cache->w= 0;
01906         cache->h= 0;
01907         cache->step= 0;
01908     }
01909 }
01910