Blender  V2.59
rayobject_octree.cpp
Go to the documentation of this file.
00001 /*
00002  * $Id: rayobject_octree.cpp 35233 2011-02-27 19:31:27Z jesterking $
00003  *
00004  * ***** BEGIN GPL LICENSE BLOCK *****
00005  *
00006  * This program is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU General Public License
00008  * as published by the Free Software Foundation; either version 2
00009  * of the License, or (at your option) any later version. 
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software Foundation,
00018  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00019  *
00020  * The Original Code is Copyright (C) 1990-1998 NeoGeo BV.
00021  * All rights reserved.
00022  *
00023  * Contributors: 2004/2005 Blender Foundation, full recode
00024  *
00025  * ***** END GPL LICENSE BLOCK *****
00026  */
00027 
00033 /* IMPORTANT NOTE: this code must be independent of any other render code
00034    to use it outside the renderer! */
00035 
00036 #include <math.h>
00037 #include <string.h>
00038 #include <stdlib.h>
00039 #include <float.h>
00040 #include <assert.h>
00041 
00042 #include "MEM_guardedalloc.h"
00043 
00044 #include "DNA_material_types.h"
00045 
00046 #include "BLI_math.h"
00047 #include "BLI_utildefines.h"
00048 
00049 #include "rayintersection.h"
00050 #include "rayobject.h"
00051 
00052 /* ********** structs *************** */
00053 #define BRANCH_ARRAY 1024
00054 #define NODE_ARRAY 4096
00055 
00056 typedef struct Branch
00057 {
00058         struct Branch *b[8];
00059 } Branch;
00060 
00061 typedef struct OcVal 
00062 {
00063         short ocx, ocy, ocz;
00064 } OcVal;
00065 
00066 typedef struct Node
00067 {
00068         struct RayFace *v[8];
00069         struct OcVal ov[8];
00070         struct Node *next;
00071 } Node;
00072 
00073 typedef struct Octree {
00074         RayObject rayobj;
00075 
00076         struct Branch **adrbranch;
00077         struct Node **adrnode;
00078         float ocsize;   /* ocsize: mult factor,  max size octree */
00079         float ocfacx,ocfacy,ocfacz;
00080         float min[3], max[3];
00081         int ocres;
00082         int branchcount, nodecount;
00083 
00084         /* during building only */
00085         char *ocface; 
00086         
00087         RayFace **ro_nodes;
00088         int ro_nodes_size, ro_nodes_used;
00089         
00090 } Octree;
00091 
00092 static int  RE_rayobject_octree_intersect(RayObject *o, Isect *isec);
00093 static void RE_rayobject_octree_add(RayObject *o, RayObject *ob);
00094 static void RE_rayobject_octree_done(RayObject *o);
00095 static void RE_rayobject_octree_free(RayObject *o);
00096 static void RE_rayobject_octree_bb(RayObject *o, float *min, float *max);
00097 
00098 /*
00099  * This function is not expected to be called by current code state.
00100  */
00101 static float RE_rayobject_octree_cost(RayObject *o)
00102 {
00103         return 1.0;
00104 }
00105 
00106 static void RE_rayobject_octree_hint_bb(RayObject *o, RayHint *hint, float *min, float *max)
00107 {
00108         return;
00109 }
00110 
00111 static RayObjectAPI octree_api =
00112 {
00113         RE_rayobject_octree_intersect,
00114         RE_rayobject_octree_add,
00115         RE_rayobject_octree_done,
00116         RE_rayobject_octree_free,
00117         RE_rayobject_octree_bb,
00118         RE_rayobject_octree_cost,
00119         RE_rayobject_octree_hint_bb
00120 };
00121 
00122 /* **************** ocval method ******************* */
00123 /* within one octree node, a set of 3x15 bits defines a 'boundbox' to OR with */
00124 
00125 #define OCVALRES        15
00126 #define BROW16(min, max)      (((max)>=OCVALRES? 0xFFFF: (1<<(max+1))-1) - ((min>0)? ((1<<(min))-1):0) )
00127 
00128 static void calc_ocval_face(float *v1, float *v2, float *v3, float *v4, short x, short y, short z, OcVal *ov)
00129 {
00130         float min[3], max[3];
00131         int ocmin, ocmax;
00132         
00133         copy_v3_v3(min, v1);
00134         copy_v3_v3(max, v1);
00135         DO_MINMAX(v2, min, max);
00136         DO_MINMAX(v3, min, max);
00137         if(v4) {
00138                 DO_MINMAX(v4, min, max);
00139         }
00140         
00141         ocmin= OCVALRES*(min[0]-x); 
00142         ocmax= OCVALRES*(max[0]-x);
00143         ov->ocx= BROW16(ocmin, ocmax);
00144         
00145         ocmin= OCVALRES*(min[1]-y); 
00146         ocmax= OCVALRES*(max[1]-y);
00147         ov->ocy= BROW16(ocmin, ocmax);
00148         
00149         ocmin= OCVALRES*(min[2]-z); 
00150         ocmax= OCVALRES*(max[2]-z);
00151         ov->ocz= BROW16(ocmin, ocmax);
00152 
00153 }
00154 
00155 static void calc_ocval_ray(OcVal *ov, float xo, float yo, float zo, float *vec1, float *vec2)
00156 {
00157         int ocmin, ocmax;
00158         
00159         if(vec1[0]<vec2[0]) {
00160                 ocmin= OCVALRES*(vec1[0] - xo);
00161                 ocmax= OCVALRES*(vec2[0] - xo);
00162         } else {
00163                 ocmin= OCVALRES*(vec2[0] - xo);
00164                 ocmax= OCVALRES*(vec1[0] - xo);
00165         }
00166         ov->ocx= BROW16(ocmin, ocmax);
00167 
00168         if(vec1[1]<vec2[1]) {
00169                 ocmin= OCVALRES*(vec1[1] - yo);
00170                 ocmax= OCVALRES*(vec2[1] - yo);
00171         } else {
00172                 ocmin= OCVALRES*(vec2[1] - yo);
00173                 ocmax= OCVALRES*(vec1[1] - yo);
00174         }
00175         ov->ocy= BROW16(ocmin, ocmax);
00176 
00177         if(vec1[2]<vec2[2]) {
00178                 ocmin= OCVALRES*(vec1[2] - zo);
00179                 ocmax= OCVALRES*(vec2[2] - zo);
00180         } else {
00181                 ocmin= OCVALRES*(vec2[2] - zo);
00182                 ocmax= OCVALRES*(vec1[2] - zo);
00183         }
00184         ov->ocz= BROW16(ocmin, ocmax);
00185 }
00186 
00187 /* ************* octree ************** */
00188 
00189 static Branch *addbranch(Octree *oc, Branch *br, short ocb)
00190 {
00191         int index;
00192         
00193         if(br->b[ocb]) return br->b[ocb];
00194         
00195         oc->branchcount++;
00196         index= oc->branchcount>>12;
00197         
00198         if(oc->adrbranch[index]==NULL)
00199                 oc->adrbranch[index]= (Branch*)MEM_callocN(4096*sizeof(Branch), "new oc branch");
00200 
00201         if(oc->branchcount>= BRANCH_ARRAY*4096) {
00202                 printf("error; octree branches full\n");
00203                 oc->branchcount=0;
00204         }
00205         
00206         return br->b[ocb]= oc->adrbranch[index]+(oc->branchcount & 4095);
00207 }
00208 
00209 static Node *addnode(Octree *oc)
00210 {
00211         int index;
00212         
00213         oc->nodecount++;
00214         index= oc->nodecount>>12;
00215         
00216         if(oc->adrnode[index]==NULL)
00217                 oc->adrnode[index]= (Node*)MEM_callocN(4096*sizeof(Node),"addnode");
00218 
00219         if(oc->nodecount> NODE_ARRAY*NODE_ARRAY) {
00220                 printf("error; octree nodes full\n");
00221                 oc->nodecount=0;
00222         }
00223         
00224         return oc->adrnode[index]+(oc->nodecount & 4095);
00225 }
00226 
00227 static int face_in_node(RayFace *face, short x, short y, short z, float rtf[][3])
00228 {
00229         static float nor[3], d;
00230         float fx, fy, fz;
00231         
00232         // init static vars 
00233         if(face) {
00234                 normal_tri_v3( nor,rtf[0], rtf[1], rtf[2]);
00235                 d= -nor[0]*rtf[0][0] - nor[1]*rtf[0][1] - nor[2]*rtf[0][2];
00236                 return 0;
00237         }
00238         
00239         fx= x;
00240         fy= y;
00241         fz= z;
00242         
00243         if((fx)*nor[0] + (fy)*nor[1] + (fz)*nor[2] + d > 0.0f) {
00244                 if((fx+1)*nor[0] + (fy  )*nor[1] + (fz  )*nor[2] + d < 0.0f) return 1;
00245                 if((fx  )*nor[0] + (fy+1)*nor[1] + (fz  )*nor[2] + d < 0.0f) return 1;
00246                 if((fx+1)*nor[0] + (fy+1)*nor[1] + (fz  )*nor[2] + d < 0.0f) return 1;
00247         
00248                 if((fx  )*nor[0] + (fy  )*nor[1] + (fz+1)*nor[2] + d < 0.0f) return 1;
00249                 if((fx+1)*nor[0] + (fy  )*nor[1] + (fz+1)*nor[2] + d < 0.0f) return 1;
00250                 if((fx  )*nor[0] + (fy+1)*nor[1] + (fz+1)*nor[2] + d < 0.0f) return 1;
00251                 if((fx+1)*nor[0] + (fy+1)*nor[1] + (fz+1)*nor[2] + d < 0.0f) return 1;
00252         }
00253         else {
00254                 if((fx+1)*nor[0] + (fy  )*nor[1] + (fz  )*nor[2] + d > 0.0f) return 1;
00255                 if((fx  )*nor[0] + (fy+1)*nor[1] + (fz  )*nor[2] + d > 0.0f) return 1;
00256                 if((fx+1)*nor[0] + (fy+1)*nor[1] + (fz  )*nor[2] + d > 0.0f) return 1;
00257         
00258                 if((fx  )*nor[0] + (fy  )*nor[1] + (fz+1)*nor[2] + d > 0.0f) return 1;
00259                 if((fx+1)*nor[0] + (fy  )*nor[1] + (fz+1)*nor[2] + d > 0.0f) return 1;
00260                 if((fx  )*nor[0] + (fy+1)*nor[1] + (fz+1)*nor[2] + d > 0.0f) return 1;
00261                 if((fx+1)*nor[0] + (fy+1)*nor[1] + (fz+1)*nor[2] + d > 0.0f) return 1;
00262         }
00263         
00264         return 0;
00265 }
00266 
00267 static void ocwrite(Octree *oc, RayFace *face, int quad, short x, short y, short z, float rtf[][3])
00268 {
00269         Branch *br;
00270         Node *no;
00271         short a, oc0, oc1, oc2, oc3, oc4, oc5;
00272 
00273         x<<=2;
00274         y<<=1;
00275 
00276         br= oc->adrbranch[0];
00277 
00278         if(oc->ocres==512) {
00279                 oc0= ((x & 1024)+(y & 512)+(z & 256))>>8;
00280                 br= addbranch(oc, br, oc0);
00281         }
00282         if(oc->ocres>=256) {
00283                 oc0= ((x & 512)+(y & 256)+(z & 128))>>7;
00284                 br= addbranch(oc, br, oc0);
00285         }
00286         if(oc->ocres>=128) {
00287                 oc0= ((x & 256)+(y & 128)+(z & 64))>>6;
00288                 br= addbranch(oc, br, oc0);
00289         }
00290 
00291         oc0= ((x & 128)+(y & 64)+(z & 32))>>5;
00292         oc1= ((x & 64)+(y & 32)+(z & 16))>>4;
00293         oc2= ((x & 32)+(y & 16)+(z & 8))>>3;
00294         oc3= ((x & 16)+(y & 8)+(z & 4))>>2;
00295         oc4= ((x & 8)+(y & 4)+(z & 2))>>1;
00296         oc5= ((x & 4)+(y & 2)+(z & 1));
00297 
00298         br= addbranch(oc, br,oc0);
00299         br= addbranch(oc, br,oc1);
00300         br= addbranch(oc, br,oc2);
00301         br= addbranch(oc, br,oc3);
00302         br= addbranch(oc, br,oc4);
00303         no= (Node *)br->b[oc5];
00304         if(no==NULL) br->b[oc5]= (Branch *)(no= addnode(oc));
00305 
00306         while(no->next) no= no->next;
00307 
00308         a= 0;
00309         if(no->v[7]) {          /* node full */
00310                 no->next= addnode(oc);
00311                 no= no->next;
00312         }
00313         else {
00314                 while(no->v[a]!=NULL) a++;
00315         }
00316         
00317         no->v[a]= (RayFace*) RE_rayobject_align(face);
00318         
00319         if(quad)
00320                 calc_ocval_face(rtf[0], rtf[1], rtf[2], rtf[3], x>>2, y>>1, z, &no->ov[a]);
00321         else
00322                 calc_ocval_face(rtf[0], rtf[1], rtf[2], NULL, x>>2, y>>1, z, &no->ov[a]);
00323 }
00324 
00325 static void d2dda(Octree *oc, short b1, short b2, short c1, short c2, char *ocface, short rts[][3], float rtf[][3])
00326 {
00327         int ocx1,ocx2,ocy1,ocy2;
00328         int x,y,dx=0,dy=0;
00329         float ox1,ox2,oy1,oy2;
00330         float labda,labdao,labdax,labday,ldx,ldy;
00331 
00332         ocx1= rts[b1][c1];
00333         ocy1= rts[b1][c2];
00334         ocx2= rts[b2][c1];
00335         ocy2= rts[b2][c2];
00336 
00337         if(ocx1==ocx2 && ocy1==ocy2) {
00338                 ocface[oc->ocres*ocx1+ocy1]= 1;
00339                 return;
00340         }
00341 
00342         ox1= rtf[b1][c1];
00343         oy1= rtf[b1][c2];
00344         ox2= rtf[b2][c1];
00345         oy2= rtf[b2][c2];
00346 
00347         if(ox1!=ox2) {
00348                 if(ox2-ox1>0.0f) {
00349                         labdax= (ox1-ocx1-1.0f)/(ox1-ox2);
00350                         ldx= -1.0f/(ox1-ox2);
00351                         dx= 1;
00352                 } else {
00353                         labdax= (ox1-ocx1)/(ox1-ox2);
00354                         ldx= 1.0f/(ox1-ox2);
00355                         dx= -1;
00356                 }
00357         } else {
00358                 labdax=1.0f;
00359                 ldx=0;
00360         }
00361 
00362         if(oy1!=oy2) {
00363                 if(oy2-oy1>0.0f) {
00364                         labday= (oy1-ocy1-1.0f)/(oy1-oy2);
00365                         ldy= -1.0f/(oy1-oy2);
00366                         dy= 1;
00367                 } else {
00368                         labday= (oy1-ocy1)/(oy1-oy2);
00369                         ldy= 1.0f/(oy1-oy2);
00370                         dy= -1;
00371                 }
00372         } else {
00373                 labday=1.0f;
00374                 ldy=0;
00375         }
00376         
00377         x=ocx1; y=ocy1;
00378         labda= MIN2(labdax, labday);
00379         
00380         while(TRUE) {
00381                 
00382                 if(x<0 || y<0 || x>=oc->ocres || y>=oc->ocres);
00383                 else ocface[oc->ocres*x+y]= 1;
00384                 
00385                 labdao=labda;
00386                 if(labdax==labday) {
00387                         labdax+=ldx;
00388                         x+=dx;
00389                         labday+=ldy;
00390                         y+=dy;
00391                 } else {
00392                         if(labdax<labday) {
00393                                 labdax+=ldx;
00394                                 x+=dx;
00395                         } else {
00396                                 labday+=ldy;
00397                                 y+=dy;
00398                         }
00399                 }
00400                 labda=MIN2(labdax,labday);
00401                 if(labda==labdao) break;
00402                 if(labda>=1.0f) break;
00403         }
00404         ocface[oc->ocres*ocx2+ocy2]=1;
00405 }
00406 
00407 static void filltriangle(Octree *oc, short c1, short c2, char *ocface, short *ocmin, short *ocmax)
00408 {
00409         int a, x, y, y1, y2;
00410 
00411         for(x=ocmin[c1];x<=ocmax[c1];x++) {
00412                 a= oc->ocres*x;
00413                 for(y=ocmin[c2];y<=ocmax[c2];y++) {
00414                         if(ocface[a+y]) {
00415                                 y++;
00416                                 while(ocface[a+y] && y!=ocmax[c2]) y++;
00417                                 for(y1=ocmax[c2];y1>y;y1--) {
00418                                         if(ocface[a+y1]) {
00419                                                 for(y2=y;y2<=y1;y2++) ocface[a+y2]=1;
00420                                                 y1=0;
00421                                         }
00422                                 }
00423                                 y=ocmax[c2];
00424                         }
00425                 }
00426         }
00427 }
00428 
00429 static void RE_rayobject_octree_free(RayObject *tree)
00430 {
00431         Octree *oc= (Octree*)tree;
00432 
00433 #if 0
00434         printf("branches %d nodes %d\n", oc->branchcount, oc->nodecount);
00435         printf("raycount %d \n", raycount);     
00436         printf("ray coherent %d \n", coherent_ray);
00437         printf("accepted %d rejected %d\n", accepted, rejected);
00438 #endif
00439         if(oc->ocface)
00440                 MEM_freeN(oc->ocface);
00441 
00442         if(oc->adrbranch) {
00443                 int a= 0;
00444                 while(oc->adrbranch[a]) {
00445                         MEM_freeN(oc->adrbranch[a]);
00446                         oc->adrbranch[a]= NULL;
00447                         a++;
00448                 }
00449                 MEM_freeN(oc->adrbranch);
00450                 oc->adrbranch= NULL;
00451         }
00452         oc->branchcount= 0;
00453         
00454         if(oc->adrnode) {
00455                 int a= 0;
00456                 while(oc->adrnode[a]) {
00457                         MEM_freeN(oc->adrnode[a]);
00458                         oc->adrnode[a]= NULL;
00459                         a++;
00460                 }
00461                 MEM_freeN(oc->adrnode);
00462                 oc->adrnode= NULL;
00463         }
00464         oc->nodecount= 0;
00465 
00466         MEM_freeN(oc);
00467 }
00468 
00469 
00470 RayObject *RE_rayobject_octree_create(int ocres, int size)
00471 {
00472         Octree *oc= (Octree*)MEM_callocN(sizeof(Octree), "Octree");
00473         assert( RE_rayobject_isAligned(oc) ); /* RayObject API assumes real data to be 4-byte aligned */        
00474         
00475         oc->rayobj.api = &octree_api;
00476         
00477         oc->ocres = ocres;
00478         
00479         oc->ro_nodes = (RayFace**)MEM_callocN(sizeof(RayFace*)*size, "octree rayobject nodes");
00480         oc->ro_nodes_size = size;
00481         oc->ro_nodes_used = 0;
00482 
00483         
00484         return RE_rayobject_unalignRayAPI((RayObject*) oc);
00485 }
00486 
00487 
00488 static void RE_rayobject_octree_add(RayObject *tree, RayObject *node)
00489 {
00490         Octree *oc = (Octree*)tree;
00491 
00492         assert( RE_rayobject_isRayFace(node) );
00493         assert( oc->ro_nodes_used < oc->ro_nodes_size );
00494         oc->ro_nodes[ oc->ro_nodes_used++ ] = (RayFace*)RE_rayobject_align(node);
00495 }
00496 
00497 static void octree_fill_rayface(Octree *oc, RayFace *face)
00498 {
00499         float ocfac[3], rtf[4][3];
00500         float co1[3], co2[3], co3[3], co4[3];
00501         short rts[4][3];
00502         short ocmin[3], ocmax[3];
00503         char *ocface= oc->ocface;       // front, top, size view of face, to fill in
00504         int a, b, c, oc1, oc2, oc3, oc4, x, y, z, ocres2;
00505 
00506         ocfac[0]= oc->ocfacx;
00507         ocfac[1]= oc->ocfacy;
00508         ocfac[2]= oc->ocfacz;
00509 
00510         ocres2= oc->ocres*oc->ocres;
00511 
00512         copy_v3_v3(co1, face->v1);
00513         copy_v3_v3(co2, face->v2);
00514         copy_v3_v3(co3, face->v3);
00515         if(face->v4)
00516                 copy_v3_v3(co4, face->v4);
00517 
00518         for(c=0;c<3;c++) {
00519                 rtf[0][c]= (co1[c]-oc->min[c])*ocfac[c] ;
00520                 rts[0][c]= (short)rtf[0][c];
00521                 rtf[1][c]= (co2[c]-oc->min[c])*ocfac[c] ;
00522                 rts[1][c]= (short)rtf[1][c];
00523                 rtf[2][c]= (co3[c]-oc->min[c])*ocfac[c] ;
00524                 rts[2][c]= (short)rtf[2][c];
00525                 if(RE_rayface_isQuad(face)) {
00526                         rtf[3][c]= (co4[c]-oc->min[c])*ocfac[c] ;
00527                         rts[3][c]= (short)rtf[3][c];
00528                 }
00529         }
00530         
00531         for(c=0;c<3;c++) {
00532                 oc1= rts[0][c];
00533                 oc2= rts[1][c];
00534                 oc3= rts[2][c];
00535                 if(!RE_rayface_isQuad(face)) {
00536                         ocmin[c]= MIN3(oc1,oc2,oc3);
00537                         ocmax[c]= MAX3(oc1,oc2,oc3);
00538                 }
00539                 else {
00540                         oc4= rts[3][c];
00541                         ocmin[c]= MIN4(oc1,oc2,oc3,oc4);
00542                         ocmax[c]= MAX4(oc1,oc2,oc3,oc4);
00543                 }
00544                 if(ocmax[c]>oc->ocres-1) ocmax[c]=oc->ocres-1;
00545                 if(ocmin[c]<0) ocmin[c]=0;
00546         }
00547         
00548         if(ocmin[0]==ocmax[0] && ocmin[1]==ocmax[1] && ocmin[2]==ocmax[2]) {
00549                 ocwrite(oc, face, RE_rayface_isQuad(face), ocmin[0], ocmin[1], ocmin[2], rtf);
00550         }
00551         else {
00552                 
00553                 d2dda(oc, 0,1,0,1,ocface+ocres2,rts,rtf);
00554                 d2dda(oc, 0,1,0,2,ocface,rts,rtf);
00555                 d2dda(oc, 0,1,1,2,ocface+2*ocres2,rts,rtf);
00556                 d2dda(oc, 1,2,0,1,ocface+ocres2,rts,rtf);
00557                 d2dda(oc, 1,2,0,2,ocface,rts,rtf);
00558                 d2dda(oc, 1,2,1,2,ocface+2*ocres2,rts,rtf);
00559                 if(!RE_rayface_isQuad(face)) {
00560                         d2dda(oc, 2,0,0,1,ocface+ocres2,rts,rtf);
00561                         d2dda(oc, 2,0,0,2,ocface,rts,rtf);
00562                         d2dda(oc, 2,0,1,2,ocface+2*ocres2,rts,rtf);
00563                 }
00564                 else {
00565                         d2dda(oc, 2,3,0,1,ocface+ocres2,rts,rtf);
00566                         d2dda(oc, 2,3,0,2,ocface,rts,rtf);
00567                         d2dda(oc, 2,3,1,2,ocface+2*ocres2,rts,rtf);
00568                         d2dda(oc, 3,0,0,1,ocface+ocres2,rts,rtf);
00569                         d2dda(oc, 3,0,0,2,ocface,rts,rtf);
00570                         d2dda(oc, 3,0,1,2,ocface+2*ocres2,rts,rtf);
00571                 }
00572                 /* nothing todo with triangle..., just fills :) */
00573                 filltriangle(oc, 0,1,ocface+ocres2,ocmin,ocmax);
00574                 filltriangle(oc, 0,2,ocface,ocmin,ocmax);
00575                 filltriangle(oc, 1,2,ocface+2*ocres2,ocmin,ocmax);
00576                 
00577                 /* init static vars here */
00578                 face_in_node(face, 0,0,0, rtf);
00579                 
00580                 for(x=ocmin[0];x<=ocmax[0];x++) {
00581                         a= oc->ocres*x;
00582                         for(y=ocmin[1];y<=ocmax[1];y++) {
00583                                 if(ocface[a+y+ocres2]) {
00584                                         b= oc->ocres*y+2*ocres2;
00585                                         for(z=ocmin[2];z<=ocmax[2];z++) {
00586                                                 if(ocface[b+z] && ocface[a+z]) {
00587                                                         if(face_in_node(NULL, x, y, z, rtf))
00588                                                                 ocwrite(oc, face, RE_rayface_isQuad(face), x,y,z, rtf);
00589                                                 }
00590                                         }
00591                                 }
00592                         }
00593                 }
00594                 
00595                 /* same loops to clear octree, doubt it can be done smarter */
00596                 for(x=ocmin[0];x<=ocmax[0];x++) {
00597                         a= oc->ocres*x;
00598                         for(y=ocmin[1];y<=ocmax[1];y++) {
00599                                 /* x-y */
00600                                 ocface[a+y+ocres2]= 0;
00601 
00602                                 b= oc->ocres*y + 2*ocres2;
00603                                 for(z=ocmin[2];z<=ocmax[2];z++) {
00604                                         /* y-z */
00605                                         ocface[b+z]= 0;
00606                                         /* x-z */
00607                                         ocface[a+z]= 0;
00608                                 }
00609                         }
00610                 }
00611         }
00612 }
00613 
00614 static void RE_rayobject_octree_done(RayObject *tree)
00615 {
00616         Octree *oc = (Octree*)tree;
00617         int c;
00618         float t00, t01, t02;
00619         int ocres2 = oc->ocres*oc->ocres;
00620         
00621         INIT_MINMAX(oc->min, oc->max);
00622         
00623         /* Calculate Bounding Box */
00624         for(c=0; c<oc->ro_nodes_used; c++)
00625                 RE_rayobject_merge_bb( RE_rayobject_unalignRayFace(oc->ro_nodes[c]), oc->min, oc->max);
00626                 
00627         /* Alloc memory */
00628         oc->adrbranch= (Branch**)MEM_callocN(sizeof(void *)*BRANCH_ARRAY, "octree branches");
00629         oc->adrnode= (Node**)MEM_callocN(sizeof(void *)*NODE_ARRAY, "octree nodes");
00630         
00631         oc->adrbranch[0]=(Branch *)MEM_callocN(4096*sizeof(Branch), "makeoctree");
00632         
00633         /* the lookup table, per face, for which nodes to fill in */
00634         oc->ocface= (char*)MEM_callocN( 3*ocres2 + 8, "ocface");
00635         memset(oc->ocface, 0, 3*ocres2);
00636 
00637         for(c=0;c<3;c++) {      /* octree enlarge, still needed? */
00638                 oc->min[c]-= 0.01f;
00639                 oc->max[c]+= 0.01f;
00640         }
00641 
00642         t00= oc->max[0]-oc->min[0];
00643         t01= oc->max[1]-oc->min[1];
00644         t02= oc->max[2]-oc->min[2];
00645         
00646         /* this minus 0.1 is old safety... seems to be needed? */
00647         oc->ocfacx= (oc->ocres-0.1)/t00;
00648         oc->ocfacy= (oc->ocres-0.1)/t01;
00649         oc->ocfacz= (oc->ocres-0.1)/t02;
00650         
00651         oc->ocsize= sqrt(t00*t00+t01*t01+t02*t02);      /* global, max size octree */
00652 
00653         for(c=0; c<oc->ro_nodes_used; c++)
00654         {
00655                 octree_fill_rayface(oc, oc->ro_nodes[c]);
00656         }
00657 
00658         MEM_freeN(oc->ocface);
00659         oc->ocface = NULL;
00660         MEM_freeN(oc->ro_nodes);
00661         oc->ro_nodes = NULL;
00662         
00663         printf("%f %f - %f\n", oc->min[0], oc->max[0], oc->ocfacx );
00664         printf("%f %f - %f\n", oc->min[1], oc->max[1], oc->ocfacy );
00665         printf("%f %f - %f\n", oc->min[2], oc->max[2], oc->ocfacz );
00666 }
00667 
00668 static void RE_rayobject_octree_bb(RayObject *tree, float *min, float *max)
00669 {
00670         Octree *oc = (Octree*)tree;
00671         DO_MINMAX(oc->min, min, max);
00672         DO_MINMAX(oc->max, min, max);
00673 }
00674 
00675 /* check all faces in this node */
00676 static int testnode(Octree *oc, Isect *is, Node *no, OcVal ocval)
00677 {
00678         short nr=0;
00679 
00680         /* return on any first hit */
00681         if(is->mode==RE_RAY_SHADOW) {
00682         
00683                 for(; no; no = no->next)
00684                 for(nr=0; nr<8; nr++)
00685                 {
00686                         RayFace *face = no->v[nr];
00687                         OcVal           *ov = no->ov+nr;
00688                         
00689                         if(!face) break;
00690                         
00691                         if( (ov->ocx & ocval.ocx) && (ov->ocy & ocval.ocy) && (ov->ocz & ocval.ocz) )
00692                         {
00693                                 if( RE_rayobject_intersect( RE_rayobject_unalignRayFace(face),is) )
00694                                         return 1;
00695                         }
00696                 }
00697         }
00698         else
00699         {                       /* else mirror or glass or shadowtra, return closest face  */
00700                 int found= 0;
00701                 
00702                 for(; no; no = no->next)
00703                 for(nr=0; nr<8; nr++)
00704                 {
00705                         RayFace *face = no->v[nr];
00706                         OcVal           *ov = no->ov+nr;
00707                         
00708                         if(!face) break;
00709                         
00710                         if( (ov->ocx & ocval.ocx) && (ov->ocy & ocval.ocy) && (ov->ocz & ocval.ocz) )
00711                         { 
00712                                 if( RE_rayobject_intersect( RE_rayobject_unalignRayFace(face),is) )
00713                                         found= 1;
00714                         }
00715                 }
00716                 
00717                 return found;
00718         }
00719 
00720         return 0;
00721 }
00722 
00723 /* find the Node for the octree coord x y z */
00724 static Node *ocread(Octree *oc, int x, int y, int z)
00725 {
00726         Branch *br;
00727         int oc1;
00728         
00729         x<<=2;
00730         y<<=1;
00731         
00732         br= oc->adrbranch[0];
00733         
00734         if(oc->ocres==512) {
00735                 oc1= ((x & 1024)+(y & 512)+(z & 256))>>8;
00736                 br= br->b[oc1];
00737                 if(br==NULL) {
00738                         return NULL;
00739                 }
00740         }
00741         if(oc->ocres>=256) {
00742                 oc1= ((x & 512)+(y & 256)+(z & 128))>>7;
00743                 br= br->b[oc1];
00744                 if(br==NULL) {
00745                         return NULL;
00746                 }
00747         }
00748         if(oc->ocres>=128) {
00749                 oc1= ((x & 256)+(y & 128)+(z & 64))>>6;
00750                 br= br->b[oc1];
00751                 if(br==NULL) {
00752                         return NULL;
00753                 }
00754         }
00755         
00756         oc1= ((x & 128)+(y & 64)+(z & 32))>>5;
00757         br= br->b[oc1];
00758         if(br) {
00759                 oc1= ((x & 64)+(y & 32)+(z & 16))>>4;
00760                 br= br->b[oc1];
00761                 if(br) {
00762                         oc1= ((x & 32)+(y & 16)+(z & 8))>>3;
00763                         br= br->b[oc1];
00764                         if(br) {
00765                                 oc1= ((x & 16)+(y & 8)+(z & 4))>>2;
00766                                 br= br->b[oc1];
00767                                 if(br) {
00768                                         oc1= ((x & 8)+(y & 4)+(z & 2))>>1;
00769                                         br= br->b[oc1];
00770                                         if(br) {
00771                                                 oc1= ((x & 4)+(y & 2)+(z & 1));
00772                                                 return (Node *)br->b[oc1];
00773                                         }
00774                                 }
00775                         }
00776                 }
00777         }
00778         
00779         return NULL;
00780 }
00781 
00782 static int cliptest(float p, float q, float *u1, float *u2)
00783 {
00784         float r;
00785 
00786         if(p<0.0f) {
00787                 if(q<p) return 0;
00788                 else if(q<0.0f) {
00789                         r= q/p;
00790                         if(r>*u2) return 0;
00791                         else if(r>*u1) *u1=r;
00792                 }
00793         }
00794         else {
00795                 if(p>0.0f) {
00796                         if(q<0.0f) return 0;
00797                         else if(q<p) {
00798                                 r= q/p;
00799                                 if(r<*u1) return 0;
00800                                 else if(r<*u2) *u2=r;
00801                         }
00802                 }
00803                 else if(q<0.0f) return 0;
00804         }
00805         return 1;
00806 }
00807 
00808 /* extensive coherence checks/storage cancels out the benefit of it, and gives errors... we
00809    need better methods, sample code commented out below (ton) */
00810  
00811 /*
00812 
00813 in top: static int coh_nodes[16*16*16][6];
00814 in makeoctree: memset(coh_nodes, 0, sizeof(coh_nodes));
00815  
00816 static void add_coherence_test(int ocx1, int ocx2, int ocy1, int ocy2, int ocz1, int ocz2)
00817 {
00818         short *sp;
00819         
00820         sp= coh_nodes[ (ocx2 & 15) + 16*(ocy2 & 15) + 256*(ocz2 & 15) ];
00821         sp[0]= ocx1; sp[1]= ocy1; sp[2]= ocz1;
00822         sp[3]= ocx2; sp[4]= ocy2; sp[5]= ocz2;
00823         
00824 }
00825 
00826 static int do_coherence_test(int ocx1, int ocx2, int ocy1, int ocy2, int ocz1, int ocz2)
00827 {
00828         short *sp;
00829         
00830         sp= coh_nodes[ (ocx2 & 15) + 16*(ocy2 & 15) + 256*(ocz2 & 15) ];
00831         if(sp[0]==ocx1 && sp[1]==ocy1 && sp[2]==ocz1 &&
00832            sp[3]==ocx2 && sp[4]==ocy2 && sp[5]==ocz2) return 1;
00833         return 0;
00834 }
00835 
00836 */
00837 
00838 /* return 1: found valid intersection */
00839 /* starts with is->orig.face */
00840 static int RE_rayobject_octree_intersect(RayObject *tree, Isect *is)
00841 {
00842         Octree *oc= (Octree*)tree;
00843         Node *no;
00844         OcVal ocval;
00845         float vec1[3], vec2[3], start[3], end[3];
00846         float u1,u2,ox1,ox2,oy1,oy2,oz1,oz2;
00847         float labdao,labdax,ldx,labday,ldy,labdaz,ldz, ddalabda;
00848         float olabda = 0;
00849         int dx,dy,dz;   
00850         int xo,yo,zo,c1=0;
00851         int ocx1,ocx2,ocy1, ocy2,ocz1,ocz2;
00852         
00853         /* clip with octree */
00854         if(oc->branchcount==0) return 0;
00855         
00856         /* do this before intersect calls */
00857 #if 0
00858         is->facecontr= NULL;                            /* to check shared edge */
00859         is->obcontr= 0;
00860         is->faceisect= is->isect= 0;            /* shared edge, quad half flag */
00861         is->userdata= oc->userdata;
00862 #endif
00863 
00864         copy_v3_v3( start, is->start );
00865         madd_v3_v3v3fl( end, is->start, is->dir, is->dist );
00866         ldx= is->dir[0]*is->dist;
00867         olabda = is->dist;
00868         u1= 0.0f;
00869         u2= 1.0f;
00870         
00871         /* clip with octree cube */
00872         if(cliptest(-ldx, start[0]-oc->min[0], &u1,&u2)) {
00873                 if(cliptest(ldx, oc->max[0]-start[0], &u1,&u2)) {
00874                         ldy= is->dir[1]*is->dist;
00875                         if(cliptest(-ldy, start[1]-oc->min[1], &u1,&u2)) {
00876                                 if(cliptest(ldy, oc->max[1]-start[1], &u1,&u2)) {
00877                                         ldz = is->dir[2]*is->dist;
00878                                         if(cliptest(-ldz, start[2]-oc->min[2], &u1,&u2)) {
00879                                                 if(cliptest(ldz, oc->max[2]-start[2], &u1,&u2)) {
00880                                                         c1=1;
00881                                                         if(u2<1.0f) {
00882                                                                 end[0] = start[0]+u2*ldx;
00883                                                                 end[1] = start[1]+u2*ldy;
00884                                                                 end[2] = start[2]+u2*ldz;
00885                                                         }
00886 
00887                                                         if(u1>0.0f) {
00888                                                                 start[0] += u1*ldx;
00889                                                                 start[1] += u1*ldy;
00890                                                                 start[2] += u1*ldz;
00891                                                         }
00892                                                 }
00893                                         }
00894                                 }
00895                         }
00896                 }
00897         }
00898 
00899         if(c1==0) return 0;
00900 
00901         /* reset static variables in ocread */
00902         //ocread(oc, oc->ocres, 0, 0);
00903 
00904         /* setup 3dda to traverse octree */
00905         ox1= (start[0]-oc->min[0])*oc->ocfacx;
00906         oy1= (start[1]-oc->min[1])*oc->ocfacy;
00907         oz1= (start[2]-oc->min[2])*oc->ocfacz;
00908         ox2= (end[0]-oc->min[0])*oc->ocfacx;
00909         oy2= (end[1]-oc->min[1])*oc->ocfacy;
00910         oz2= (end[2]-oc->min[2])*oc->ocfacz;
00911 
00912         ocx1= (int)ox1;
00913         ocy1= (int)oy1;
00914         ocz1= (int)oz1;
00915         ocx2= (int)ox2;
00916         ocy2= (int)oy2;
00917         ocz2= (int)oz2;
00918         
00919         if(ocx1==ocx2 && ocy1==ocy2 && ocz1==ocz2) {
00920                 no= ocread(oc, ocx1, ocy1, ocz1);
00921                 if(no) {
00922                         /* exact intersection with node */
00923                         vec1[0]= ox1; vec1[1]= oy1; vec1[2]= oz1;
00924                         vec2[0]= ox2; vec2[1]= oy2; vec2[2]= oz2;
00925                         calc_ocval_ray(&ocval, (float)ocx1, (float)ocy1, (float)ocz1, vec1, vec2);
00926                         if( testnode(oc, is, no, ocval) ) return 1;
00927                 }
00928         }
00929         else {
00930                 int found = 0;
00931                 //static int coh_ocx1,coh_ocx2,coh_ocy1, coh_ocy2,coh_ocz1,coh_ocz2;
00932                 float dox, doy, doz;
00933                 int eqval;
00934                 
00935                 /* calc labda en ld */
00936                 dox= ox1-ox2;
00937                 doy= oy1-oy2;
00938                 doz= oz1-oz2;
00939 
00940                 if(dox<-FLT_EPSILON) {
00941                         ldx= -1.0f/dox;
00942                         labdax= (ocx1-ox1+1.0f)*ldx;
00943                         dx= 1;
00944                 } else if(dox>FLT_EPSILON) {
00945                         ldx= 1.0f/dox;
00946                         labdax= (ox1-ocx1)*ldx;
00947                         dx= -1;
00948                 } else {
00949                         labdax=1.0f;
00950                         ldx=0;
00951                         dx= 0;
00952                 }
00953 
00954                 if(doy<-FLT_EPSILON) {
00955                         ldy= -1.0f/doy;
00956                         labday= (ocy1-oy1+1.0f)*ldy;
00957                         dy= 1;
00958                 } else if(doy>FLT_EPSILON) {
00959                         ldy= 1.0f/doy;
00960                         labday= (oy1-ocy1)*ldy;
00961                         dy= -1;
00962                 } else {
00963                         labday=1.0f;
00964                         ldy=0;
00965                         dy= 0;
00966                 }
00967 
00968                 if(doz<-FLT_EPSILON) {
00969                         ldz= -1.0f/doz;
00970                         labdaz= (ocz1-oz1+1.0f)*ldz;
00971                         dz= 1;
00972                 } else if(doz>FLT_EPSILON) {
00973                         ldz= 1.0f/doz;
00974                         labdaz= (oz1-ocz1)*ldz;
00975                         dz= -1;
00976                 } else {
00977                         labdaz=1.0f;
00978                         ldz=0;
00979                         dz= 0;
00980                 }
00981                 
00982                 xo=ocx1; yo=ocy1; zo=ocz1;
00983                 labdao= ddalabda= MIN3(labdax,labday,labdaz);
00984                 
00985                 vec2[0]= ox1;
00986                 vec2[1]= oy1;
00987                 vec2[2]= oz1;
00988                 
00989                 /* this loop has been constructed to make sure the first and last node of ray
00990                    are always included, even when ddalabda==1.0f or larger */
00991 
00992                 while(TRUE) {
00993 
00994                         no= ocread(oc, xo, yo, zo);
00995                         if(no) {
00996                                 
00997                                 /* calculate ray intersection with octree node */
00998                                 copy_v3_v3(vec1, vec2);
00999                                 // dox,y,z is negative
01000                                 vec2[0]= ox1-ddalabda*dox;
01001                                 vec2[1]= oy1-ddalabda*doy;
01002                                 vec2[2]= oz1-ddalabda*doz;
01003                                 calc_ocval_ray(&ocval, (float)xo, (float)yo, (float)zo, vec1, vec2);
01004 
01005                                 //is->dist = (u1+ddalabda*(u2-u1))*olabda;
01006                                 if( testnode(oc, is, no, ocval) )
01007                                         found = 1;
01008 
01009                                 if(is->dist < (u1+ddalabda*(u2-u1))*olabda)
01010                                         return found;
01011                         }
01012 
01013 
01014                         labdao= ddalabda;
01015                         
01016                         /* traversing ocree nodes need careful detection of smallest values, with proper
01017                            exceptions for equal labdas */
01018                         eqval= (labdax==labday);
01019                         if(labday==labdaz) eqval += 2;
01020                         if(labdax==labdaz) eqval += 4;
01021                         
01022                         if(eqval) {     // only 4 cases exist!
01023                                 if(eqval==7) {  // x=y=z
01024                                         xo+=dx; labdax+=ldx;
01025                                         yo+=dy; labday+=ldy;
01026                                         zo+=dz; labdaz+=ldz;
01027                                 }
01028                                 else if(eqval==1) { // x=y 
01029                                         if(labday < labdaz) {
01030                                                 xo+=dx; labdax+=ldx;
01031                                                 yo+=dy; labday+=ldy;
01032                                         }
01033                                         else {
01034                                                 zo+=dz; labdaz+=ldz;
01035                                         }
01036                                 }
01037                                 else if(eqval==2) { // y=z
01038                                         if(labdax < labday) {
01039                                                 xo+=dx; labdax+=ldx;
01040                                         }
01041                                         else {
01042                                                 yo+=dy; labday+=ldy;
01043                                                 zo+=dz; labdaz+=ldz;
01044                                         }
01045                                 }
01046                                 else { // x=z
01047                                         if(labday < labdax) {
01048                                                 yo+=dy; labday+=ldy;
01049                                         }
01050                                         else {
01051                                                 xo+=dx; labdax+=ldx;
01052                                                 zo+=dz; labdaz+=ldz;
01053                                         }
01054                                 }
01055                         }
01056                         else {  // all three different, just three cases exist
01057                                 eqval= (labdax<labday);
01058                                 if(labday<labdaz) eqval += 2;
01059                                 if(labdax<labdaz) eqval += 4;
01060                                 
01061                                 if(eqval==7 || eqval==5) { // x smallest
01062                                         xo+=dx; labdax+=ldx;
01063                                 }
01064                                 else if(eqval==2 || eqval==6) { // y smallest
01065                                         yo+=dy; labday+=ldy;
01066                                 }
01067                                 else { // z smallest
01068                                         zo+=dz; labdaz+=ldz;
01069                                 }
01070                                 
01071                         }
01072 
01073                         ddalabda=MIN3(labdax,labday,labdaz);
01074                         if(ddalabda==labdao) break;
01075                         /* to make sure the last node is always checked */
01076                         if(labdao>=1.0f) break;
01077                 }
01078         }
01079         
01080         /* reached end, no intersections found */
01081         return 0;
01082 }       
01083 
01084 
01085