Blender V2.61 - r43446

rayobject_octree.cpp

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