int RE_rayobject_raycast(RayObject *r, Isect *isec) { int i; RE_RC_COUNT(isec->raycounter->raycast.test); /* setup vars used on raycast */ for(i=0; i<3; i++) { isec->idot_axis[i] = 1.0f / isec->dir[i]; isec->bv_index[2*i] = isec->idot_axis[i] < 0.0 ? 1 : 0; isec->bv_index[2*i+1] = 1 - isec->bv_index[2*i]; isec->bv_index[2*i] = i+3*isec->bv_index[2*i]; isec->bv_index[2*i+1] = i+3*isec->bv_index[2*i+1]; } #ifdef RT_USE_LAST_HIT /* last hit heuristic */ if(isec->mode==RE_RAY_SHADOW && isec->last_hit) { RE_RC_COUNT(isec->raycounter->rayshadow_last_hit.test); if(RE_rayobject_intersect(isec->last_hit, isec)) { RE_RC_COUNT(isec->raycounter->raycast.hit); RE_RC_COUNT(isec->raycounter->rayshadow_last_hit.hit); return 1; } } #endif #ifdef RT_USE_HINT isec->hit_hint = 0; #endif if(RE_rayobject_intersect(r, isec)) { RE_RC_COUNT(isec->raycounter->raycast.hit); #ifdef RT_USE_HINT isec->hint = isec->hit_hint; #endif return 1; } return 0; }
MALWAYS_INLINE int intersect_rayface(RayObject *hit_obj, RayFace *face, Isect *is) { float dist, uv[2]; int ok= 0; /* avoid self-intersection */ if (is->orig.ob == face->ob && is->orig.face == face->face) return 0; /* check if we should intersect this face */ if (is->check == RE_CHECK_VLR_RENDER) { if (vlr_check_intersect(is, (ObjectInstanceRen*)face->ob, (VlakRen*)face->face) == 0) return 0; } else if (is->check == RE_CHECK_VLR_NON_SOLID_MATERIAL) { if (vlr_check_intersect(is, (ObjectInstanceRen*)face->ob, (VlakRen*)face->face) == 0) return 0; if (vlr_check_intersect_solid(is, (ObjectInstanceRen*)face->ob, (VlakRen*)face->face) == 0) return 0; } else if (is->check == RE_CHECK_VLR_BAKE) { if (vlr_check_bake(is, (ObjectInstanceRen*)face->ob, (VlakRen*)face->face) == 0) return 0; } /* ray counter */ RE_RC_COUNT(is->raycounter->faces.test); dist= is->dist; ok= isec_tri_quad(is->start, is->dir, face, uv, &dist); if (ok) { /* when a shadow ray leaves a face, it can be little outside the edges * of it, causing intersection to be detected in its neighbor face */ if (is->skip & RE_SKIP_VLR_NEIGHBOUR) { if (dist < 0.1f && is->orig.ob == face->ob) { VlakRen * a = (VlakRen*)is->orig.face; VlakRen * b = (VlakRen*)face->face; /* so there's a shared edge or vertex, let's intersect ray with * face itself, if that's true we can safely return 1, otherwise * we assume the intersection is invalid, 0 */ if (a->v1==b->v1 || a->v2==b->v1 || a->v3==b->v1 || a->v4==b->v1 || a->v1==b->v2 || a->v2==b->v2 || a->v3==b->v2 || a->v4==b->v2 || a->v1==b->v3 || a->v2==b->v3 || a->v3==b->v3 || a->v4==b->v3 || (b->v4 && (a->v1==b->v4 || a->v2==b->v4 || a->v3==b->v4 || a->v4==b->v4))) { /* create RayFace from original face, transformed if necessary */ RayFace origface; ObjectInstanceRen *ob= (ObjectInstanceRen*)is->orig.ob; rayface_from_vlak(&origface, ob, (VlakRen*)is->orig.face); if (!isec_tri_quad_neighbour(is->start, is->dir, &origface)) { return 0; } } } } RE_RC_COUNT(is->raycounter->faces.hit); is->isect= ok; // which half of the quad is->dist= dist; is->u= uv[0]; is->v= uv[1]; is->hit.ob = face->ob; is->hit.face = face->face; #ifdef RT_USE_LAST_HIT is->last_hit = hit_obj; #endif return 1; } return 0; }