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