Ejemplo n.º 1
0
Archivo: Ray.cpp Proyecto: arajar/funk
	bool Ray::IntersectBox( Box3 a_box, matrix a_mat_transform )
	{
		// translate by position
		a_mat_transform = a_mat_transform * matrix::Translation( a_box.GetCenter() );
		
		v3 halfsize = a_box.Size()*0.5f;
		
		float tmin = -FLT_MAX;
        float tmax = FLT_MAX;
		
        v4 nmin;
        v4 nmax;
		
        const v4 p = a_mat_transform.w - v4(m_pos,1.0f);
		
        for ( size_t i=0; i!=3; ++i )
        {
			v4 box_basis_vector = a_mat_transform[i];
			
			const float e = dot( box_basis_vector, p );
			float f = dot( box_basis_vector, v4(m_dir,0.0f) );
			
			if ( fabs(f) > EPSILON )
			{
				f = 1.0f/f;
				
				float t1 = ( e + halfsize[i] ) * f;
				float t2 = ( e - halfsize[i] ) * f;
				
				float flip = 1.f;
				
				if ( t1 > t2 )
				{
					// swap
					float tmp = t1;
					t1 = t2;
					t2 = tmp;
					
					flip = -flip;
				}
				
				if ( t1 > tmin ) { tmin = t1; nmin = a_mat_transform[i] * flip; }
				if ( t2 < tmax ) { tmax = t2; nmax =-a_mat_transform[i] * flip; }
				
				if ( tmin > tmax )	return false;
				if ( tmax < 0.f )	return false;
			}
			else if ( ( ( -e - halfsize[i] ) > 0.f ) ||
					  ( ( -e + halfsize[i] ) < 0.f ) )
			{
				// ray parallel to the stab
				return false;
			}
        }
		
        if ( tmin > 0.f )
			return NewHit( tmin, nmin.xyz() );

        return NewHit( tmax, nmax.xyz() );
	}
Ejemplo n.º 2
0
Archivo: Ray.cpp Proyecto: arajar/funk
	bool Ray::IntersectTri( v3 a_pt0, v3 a_pt1, v3 a_pt2 )
	{
		v3 tri_normal = cross( a_pt1 - a_pt0, a_pt2 - a_pt0 );
		const float vdotn = dot( tri_normal, m_dir );
		
        // the ray direction is parallel to triangle plane, return no intersection
		
        if ( fabs(vdotn) <= EPSILON )
			return false;
		
        // signed distance to intersection point
		
        const float sd = dot( a_pt0-m_pos , tri_normal ) / vdotn;
		
        if ( sd < 0.f )
			return false;
		
        const v3 i = m_pos + m_dir * sd;
		
		if ( dot( cross( a_pt1-a_pt0, i-a_pt0 ), tri_normal ) < 0.f ) return false;
		if ( dot( cross( a_pt2-a_pt1, i-a_pt1 ), tri_normal ) < 0.f ) return false;
		if ( dot( cross( a_pt0-a_pt2, i-a_pt2 ), tri_normal ) < 0.f ) return false;
		
        return NewHit( sd, tri_normal );
	}
Ejemplo n.º 3
0
Archivo: Ray.cpp Proyecto: arajar/funk
	bool Ray::IntersectQuad( v3 a_pt0, v3 a_pt1, v3 a_pt2,  v3 a_pt3 )
	{
		v3 normal = normalize( cross(a_pt1-a_pt0, a_pt2-a_pt0) );
		const float vdotn = dot(m_dir, normal );
		
        // the ray direction is parallel to triangle plane, return no intersection
		
        if ( fabs(vdotn) <= EPSILON )
			return false;
		
        // signed distance to intersection point
		
        const float sd = ( ( dot( a_pt0 - m_pos, normal ) ) / vdotn );
		
        if ( sd < 0.f )
			return false;
		
        const v3 i = m_pos + m_dir * sd;
		
        if ( dot( cross(a_pt1 - a_pt0, i - a_pt0 ), normal ) < 0.f ) return false;
        if ( dot( cross(a_pt2 - a_pt1, i - a_pt1 ), normal ) < 0.f ) return false;
        if ( dot( cross(a_pt3 - a_pt2, i - a_pt2 ), normal ) < 0.f ) return false;
        if ( dot( cross(a_pt0 - a_pt3, i - a_pt3 ), normal ) < 0.f ) return false;
		
        return NewHit( sd, normal );
	}
Ejemplo n.º 4
0
Archivo: Ray.cpp Proyecto: arajar/funk
	bool Ray::IntersectPlane( Plane a_plane )
	{
		v3 normal = a_plane.GetNormal();
		const float vdotn = dot( m_dir, normal );
		
        if ( fabs(vdotn) <= EPSILON )
			return false;
        
        return NewHit( - dot( m_pos - m_pos, normal ) / vdotn, normal );
	}
Ejemplo n.º 5
0
Archivo: Ray.cpp Proyecto: arajar/funk
	bool Ray::IntersectDisk( v3 a_center, float a_radius, v3 a_normal )
	{
		const float vdotn = dot( m_dir, a_normal );
		
        // the ray direction is parallel to triangle plane, return no intersection
		
        if ( fabs(vdotn) <= EPSILON )
			return false;
		
        // signed distance to intersection point
		
        const float sd = ( dot(a_center, a_normal) - dot(m_pos, a_normal) ) / vdotn;
		
        if ( sd < 0.f )
			return false;
		
        const v4 i = m_pos + m_dir * sd;
		
        if ( lengthSqr( i - a_center ) > a_radius*a_radius )
			return false;
		
        return NewHit( sd, a_normal );
	}
Ejemplo n.º 6
0
Archivo: Ray.cpp Proyecto: arajar/funk
	bool Ray::IntersectSphere( v3 center, float radius )
	{
		// http://wiki.cgsociety.org/index.php/Ray_Sphere_Intersection
		
		v3 ray_pos_transformed = m_pos - center;
		
		// Compute A, B and C coefficients
		float a = dot(m_dir, m_dir);
		float b = 2 * dot(m_dir, ray_pos_transformed);
		float c = dot(ray_pos_transformed, ray_pos_transformed) - (radius * radius);
		
		//Find discriminant
		float disc = b * b - 4 * a * c;
		
		// if discriminant is negative there are no real roots, so return
		// false as ray misses sphere
		if (disc < 0)
			return false;
		
		// compute q as described above
		float distSqrt = sqrtf(disc);
		float q;
		if (b < 0)
			q = (-b - distSqrt)/2.0f;
		else
			q = (-b + distSqrt)/2.0f;
		
		// compute t0 and t1
		float t0 = q / a;
		float t1 = c / q;
		
		// make sure t0 is smaller than t1
		if (t0 > t1)
		{
			// if t0 is bigger than t1 swap them around
			float temp = t0;
			t0 = t1;
			t1 = temp;
		}
				
		// if t1 is less than zero, the object is in the ray's negative direction
		// and consequently the ray misses the sphere
		if (t1 < 0)
			return false;
			
		float t;
		
		// if t0 is less than zero, the intersection point is at t1
		if (t0 < 0)
		{
			t = t1;
		}
		// else the intersection point is at t0
		else
		{
			t = t0;
		}
		
		v3 sphere_pos = ray_pos_transformed + m_dir*t;
		v3 normal = normalize(sphere_pos);
		
		return NewHit(t, normal );
	}
Ejemplo n.º 7
0
Archivo: inter.c Proyecto: oleavitt/gem
HitData *GetNextHit(HitData *hit)
{
  if(hit->next == NULL)
    hit->next = NewHit();
  return hit->next;
}