Blender V2.61 - r43446
|
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