Esempio n. 1
0
bool CheckRay(const CRay& ray, const CPlane& plane, Vector3* hitPoint)
{
    //This algorithm is based on the plane equation we saw in the CheckPlane methods
	float planeRayDirection = plane.GetNormal().Dot(ray.GetDirection());

	if (planeRayDirection == 0)
	{
		return false;
	}

    //The equation is between the plane normal and the ray origin. It is also divided by the dot product of the plane normal and ray direction
	float t = -(plane.GetNormal().Dot(ray.GetOrigin()) + plane.GetDistance()) / planeRayDirection;
	
    //If the result of the equation is negative then there is no hit
    if (t < 0)
	{
		return false;
	}
	if (hitPoint)
	{
        //Here we calculate the point where the ray hits the plane
		Vector3 pointOnPlane = (ray.GetDirection() * t) + ray.GetOrigin();
		hitPoint->x = pointOnPlane.x;
		hitPoint->y = pointOnPlane.y;
		hitPoint->z = pointOnPlane.z;
	}
	return true;
}
Esempio n. 2
0
bool CheckRay(const CRay& ray, const CBoundingBox& bb, Vector3* hitPoint)
{
    //This algorithm is adapted from: http://tavianator.com/fast-branchless-raybounding-box-intersections/
    //Its based on the "Slab Technique" which treats a bounding box as a series of 2 planes in each axis.
    //It finds where the ray lies on each of these planes and compares those values across each axis.
	float tmin = -INFINITY;
	float tmax = INFINITY;

	float tx1 = (bb.GetMin().x - ray.GetOrigin().x) / ray.GetDirection().x;
	float tx2 = (bb.GetMax().x - ray.GetOrigin().x) / ray.GetDirection().x;

	tmin = max(tmin, min(tx1, tx2));
	tmax = min(tmax, max(tx1, tx2));
	
	float ty1 = (bb.GetMin().y - ray.GetOrigin().y) / ray.GetDirection().y;
	float ty2 = (bb.GetMax().y - ray.GetOrigin().y) / ray.GetDirection().y;

	tmin = max(tmin, min(ty1, ty2));
	tmax = min(tmax, max(ty1, ty2));
	
	float tz1 = (bb.GetMin().z - ray.GetOrigin().z) / ray.GetDirection().z;
	float tz2 = (bb.GetMax().z - ray.GetOrigin().z) / ray.GetDirection().z;

	tmin = max(tmin, min(tz1, tz2));
	tmax = min(tmax, max(tz1, tz2));
	
    //We end up with two hit values just like the sphere, if the max hit is less than 0 then it all happened behind the ray origin
	if (tmax < 0)
		return false;

    //If the max hit value is greater than the min hit (as it should be) then we have a hit!
	if (tmax >= tmin)
	{
		if (hitPoint)
		{
            //If we need to know the first hit point on the box then we should use tmin, unless it's negative then we use tmax.
            //This would come up in situations where the origin of the ray is within the box.
			float firstHitDistance = tmin < 0 ? tmax : tmin;
			Vector3 pointOnBox = (ray.GetDirection() * firstHitDistance) + ray.GetOrigin();
		
			hitPoint->x = pointOnBox.x;
			hitPoint->y = pointOnBox.y;
			hitPoint->z = pointOnBox.z;
		}
		return true;
	}
	return false;
}
Esempio n. 3
0
bool CheckRay(const CRay& ray, const CBoundingSphere& sphere, Vector3* hitPoint)
{
    //This algorithm is adatped from: http://www.cosinekitty.com/raytrace/chapter06_sphere.html
    //It breaks the problem down into the plane equations needed to find the hit points between the ray and sphere
    //To solve this correctly it makes use of a quadratic equation.
	Vector3 displacement = ray.GetOrigin() - sphere.GetCenter();
	float a = ray.GetDirection().LengthSquared();
	float b = 2.0f * displacement.Dot(ray.GetDirection());
	float c = displacement.LengthSquared() - sphere.GetRadius() * sphere.GetRadius();

	float randicand = b*b - 4.0f * a * c;
	//If the quadratic equation comes back as a negitive then there is no hit.
    if (randicand < 0.0f)
	{
		return false;
	}
	

	float root = sqrt(randicand);
	float denom = 2.0 * a;

    //Here we calculate the distance between ray origin and the two hit points (where the ray enters the sphere and where it exits)
	float hit1 = (-b + root) / denom;
	float hit2 = (-b - root) / denom;

    //If both of the hits are negitive then it means that the sphere is behind the origin of the ray so there is no hit
	if (hit1 < 0 && hit2 < 0)
	{
		return false;
	}

	
	if (hitPoint)
	{
        //If we need to know the first hit point on the sphere then we should use hit1, unless it's negative then we use hit2.
        //This would come up in situations where the origin of the ray is within the sphere.
        float firstHitDistance = hit1 < 0 ? hit2 : hit1;
		Vector3 pointOnSphere = (ray.GetDirection() * firstHitDistance) + ray.GetOrigin();
		hitPoint->x = pointOnSphere.x;
		hitPoint->y = pointOnSphere.y;
		hitPoint->z = pointOnSphere.z;
	}
	return true;
}
Esempio n. 4
0
bool
CSphere::Intersect(const CRay& clRay, RealType t0, RealType t1, TTracingContext& tContext ) const
{
	/*
		Implement ray-sphere intersection.
		You must set the following member of the TTracingContext struct:
		t          - ray parameter of intersection point
		v3Normal   - Normal of surface at intersection point
		v3HitPoint - Coordinate of intersection point
		v2TexCoord - 2D-Texture coordinate of intersection point (use polar coordinates (method Cartesian2Polar), not needed currently)
		pclShader  - Material of sphere
	*/

    VectorType3 vecDiff(m_v3Center - clRay.GetOrigin());


    RealType t_ca = vecDiff | clRay.GetDir();

    if (t_ca < 0)
        return false;

    RealType d2 = (vecDiff | vecDiff) - t_ca * t_ca;
    RealType r2 = m_rRadius * m_rRadius ;

    if (d2 > r2) {
        return false;
    }

    RealType desc = sqrt(r2 - d2);

    RealType t = (t_ca - desc) ;

    if (t < 0.0) {
        t = (t_ca + desc);
    }

    if (t > tContext.t) {
        return false;
    }
    tContext.t = t;

    tContext.v3HitPoint = clRay.Evaluate(tContext.t);
    tContext.v3Normal = (tContext.v3HitPoint - m_v3Center).normalize();

    tContext.pclShader = GetShader();

    return true;

}