Blender V2.61 - r43446

rayobject.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) 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