|
Blender
V2.59
|
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