Exemplo n.º 1
0
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;
}
Exemplo n.º 2
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;
}