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) 2009 Blender Foundation. 00019 * All rights reserved. 00020 * 00021 * The Original Code is: all of this file. 00022 * 00023 * Contributor(s): André Pinto. 00024 * 00025 * ***** END GPL LICENSE BLOCK ***** 00026 */ 00027 00033 #include <assert.h> 00034 00035 #include "MEM_guardedalloc.h" 00036 00037 #include "BLI_math.h" 00038 #include "BLI_utildefines.h" 00039 00040 #include "DNA_material_types.h" 00041 00042 #include "rayintersection.h" 00043 #include "rayobject.h" 00044 #include "raycounter.h" 00045 #include "render_types.h" 00046 00047 /* RayFace 00048 00049 note we force always inline here, because compiler refuses to otherwise 00050 because function is too long. Since this is code that is called billions 00051 of times we really do want to inline. */ 00052 00053 MALWAYS_INLINE RayObject* rayface_from_coords(RayFace *rayface, void *ob, void *face, 00054 float *v1, float *v2, float *v3, float *v4) 00055 { 00056 rayface->ob = ob; 00057 rayface->face = face; 00058 00059 copy_v3_v3(rayface->v1, v1); 00060 copy_v3_v3(rayface->v2, v2); 00061 copy_v3_v3(rayface->v3, v3); 00062 00063 if(v4) 00064 { 00065 copy_v3_v3(rayface->v4, v4); 00066 rayface->quad = 1; 00067 } 00068 else 00069 { 00070 rayface->quad = 0; 00071 } 00072 00073 return RE_rayobject_unalignRayFace(rayface); 00074 } 00075 00076 MALWAYS_INLINE void rayface_from_vlak(RayFace *rayface, ObjectInstanceRen *obi, VlakRen *vlr) 00077 { 00078 rayface_from_coords(rayface, obi, vlr, vlr->v1->co, vlr->v2->co, vlr->v3->co, vlr->v4 ? vlr->v4->co : 0); 00079 00080 if(obi->transform_primitives) 00081 { 00082 mul_m4_v3(obi->mat, rayface->v1); 00083 mul_m4_v3(obi->mat, rayface->v2); 00084 mul_m4_v3(obi->mat, rayface->v3); 00085 00086 if(RE_rayface_isQuad(rayface)) 00087 mul_m4_v3(obi->mat, rayface->v4); 00088 } 00089 } 00090 00091 RayObject* RE_rayface_from_vlak(RayFace *rayface, ObjectInstanceRen *obi, VlakRen *vlr) 00092 { 00093 return rayface_from_coords(rayface, obi, vlr, vlr->v1->co, vlr->v2->co, vlr->v3->co, vlr->v4 ? vlr->v4->co : 0); 00094 } 00095 00096 /* VlakPrimitive */ 00097 00098 RayObject* RE_vlakprimitive_from_vlak(VlakPrimitive *face, struct ObjectInstanceRen *obi, struct VlakRen *vlr) 00099 { 00100 face->ob = obi; 00101 face->face = vlr; 00102 00103 return RE_rayobject_unalignVlakPrimitive(face); 00104 } 00105 00106 /* Checks for ignoring faces or materials */ 00107 00108 MALWAYS_INLINE int vlr_check_intersect(Isect *is, ObjectInstanceRen *obi, VlakRen *vlr) 00109 { 00110 /* for baking selected to active non-traceable materials might still 00111 * be in the raytree */ 00112 if(!(vlr->flag & R_TRACEBLE)) 00113 return 0; 00114 00115 /* I know... cpu cycle waste, might do smarter once */ 00116 if(is->mode==RE_RAY_MIRROR) 00117 return !(vlr->mat->mode & MA_ONLYCAST); 00118 else 00119 return (is->lay & obi->lay); 00120 } 00121 00122 MALWAYS_INLINE int vlr_check_intersect_solid(Isect *UNUSED(is), ObjectInstanceRen* UNUSED(obi), VlakRen *vlr) 00123 { 00124 /* solid material types only */ 00125 if (vlr->mat->material_type == MA_TYPE_SURFACE) 00126 return 1; 00127 else 00128 return 0; 00129 } 00130 00131 MALWAYS_INLINE int vlr_check_bake(Isect *is, ObjectInstanceRen* obi, VlakRen *UNUSED(vlr)) 00132 { 00133 return (obi->obr->ob != is->userdata); 00134 } 00135 00136 /* Ray Triangle/Quad Intersection */ 00137 00138 MALWAYS_INLINE int isec_tri_quad(float start[3], float dir[3], RayFace *face, float uv[2], float *lambda) 00139 { 00140 float co1[3], co2[3], co3[3], co4[3]; 00141 float t0[3], t1[3], x[3], r[3], m[3], u, v, divdet, det1, l; 00142 int quad; 00143 00144 quad= RE_rayface_isQuad(face); 00145 00146 copy_v3_v3(co1, face->v1); 00147 copy_v3_v3(co2, face->v2); 00148 copy_v3_v3(co3, face->v3); 00149 00150 copy_v3_v3(r, dir); 00151 00152 /* intersect triangle */ 00153 sub_v3_v3v3(t0, co3, co2); 00154 sub_v3_v3v3(t1, co3, co1); 00155 00156 cross_v3_v3v3(x, r, t1); 00157 divdet= dot_v3v3(t0, x); 00158 00159 sub_v3_v3v3(m, start, co3); 00160 det1= dot_v3v3(m, x); 00161 00162 if(divdet != 0.0f) { 00163 divdet= 1.0f/divdet; 00164 v= det1*divdet; 00165 00166 if(v < RE_RAYTRACE_EPSILON && v > -(1.0f+RE_RAYTRACE_EPSILON)) { 00167 float cros[3]; 00168 00169 cross_v3_v3v3(cros, m, t0); 00170 u= divdet*dot_v3v3(cros, r); 00171 00172 if(u < RE_RAYTRACE_EPSILON && (v + u) > -(1.0f+RE_RAYTRACE_EPSILON)) { 00173 l= divdet*dot_v3v3(cros, t1); 00174 00175 /* check if intersection is within ray length */ 00176 if(l > -RE_RAYTRACE_EPSILON && l < *lambda) { 00177 uv[0]= u; 00178 uv[1]= v; 00179 *lambda= l; 00180 return 1; 00181 } 00182 } 00183 } 00184 } 00185 00186 /* intersect second triangle in quad */ 00187 if(quad) { 00188 copy_v3_v3(co4, face->v4); 00189 sub_v3_v3v3(t0, co3, co4); 00190 divdet= dot_v3v3(t0, x); 00191 00192 if(divdet != 0.0f) { 00193 divdet= 1.0f/divdet; 00194 v = det1*divdet; 00195 00196 if(v < RE_RAYTRACE_EPSILON && v > -(1.0f+RE_RAYTRACE_EPSILON)) { 00197 float cros[3]; 00198 00199 cross_v3_v3v3(cros, m, t0); 00200 u= divdet*dot_v3v3(cros, r); 00201 00202 if(u < RE_RAYTRACE_EPSILON && (v + u) > -(1.0f+RE_RAYTRACE_EPSILON)) { 00203 l= divdet*dot_v3v3(cros, t1); 00204 00205 if(l >- RE_RAYTRACE_EPSILON && l < *lambda) { 00206 uv[0]= u; 00207 uv[1]= -(1.0f + v + u); 00208 *lambda= l; 00209 return 2; 00210 } 00211 } 00212 } 00213 } 00214 } 00215 00216 return 0; 00217 } 00218 00219 /* Simpler yes/no Ray Triangle/Quad Intersection */ 00220 00221 MALWAYS_INLINE int isec_tri_quad_neighbour(float start[3], float dir[3], RayFace *face) 00222 { 00223 float co1[3], co2[3], co3[3], co4[3]; 00224 float t0[3], t1[3], x[3], r[3], m[3], u, v, divdet, det1; 00225 int quad; 00226 00227 quad= RE_rayface_isQuad(face); 00228 00229 copy_v3_v3(co1, face->v1); 00230 copy_v3_v3(co2, face->v2); 00231 copy_v3_v3(co3, face->v3); 00232 00233 negate_v3_v3(r, dir); /* note, different than above function */ 00234 00235 /* intersect triangle */ 00236 sub_v3_v3v3(t0, co3, co2); 00237 sub_v3_v3v3(t1, co3, co1); 00238 00239 cross_v3_v3v3(x, r, t1); 00240 divdet= dot_v3v3(t0, x); 00241 00242 sub_v3_v3v3(m, start, co3); 00243 det1= dot_v3v3(m, x); 00244 00245 if(divdet != 0.0f) { 00246 divdet= 1.0f/divdet; 00247 v= det1*divdet; 00248 00249 if(v < RE_RAYTRACE_EPSILON && v > -(1.0f+RE_RAYTRACE_EPSILON)) { 00250 float cros[3]; 00251 00252 cross_v3_v3v3(cros, m, t0); 00253 u= divdet*dot_v3v3(cros, r); 00254 00255 if(u < RE_RAYTRACE_EPSILON && (v + u) > -(1.0f+RE_RAYTRACE_EPSILON)) 00256 return 1; 00257 } 00258 } 00259 00260 /* intersect second triangle in quad */ 00261 if(quad) { 00262 copy_v3_v3(co4, face->v4); 00263 sub_v3_v3v3(t0, co3, co4); 00264 divdet= dot_v3v3(t0, x); 00265 00266 if(divdet != 0.0f) { 00267 divdet= 1.0f/divdet; 00268 v = det1*divdet; 00269 00270 if(v < RE_RAYTRACE_EPSILON && v > -(1.0f+RE_RAYTRACE_EPSILON)) { 00271 float cros[3]; 00272 00273 cross_v3_v3v3(cros, m, t0); 00274 u= divdet*dot_v3v3(cros, r); 00275 00276 if(u < RE_RAYTRACE_EPSILON && (v + u) > -(1.0f+RE_RAYTRACE_EPSILON)) 00277 return 2; 00278 } 00279 } 00280 } 00281 00282 return 0; 00283 } 00284 00285 /* RayFace intersection with checks and neighbour verifaction included, 00286 Isect is modified if the face is hit. */ 00287 00288 MALWAYS_INLINE int intersect_rayface(RayObject *hit_obj, RayFace *face, Isect *is) 00289 { 00290 float dist, uv[2]; 00291 int ok= 0; 00292 00293 /* avoid self-intersection */ 00294 if(is->orig.ob == face->ob && is->orig.face == face->face) 00295 return 0; 00296 00297 /* check if we should intersect this face */ 00298 if(is->check == RE_CHECK_VLR_RENDER) 00299 { 00300 if(vlr_check_intersect(is, (ObjectInstanceRen*)face->ob, (VlakRen*)face->face) == 0) 00301 return 0; 00302 } 00303 else if(is->check == RE_CHECK_VLR_NON_SOLID_MATERIAL) 00304 { 00305 if(vlr_check_intersect(is, (ObjectInstanceRen*)face->ob, (VlakRen*)face->face) == 0) 00306 return 0; 00307 if(vlr_check_intersect_solid(is, (ObjectInstanceRen*)face->ob, (VlakRen*)face->face) == 0) 00308 return 0; 00309 } 00310 else if(is->check == RE_CHECK_VLR_BAKE) { 00311 if(vlr_check_bake(is, (ObjectInstanceRen*)face->ob, (VlakRen*)face->face) == 0) 00312 return 0; 00313 } 00314 00315 /* ray counter */ 00316 RE_RC_COUNT(is->raycounter->faces.test); 00317 00318 dist= is->dist; 00319 ok= isec_tri_quad(is->start, is->dir, face, uv, &dist); 00320 00321 if(ok) { 00322 00323 /* when a shadow ray leaves a face, it can be little outside the edges 00324 of it, causing intersection to be detected in its neighbour face */ 00325 if(is->skip & RE_SKIP_VLR_NEIGHBOUR) 00326 { 00327 if(dist < 0.1f && is->orig.ob == face->ob) 00328 { 00329 VlakRen * a = (VlakRen*)is->orig.face; 00330 VlakRen * b = (VlakRen*)face->face; 00331 00332 /* so there's a shared edge or vertex, let's intersect ray with 00333 face itself, if that's true we can safely return 1, otherwise 00334 we assume the intersection is invalid, 0 */ 00335 if(a->v1==b->v1 || a->v2==b->v1 || a->v3==b->v1 || a->v4==b->v1 00336 || a->v1==b->v2 || a->v2==b->v2 || a->v3==b->v2 || a->v4==b->v2 00337 || a->v1==b->v3 || a->v2==b->v3 || a->v3==b->v3 || a->v4==b->v3 00338 || (b->v4 && (a->v1==b->v4 || a->v2==b->v4 || a->v3==b->v4 || a->v4==b->v4))) { 00339 /* create RayFace from original face, transformed if necessary */ 00340 RayFace origface; 00341 ObjectInstanceRen *ob= (ObjectInstanceRen*)is->orig.ob; 00342 rayface_from_vlak(&origface, ob, (VlakRen*)is->orig.face); 00343 00344 if(!isec_tri_quad_neighbour(is->start, is->dir, &origface)) 00345 { 00346 return 0; 00347 } 00348 } 00349 } 00350 } 00351 00352 RE_RC_COUNT(is->raycounter->faces.hit); 00353 00354 is->isect= ok; // which half of the quad 00355 is->dist= dist; 00356 is->u= uv[0]; is->v= uv[1]; 00357 00358 is->hit.ob = face->ob; 00359 is->hit.face = face->face; 00360 #ifdef RT_USE_LAST_HIT 00361 is->last_hit = hit_obj; 00362 #endif 00363 return 1; 00364 } 00365 00366 return 0; 00367 } 00368 00369 /* Intersection */ 00370 00371 int RE_rayobject_raycast(RayObject *r, Isect *isec) 00372 { 00373 int i; 00374 00375 RE_RC_COUNT(isec->raycounter->raycast.test); 00376 00377 /* setup vars used on raycast */ 00378 for(i=0; i<3; i++) 00379 { 00380 isec->idot_axis[i] = 1.0f / isec->dir[i]; 00381 00382 isec->bv_index[2*i] = isec->idot_axis[i] < 0.0 ? 1 : 0; 00383 isec->bv_index[2*i+1] = 1 - isec->bv_index[2*i]; 00384 00385 isec->bv_index[2*i] = i+3*isec->bv_index[2*i]; 00386 isec->bv_index[2*i+1] = i+3*isec->bv_index[2*i+1]; 00387 } 00388 00389 #ifdef RT_USE_LAST_HIT 00390 /* last hit heuristic */ 00391 if(isec->mode==RE_RAY_SHADOW && isec->last_hit) 00392 { 00393 RE_RC_COUNT(isec->raycounter->rayshadow_last_hit.test); 00394 00395 if(RE_rayobject_intersect(isec->last_hit, isec)) 00396 { 00397 RE_RC_COUNT(isec->raycounter->raycast.hit); 00398 RE_RC_COUNT(isec->raycounter->rayshadow_last_hit.hit); 00399 return 1; 00400 } 00401 } 00402 #endif 00403 00404 #ifdef RT_USE_HINT 00405 isec->hit_hint = 0; 00406 #endif 00407 00408 if(RE_rayobject_intersect(r, isec)) 00409 { 00410 RE_RC_COUNT(isec->raycounter->raycast.hit); 00411 00412 #ifdef RT_USE_HINT 00413 isec->hint = isec->hit_hint; 00414 #endif 00415 return 1; 00416 } 00417 00418 return 0; 00419 } 00420 00421 int RE_rayobject_intersect(RayObject *r, Isect *i) 00422 { 00423 if(RE_rayobject_isRayFace(r)) 00424 { 00425 return intersect_rayface(r, (RayFace*) RE_rayobject_align(r), i); 00426 } 00427 else if(RE_rayobject_isVlakPrimitive(r)) 00428 { 00429 //TODO optimize (useless copy to RayFace to avoid duplicate code) 00430 VlakPrimitive *face = (VlakPrimitive*) RE_rayobject_align(r); 00431 RayFace nface; 00432 rayface_from_vlak(&nface, face->ob, face->face); 00433 00434 return intersect_rayface(r, &nface, i); 00435 } 00436 else if(RE_rayobject_isRayAPI(r)) 00437 { 00438 r = RE_rayobject_align(r); 00439 return r->api->raycast(r, i); 00440 } 00441 else { 00442 assert(0); 00443 return 0; 00444 } 00445 } 00446 00447 /* Building */ 00448 00449 void RE_rayobject_add(RayObject *r, RayObject *o) 00450 { 00451 r = RE_rayobject_align(r); 00452 return r->api->add(r, o); 00453 } 00454 00455 void RE_rayobject_done(RayObject *r) 00456 { 00457 r = RE_rayobject_align(r); 00458 r->api->done(r); 00459 } 00460 00461 void RE_rayobject_free(RayObject *r) 00462 { 00463 r = RE_rayobject_align(r); 00464 r->api->free(r); 00465 } 00466 00467 float RE_rayobject_cost(RayObject *r) 00468 { 00469 if(RE_rayobject_isRayFace(r) || RE_rayobject_isVlakPrimitive(r)) 00470 { 00471 return 1.0f; 00472 } 00473 else if(RE_rayobject_isRayAPI(r)) 00474 { 00475 r = RE_rayobject_align(r); 00476 return r->api->cost(r); 00477 } 00478 else { 00479 assert(0); 00480 return 1.0f; 00481 } 00482 } 00483 00484 /* Bounding Boxes */ 00485 00486 void RE_rayobject_merge_bb(RayObject *r, float *min, float *max) 00487 { 00488 if(RE_rayobject_isRayFace(r)) 00489 { 00490 RayFace *face = (RayFace*) RE_rayobject_align(r); 00491 00492 DO_MINMAX(face->v1, min, max); 00493 DO_MINMAX(face->v2, min, max); 00494 DO_MINMAX(face->v3, min, max); 00495 if(RE_rayface_isQuad(face)) DO_MINMAX(face->v4, min, max); 00496 } 00497 else if(RE_rayobject_isVlakPrimitive(r)) 00498 { 00499 VlakPrimitive *face = (VlakPrimitive*) RE_rayobject_align(r); 00500 RayFace nface; 00501 rayface_from_vlak(&nface, face->ob, face->face); 00502 00503 DO_MINMAX(nface.v1, min, max); 00504 DO_MINMAX(nface.v2, min, max); 00505 DO_MINMAX(nface.v3, min, max); 00506 if(RE_rayface_isQuad(&nface)) DO_MINMAX(nface.v4, min, max); 00507 } 00508 else if(RE_rayobject_isRayAPI(r)) 00509 { 00510 r = RE_rayobject_align(r); 00511 r->api->bb(r, min, max); 00512 } 00513 else 00514 assert(0); 00515 } 00516 00517 /* Hints */ 00518 00519 void RE_rayobject_hint_bb(RayObject *r, RayHint *hint, float *min, float *max) 00520 { 00521 if(RE_rayobject_isRayFace(r) || RE_rayobject_isVlakPrimitive(r)) 00522 { 00523 return; 00524 } 00525 else if(RE_rayobject_isRayAPI(r)) 00526 { 00527 r = RE_rayobject_align(r); 00528 return r->api->hint_bb(r, hint, min, max); 00529 } 00530 else 00531 assert(0); 00532 } 00533 00534 /* RayObjectControl */ 00535 00536 int RE_rayobjectcontrol_test_break(RayObjectControl *control) 00537 { 00538 if(control->test_break) 00539 return control->test_break(control->data); 00540 00541 return 0; 00542 } 00543 00544 void RE_rayobject_set_control(RayObject *r, void *data, RE_rayobjectcontrol_test_break_callback test_break) 00545 { 00546 if(RE_rayobject_isRayAPI(r)) 00547 { 00548 r = RE_rayobject_align(r); 00549 r->control.data = data; 00550 r->control.test_break = test_break; 00551 } 00552 } 00553