Пример #1
0
    void TranslationTool::ImpulseBegin(const Ray& ray) {
        UpdateScale();

        Vector3f position = transformable->GetPosition();
        Matrix transform = Matrix::CreateScale(Vector3f(scale)) * Matrix::CreateTranslation(position);
        BoundingBox xBox = BoundingBox::Transform(xAxisBBox, transform);    
        BoundingBox yBox = BoundingBox::Transform(yAxisBBox, transform);
        BoundingBox zBox = BoundingBox::Transform(zAxisBBox, transform);

        F32 distance;
        if (ray.Intersects(xBox, &distance)) {
            if (ray.Intersects(Plane(Vector3f::Up, -position.y), &distance)) {
                type = XAxis;
                prevPoint = ray.GetOrigin() + ray.GetDirection() * distance;
            }
        } else if (ray.Intersects(yBox, &distance)) {
            if (ray.Intersects(Plane(Vector3f::Backward, -position.z), &distance)) {
                type = YAxis;
                prevPoint = ray.GetOrigin() + ray.GetDirection() * distance;
            }
        } else if (ray.Intersects(zBox, &distance)) {
            if (ray.Intersects(Plane(Vector3f::Right, -position.x), &distance)) {
                type = ZAxis;
                prevPoint = ray.GetOrigin() + ray.GetDirection() * distance;
            }
        }
    }
Пример #2
0
 void TranslationTool::Impulse(const Ray& ray) {
     Vector3f position = transformable->GetPosition();
     switch(type) {
         case XAxis: {
             F32 distance;
             if (ray.Intersects(Plane(Vector3f::Up, -position.y), &distance)) {
                 Vector3f intersection = ray.GetOrigin() + ray.GetDirection() * distance;
                 F32 deltaX = intersection.x - prevPoint.x;
                 transformable->SetPosition(Vector3f(position.x + deltaX, position.y, position.z));
                 prevPoint = intersection;
             }
             break;
         }
         case YAxis: {
             F32 distance;
             if (ray.Intersects(Plane(Vector3f::Backward, -position.z), &distance)) {
                 Vector3f intersection = ray.GetOrigin() + ray.GetDirection() * distance;
                 F32 deltaY = intersection.y - prevPoint.y;
                 transformable->SetPosition(Vector3f(position.x, position.y + deltaY, position.z));
                 prevPoint = intersection;
             }
             break;
         }
         case ZAxis: {
             F32 distance;
             if (ray.Intersects(Plane(Vector3f::Right, -position.x), &distance)) {
                 Vector3f intersection = ray.GetOrigin() + ray.GetDirection() * distance;
                 F32 deltaZ = intersection.z - prevPoint.z;
                 transformable->SetPosition(Vector3f(position.x, position.y, position.z + deltaZ));
                 prevPoint = intersection;
             }
             break;
         }
     }
 }
Пример #3
0
        GeometryRayTestResult Intersects(const Sphere& Ball, const Ray& Cast)
        {
            // Code in this function is based on the equivalent in Ogre
            const Vector3 CastDir = Cast.GetNormal();
            const Vector3 CastOrigin = Cast.GetOrigin() - Ball.Center; // Makes math easier to do this in sphere local coordinates
            const Real Radius = Ball.Radius;

            // Build coefficients for our formula
            // t = (-b +/- sqrt(b*b + 4ac)) / 2a
            Real ACoEff = CastDir.DotProduct(CastDir);
            Real BCoEff = 2 * CastOrigin.DotProduct(CastDir);
            Real CCoEff = CastOrigin.DotProduct(CastOrigin) - ( Radius * Radius );

            // Get the Determinate
            Real Determinate = ( BCoEff * BCoEff ) - ( 4 * ACoEff * CCoEff );
            if( Determinate < 0 ) {
                return GeometryRayTestResult(false,Ray());
            }else{
                Real NearDist = ( -BCoEff - MathTools::Sqrt( Determinate ) ) / ( 2 * ACoEff );
                Real FarDist = ( -BCoEff + MathTools::Sqrt( Determinate ) ) / ( 2 * ACoEff );

                Ray Ret( Cast.GetOrigin() + (CastDir * NearDist), Cast.GetOrigin() + (CastDir * FarDist) );
                return GeometryRayTestResult(true,Ret);
            }
        }
bool BasicPrimitiveTests::IntersectingRayAgainstAABB(const Ray & ray, const AABB & aabb, float & rtn_t)
{
	/*
		Main Idea:
            -> Uses slab representation for box.
            -> Finds intersection of ray/segment with each slab. Then compares intersection times for overlap in all slabs.
                -> Keep track of:
                    -> A: The farthest of all entries into a slab
                    -> B: The closest of all exits out of a slab.
                -> If A > B at anytime, exit with no intersection. 

        Intersecting slabs:
            -> Intersect slabs by inserting ray equation into plane equations for slab.
            -> Solve for t

        -> Must handle case when ray parallel to slab separately.
            -> To avoid division by zero.

        Can test for intersection without calculating intersection point:
            -> Choose coordinate system where box is axis aligned and centered at origin:
                AABB:
                    -> Translate segment and AABB to origin.
                OBB:
                    -> Transform Segment to OBB space, then translate both segment and OBB to origin.

            -> Do separating axis test with 6 axes:
                -> Three principle axes.
                -> Three cross products of box face normals and segment direction vector.
	*/
	
	rtn_t = 0.0f;
	float tmax = FLT_MAX;
	Eigen::Vector3f aabb_min = aabb.GetCenter() - aabb.GetExtents();
	Eigen::Vector3f aabb_max = aabb.GetCenter() + aabb.GetExtents();
	for (int i = 0; i < 3; ++i)
	{
		if (abs(ray.GetDirection()[i]) < EPSILON)
		{
			//Ray is parallel to slab. Not hit if origin not within slab.
			if (ray.GetOrigin()[i] < aabb_min[i] || ray.GetOrigin()[i] > aabb_max[i])
			{
				return false;
			}
		}
		else
		{
			float one_over_direction = 1.0f / ray.GetDirection()[i];
			float t1 = (aabb_min[i] - ray.GetOrigin()[i]) * one_over_direction;
			float t2 = (aabb_max[i] - ray.GetOrigin()[i]) * one_over_direction;
			if (t1 > t2) Swap(t1, t2);
			if (t1 > rtn_t) rtn_t = t1;
			if (t2 > tmax) tmax = t2;
			if (rtn_t > tmax) return false;
		}
	}
	
	return true;
}
Пример #5
0
 Point3DTestResult Intersects(const Plane& Surface, const Ray& Cast)
 {
     // Code in this function is based on the equivalent in Ogre
     Real Denom = Surface.Normal.DotProduct( Cast.GetNormal() );// + Surface.Distance;
     if( MathTools::Abs(Denom) < std::numeric_limits<Real>::epsilon() ) {
         return Point3DTestResult( false, Vector3() );
     }else{
         Real Nom = Surface.Normal.DotProduct( Cast.GetOrigin() ) + Surface.Distance;
         Real Distance = -( Nom / Denom );
         return Point3DTestResult( true, Cast.GetOrigin() + ( Cast.GetNormal() * Distance) );
     }
     return Point3DTestResult( false, Vector3() );
 }
Пример #6
0
Файл: Ray.cpp Проект: panmar/pg3
 Ray Ray::Transform(const Ray& ray, const Matrix& transform) {
     Vector3f origin = ray.GetOrigin();
     Vector3f target = origin + ray.GetDirection() * ray.GetDistance();
     Vector3f newOrigin = Vector3f::Transform(origin, transform);
     Vector3f newTarget = Vector3f::Transform(target, transform);
     return Ray(newOrigin, newTarget);
 }
Пример #7
0
		Air::U1 MeshEntity::RayCast( const Ray& ray ,float*	pOutDistance)
		{
#if 1
			if(!GetWorldBoundingBox().RayCast(ray.GetOrigin(),ray.GetDirection())){//.Intersect(GetWorldBoundingBox())){
				return	false;
			}
#endif

			Matrix	matWorld	=	*GetWorldMatrix();
			Matrix	matWorldInv	=	matWorld;
			matWorldInv.Inverse();
			Float3	vStart	=	ray.m_vStart;
			Float3	vLookAt	=	vStart	+	ray.m_vDirection;
			vStart			=	matWorldInv*vStart;
			vLookAt			=	matWorldInv*vLookAt;
			Float3	vDir	=	(vLookAt	-	vStart);
			vDir.Normalize();

			Ray	objSpaceRay(vStart,vDir);

			float	fDistance	=	999999.0f;

			U1	bHit	=	m_pMesh->RayCast(objSpaceRay,&fDistance);
			if(bHit	&&	pOutDistance!=NULL){
				Float3	vObjSpaceHitPostion		=	vStart	+	vDir*fDistance;
				Float3	vWorldSpaceHiPosition	=	matWorld*vObjSpaceHitPostion;
				*pOutDistance	=	(vWorldSpaceHiPosition	-	ray.m_vStart).Length();
			}
			return	bHit;
		}
Пример #8
0
bool PlaneIntersector<real>::Intersect( const Plane<real>* plane, const Ray<real>& ray, Intersection<real>& oIntersection )
{
    const Vector3<real>& origin = ray.GetOrigin();
    const Vector3<real>& direction = ray.GetDirection();

    // Do not perform intersection if the direction of the ray is degenerated relative to the plane
    if ( fabs( direction.Y() ) > EPS )
    {
        // Compute the intersection point and see if it's inside the plane bounds
        real t = -origin.Y() / direction.Y();
        Vector3<real> intersectionPoint = origin + t * direction;
        bool isInsideXBounds = ( fabs( intersectionPoint.X() ) < plane->GetSizeX() * 0.5 ) ? true : false;
        bool isInsideZBounds = ( fabs( intersectionPoint.Z() ) < plane->GetSizeZ() * 0.5 ) ? true : false;

        // If the ray intersect and the intersection is in front
        if ( ( t > 0 ) && isInsideXBounds && isInsideZBounds )
        {
            oIntersection.SetPosition( intersectionPoint );
            oIntersection.SetNormal( Vector3<real>( 0, -sign<real>( direction.Y() ), 0 ) );
            oIntersection.IsInside( false );

            // Compute texture coodinates as (z=-0.5 => u=0 and x=-0.5 => v=0)
            real u = ( intersectionPoint.Z() + plane->GetSizeZ() * 0.5 ) / plane->GetSizeZ();
            real v = ( intersectionPoint.X() + plane->GetSizeX() * 0.5 ) / plane->GetSizeX();
            oIntersection.SetTextureCoordinates( Vector3<real>( u, v, 0 ) );

            return true;
        }
    }

    return false;
}
Пример #9
0
float Sphere::CheckCollision(Ray ray)
{
	Vector q = ray.GetOrigin();
	Vector v = ray.GetDirection();
	float A = pow(v.x, 2) + pow(v.y, 2) + pow(v.z, 2);
    float Bx = v.x * (q.x - origin.x);
    float By = v.y * (q.y - origin.y);
    float Bz = v.z * (q.z - origin.z);
    float B = 2 * (Bx + By + Bz);
    float C = pow(q.x - origin.x, 2) + pow(q.y - origin.y, 2) + pow(q.z - origin.z, 2) - pow(radius, 2);

    //Determines if we have a 'hit'
    float discriminant = pow(B, 2) - (4 * A * C);

    if (discriminant >= 0.f)
    {
        //Calculate our t values
        float root = sqrt(discriminant);
        float t1 = (-B + root) / (2 * A);
        float t2 = (-B - root) / (2 * A);
        float d = t1;
        if (t1 > t2 && t2 > 0) //Make sure we don't take a negative 
            d = t2; //Choose the smaller (closer) of the 2 values.

        if (d >= 0) //We want a positive distance from the starting vector
        {
            return d;
        }
    }

    return -1.0f;
}
Пример #10
0
Ray<real> NodeIntersector<real>::TransformRayToLocalCoordinates( const CoreLib::Node<real>* node, const Ray<real>& ray )
{
	const Matrix4<real>& globalToLocal = node->GetGlobalToLocal();

	// The origin is affected by the affine transformation while the direction is not affected by translation ( operator ^ )
	return Ray<real>( globalToLocal * ray.GetOrigin(), globalToLocal ^ ray.GetDirection() );
}
Пример #11
0
int Sphere::Intersect( Ray& a_Ray, float& a_Dist )
{
	vector3 v = a_Ray.GetOrigin() - m_Centre;
	float b = -DOT( v, a_Ray.GetDirection() );
	float det = (b * b) - DOT( v, v ) + m_SqRadius;
	int retval = MISS;
	if (det > 0)
	{
		det = sqrtf( det );
		float i1 = b - det;
		float i2 = b + det;
		if (i2 > 0)
		{
			if (i1 < 0) 
			{
				if (i2 < a_Dist) 
				{
					a_Dist = i2;
					retval = INPRIM;
				}
			}
			else
			{
				if (i1 < a_Dist)
				{
					a_Dist = i1;
					retval = HIT;
				}
			}
		}
	}
	return retval;
}
bool BasicPrimitiveTests::IntersectingRayAgainstAABB(const Ray & ray, const AABB & aabb)
{
	
	const Eigen::Vector3f & ray_d_aabb = ray.GetDirection();
	Eigen::Vector3f ray_o_aabb = ray.GetOrigin() - aabb.GetCenter();
	
	return 0;
}
Пример #13
0
bool SphereIntersector<real>::Intersect( const Sphere<real>* sphere, const Ray<real>& ray, Intersection<real>& oIntersection )
{
	// Compute the equation corresponding to x²+y²+z²=0 with p+t*d to obtain a quadratic equation
	real a = ray.GetDirection().SquaredLength();
	real b = 2.0 * ray.GetDirection() * ray.GetOrigin();
	real c = ray.GetOrigin().SquaredLength() - sphere->GetRadius() * sphere->GetRadius();

	real discriminant = b*b - 4*a*c;

	// Discriminant >= 0 => the must be at least one intersection
	if ( discriminant >= 0 )
	{
		// Compute the two potential intersections and only keep the nearest
		real sqrtDisc = sqrt( discriminant );
		real t = 0;
		real t1 = ( -b - sqrtDisc ) / ( 2.0 * a );
		real t2 = ( -b + sqrtDisc ) / ( 2.0 * a );

		if ( t1 >= 0 )
		{
			t = t1;
			oIntersection.IsInside( false );
		}
		else if ( t2 >= 0 )
		{
			t = t2;
			oIntersection.IsInside( true );
		}
		else
			return false;

		oIntersection.SetPosition( ray.GetOrigin() + t * ray.GetDirection() );
		oIntersection.SetNormal( oIntersection.GetPosition().Normalized() );
		oIntersection.SetTextureCoordinates( oIntersection.GetPosition().Normalized() );

		// The normal must be flipped to coincide with the hit direction
		if ( oIntersection.IsInside() )
			oIntersection.SetNormal( -oIntersection.GetNormal() );

		return true;
	}

	return false;
}
bool BasicPrimitiveTests::IntersectingRayAgainstOBB(const Ray & ray, const OBB & obb)
{
	
	Eigen::Matrix3f obb_rotation;
	obb.GetRotationMatrix(obb_rotation);
	Eigen::Vector3f ray_d_obb = obb_rotation * ray.GetDirection();
	Eigen::Vector3f ray_o_obb = obb_rotation * (ray.GetOrigin() - obb.GetCenter());
	
	return 0;
}
Пример #15
0
FPType Plane::GetIntersectionDisk(Ray ray, Vector3d normal_, Vector3d position)
{
	FPType denom = normal_.Dot(ray.GetDirection());
	FPType t = -1;
	if(std::abs(denom) > ray.tMin && t <= ray.tMax)
	{
		t = (position - ray.GetOrigin()).Dot(normal_) / denom;
	}
	return t;
}
Пример #16
0
FPType Plane::GetIntersection(const Ray &ray)
{
	FPType denom = normal.Dot(ray.GetDirection());
	if(std::abs(denom) > BIAS)
	{
		FPType t = (center - ray.GetOrigin()).Dot(normal) / denom;
		if(t > BIAS)
			return t;
	}
	return false;
}
Пример #17
0
bool Camera::getPoint(int mx, int my, const std::vector<LineSegment>& lines,
                      Vector3& p, const Plane& plane) {
    float minDist = 1000.0f;
    bool findCurr = false;
    Ray ray = getRay(mx, my);

    for (int i = 0; i < lines.size(); ++i) {
        for (int j = 0; j < 2; ++j) {
            if (Ray::distRayPoint(ray, lines[i].points[j]) < 0.1f) {
                if ((ray.GetOrigin() - lines[i].points[j]).length() < minDist) {
                    minDist = (ray.GetOrigin() - lines[i].points[j]).length();
                    p = lines[i].points[j];
                    findCurr = true;
                }
            }
        }
    }
    if (!findCurr)
        p = intersect(ray, plane);
    // std::cout<<p<<std::endl;
    return findCurr;
}
bool BasicPrimitiveTests::IntersectingRayAgainstSphere(const Ray & ray, const BoundingSphere & sphere, float & rtn_t)
{
	/*
		Main idea:
            - Ray is substituted into sphere equation. Then solve quadratic formula for intersection.
                - Test if intersection is within segment/ray endpoints

        -> Use dot(X-C, X-C) = exp(r, 2)
            -> As sphere equation.

        Solving for "t":
            -> Quadratic equation in "t" encountered.
                    -> where b = dot(m, d)
                    -> where c = dot(m, m) - r*r
						-> where m = P-C
                -> t = -b + sqrt(exp(b, 2) - c)
                -> t = -b - sqrt(exp(b, 2) - c)

        Notes:
            -> Number of real roots => number of intersections:
                -> Categorized by discriminant d = exp(b, 2) - c

            -> May have false intersection with t < 0 when ray starts from inside sphere.
	*/
	
	Eigen::Vector3f m = ray.GetOrigin() - sphere.GetCenter();
	float b = (m).dot(ray.GetDirection());
	float c = m.dot(m);
	if (c > 0.0f && b > 0.0f)
	{
		//Case: Ray origin outside of sphere and points away. => No Intersections.
		return false;
	}
	float discriminant = b * b - c;
	if (discriminant < 0.0f)
	{
		//Case: Misses sphere
		return false;
	}
	else
	{
		//Case: Hits sphere. Calculate smallest t.
		rtn_t = -b - sqrt(discriminant);
		if (rtn_t < 0.0f)
		{
			rtn_t = 0.0f;
		}
		return true;
	}
	
}
Пример #19
0
bool AABB::Intersect(Ray &ray)
{
	glm::vec3 invDir = 1.0f / ray.GetDirection();
	float tmin = (pMin.x - ray.GetOrigin().x) * invDir.x;
	float tmax = (pMax.x - ray.GetOrigin().x) * invDir.x;

	if (tmin > tmax) swap(tmin, tmax);

	float tymin = (pMin.y - ray.GetOrigin().y) * invDir.y;
	float tymax = (pMax.y - ray.GetOrigin().y) * invDir.y;

	if (tymin > tymax) swap(tymin, tymax);

	if ((tmin > tymax) || (tymin > tmax))
		return false;

	if (tymin > tmin)
		tmin = tymin;

	if (tymax < tmax)
		tmax = tymax;

	float tzmin = (pMin.z - ray.GetOrigin().z) * invDir.z;
	float tzmax = (pMax.z - ray.GetOrigin().z) * invDir.z;

	if (tzmin > tzmax) swap(tzmin, tzmax);

	if ((tmin > tzmax) || (tzmin > tmax))
		return false;

	if (tzmin > tmin)
		tmin = tzmin;

	if (tzmax < tmax)
		tmax = tzmax;

	return true;
}
Пример #20
0
int PlanePrim::Intersect( Ray& a_Ray, float& a_Dist )
{
	float d = DOT( m_Plane.N, a_Ray.GetDirection() );
	if (d < 0)
	{
		float dist = -(DOT( m_Plane.N, a_Ray.GetOrigin() ) + m_Plane.D) / d;
		if (dist < a_Dist) 
		{
			a_Dist = dist;
			return HIT;
		}
	}
	return MISS;
}
Пример #21
0
bool Renderer::RaySphereIntersection(Ray ray, Sphere sphere)
{
	Vector d = ray.GetDirection();
	Vector e = ray.GetOrigin();
	Vector c = sphere.GetCenter();
	int R = sphere.GetRadius();

	float discriminant = (d ^ (e - c)) * (d ^ (e - c)) - ((d ^ d) * (((e - c) ^ (e - c)) - R * R));

	if(discriminant >= 0.0)
		return true;

	return false;
}
Пример #22
0
int Box::Intersect( Ray& a_Ray, float& a_Dist )
{
	m_RayID = a_Ray.GetID();
	float dist[6];
	vector3 ip[6], d = a_Ray.GetDirection(), o = a_Ray.GetOrigin();
	bool retval = MISS;
	for ( int i = 0; i < 6; i++ ) dist[i] = -1;
	vector3 v1 = m_Box.GetPos(), v2 = m_Box.GetPos() + GetSize();
	if (d.x) 
	{
		float rc = 1.0f / d.x;
		dist[0] = (v1.x - o.x) * rc;
		dist[3] = (v2.x - o.x) * rc;
	}
	if (d.y) 
	{
		float rc = 1.0f / d.y;
		dist[1] = (v1.y - o.y) * rc;
		dist[4] = (v2.y - o.y) * rc;
	}
	if (d.z) 
	{
		float rc = 1.0f / d.z;
		dist[2] = (v1.z - o.z) * rc;
		dist[5] = (v2.z - o.z) * rc;
	}
	for ( int i = 0; i < 6; i++ ) if (dist[i] > 0)
	{
		//ip[i] = o + dist[i] * d;  // Uses vector addition and multiplication 
		ip[i].x = o.x + dist[i] * d.x;
		ip[i].y = o.y + dist[i] * d.y;
		ip[i].z = o.z + dist[i] * d.z;
		if ((ip[i].x > (v1.x - EPSILON)) && (ip[i].x < (v2.x + EPSILON)) && 
			(ip[i].y > (v1.y - EPSILON)) && (ip[i].y < (v2.y + EPSILON)) &&
			(ip[i].z > (v1.z - EPSILON)) && (ip[i].z < (v2.z + EPSILON)))
		{
			if (dist[i] < a_Dist) 
			{
				a_Dist = dist[i];
				retval = HIT;
			}
		}
	}
	return retval;
}
Пример #23
0
int Camera::getLine(int mx, int my, const std::vector<LineSegment>& lines,
                    LineSegment& line) {
    Ray ray = getRay(mx, my);
    Vector3 v1 = ray.GetOrigin();
    Vector3 v2 = v1 + ray.GetDirection() * 100.0f;
    LineSegment l;
    l.points[0] = v1;
    l.points[1] = v2;
    float minDist = 1000.0f;
    int linePos = -1;
    for (int i = 0; i < lines.size(); ++i) {
        float dist = LineSegment::distSegmentSegment(lines[i], l);
        if (dist <= 0.1f) {
            minDist = dist;
            line = lines[i];
            linePos = i;
        }
    }
    return linePos;
}
bool BasicPrimitiveTests::IntersectingRayAgainstOBB(const Ray & ray, const OBB & obb, float & rtn_t)
{
	
	Eigen::Matrix3f obb_rotation;
	obb.GetRotationMatrix(obb_rotation);
	Eigen::Vector3f ray_d_obb = obb_rotation * ray.GetDirection();
	Eigen::Vector3f ray_o_obb = obb_rotation * (ray.GetOrigin() - obb.GetCenter());

	
	rtn_t = 0.0f;
	float tmax = FLT_MAX;
	Eigen::Vector3f aabb_min = -obb.GetExtents();
	Eigen::Vector3f aabb_max = obb.GetExtents();
	for (int i = 0; i < 3; ++i)
	{
		if (abs(ray_d_obb[i]) < EPSILON)
		{
			//Ray is parallel to slab. Not hit if origin not within slab.
			if (ray_o_obb[i] < aabb_min[i] || ray_o_obb[i] > aabb_max[i])
			{
				return false;
			}
		}
		else
		{
			float one_over_direction = 1.0f / ray_d_obb[i];
			float t1 = (aabb_min[i] - ray_o_obb[i]) * one_over_direction;
			float t2 = (aabb_max[i] - ray_o_obb[i]) * one_over_direction;
			if (t1 > t2) Swap(t1, t2);
			if (t1 > rtn_t) rtn_t = t1;
			if (t2 > tmax) tmax = t2;
			if (rtn_t > tmax) return false;
		}
	}
	
	
	return true;
}
Пример #25
0
// ray tracing
Colour RayTracer::TraceRay(Ray& ray, int traceDepth)
{
	if (traceDepth > MAXTRACEDEPTH)
		return Colour();

	Colour		litColour, reflectedColour;
	float		distanceToIntersect = MAXDISTANCE;
	Vector3f		intersectionPoint;
	Primitive*	nearestPrimitive = 0;

	nearestPrimitive = mScene->GetFirstPrimitive(ray, distanceToIntersect);

	if (!nearestPrimitive)
		return Colour();

	else
	{
		// Ambient,Specular lighting
		intersectionPoint = ray.GetOrigin() + ray.GetDirection() * distanceToIntersect;
		litColour = mScene->CalculatePrimitiveLightingAtPoint((*nearestPrimitive), intersectionPoint, ray.GetDirection());

		//  reflection
		float reflectionFactor = nearestPrimitive->GetMaterial()->Reflection;

		if (reflectionFactor > 0.0f)
		{
			Vector3f normal = nearestPrimitive->GetNormal(intersectionPoint);
			Vector3f reflected = ray.GetDirection() - normal * (2.0f * (ray.GetDirection()*normal));

			Ray reflectedRay = Ray(intersectionPoint , reflected);
			reflectedColour = TraceRay(reflectedRay, traceDepth + 1) * reflectionFactor;
		}

		return litColour + reflectedColour;
	}
}
Пример #26
0
bool CylinderIntersector<real>::Intersect( const Cylinder<real>* cylinder, const Ray<real>& ray, Intersection<real>& oIntersection )
{
	real nearestDistance = std::numeric_limits<real>::max();
	real distance = 0;
	bool hasIntersection = false;

	////////////////////////////////////////////
	//////////////////IFT 3355//////////////////
	////////////////////////////////////////////
	//Ici, vous calculerez l'intersection entre
	//le rayon "ray" et le cylindre "cylinder"
	//Pensez à initialiser les quatre attributs
	//de oIntersection (retourné par référence)
	//correctement si une intersection est trouvée.
	////////////////////////////////////////////
	//////////////////IFT 3355//////////////////
	////////////////////////////////////////////

    real halfHeight = cylinder->GetHeight() / 2;
    real radius = cylinder->GetRadius();

    // Intersection with extremeties.
    Vector3<real> extremeties[2] = {
        Vector3<real>(0, halfHeight, 0),
        Vector3<real>(0, -halfHeight, 0),
    };

    for (int k = 0; k < 2; ++k) {
        Vector3<real> plane = extremeties[k];
        real denom = ray.GetDirection() * plane;
	    bool intersectsPlane = fabs(denom) > EPS;

	    // Ray intersects with the extremety.
	    if (intersectsPlane) {
            // Intersection position on the infinite plane.
	        real t = ((plane - ray.GetOrigin()) * plane) / denom;
	        Vector3<real> intersectionPos = ray.GetOrigin() + t * ray.GetDirection();
	        // Ray intersects in the window.
            if ((plane - intersectionPos).Length() <= radius &&
                ray.GetDirection() * plane < 0 &&
                t > EPS && t <= nearestDistance) {
                oIntersection.SetNormal(plane);
                oIntersection.SetPosition(intersectionPos);
                oIntersection.SetTextureCoordinates(intersectionPos);
                oIntersection.IsInside(false);
                nearestDistance = t;
                hasIntersection = true;
            }
        }
    }




    // Intersection with main body
    Vector3<real> o = Vector3<real>(ray.GetOrigin().X(), 0, ray.GetOrigin().Z());
    Vector3<real> d = Vector3<real>(ray.GetDirection().X(), 0, ray.GetDirection().Z());
    real a = d*d;
    real b = 2 * d * o;
    real c = o * o - (radius*radius);

    real discr = b*b - 4*a*c;

    if (discr < -EPS) {
        return hasIntersection;           // No intersection.
    }
    else {
        real t1 = (-b - sqrt(discr)) / (2*a);
        real t2 = (-b + sqrt(discr)) / (2*a);
        real t = std::min<real>(t1, t2);
        Vector3<real> intersectionPos = ray.GetOrigin() + t * ray.GetDirection();
        if (t >= EPS && t < nearestDistance && fabs(intersectionPos.Y()) < halfHeight+EPS) {
            oIntersection.SetNormal(intersectionPos - Vector3<real>(0, intersectionPos.Y(), 0));
            oIntersection.SetPosition(intersectionPos);
            oIntersection.SetTextureCoordinates(intersectionPos);
            oIntersection.IsInside(false);
            nearestDistance = t;
            hasIntersection = true;
        }
    }

	return hasIntersection;
}
Пример #27
0
bool Ray::operator== (const Ray& ray) const
{
	return m_direction == ray.GetDirection() && m_origin == ray.GetOrigin();
}
Пример #28
0
        GeometryRayTestResult Intersects(const AxisAlignedBox& Box, const Ray& Cast)
        {
            // Code in this function is based on the equivalent in Ogre
            Vector3 CastDir = Cast.GetNormal();
            Vector3 AbsoluteDir = CastDir;
            AbsoluteDir.X = MathTools::Abs( AbsoluteDir.X );
            AbsoluteDir.Y = MathTools::Abs( AbsoluteDir.Y );
            AbsoluteDir.Z = MathTools::Abs( AbsoluteDir.Z );

            // A small fixed sized constant time sorting algorithm for sorting the length of each axis.
            Whole MaxAxis = 0, MidAxis = 1, MinAxis = 2;
            if( AbsoluteDir[0] < AbsoluteDir[2] ) {
                MaxAxis = 2;
                MinAxis = 1;
            }else if( AbsoluteDir[1] < AbsoluteDir[MinAxis] ) {
                MidAxis = MinAxis;
                MinAxis = 1;
            }else if( AbsoluteDir[1] > AbsoluteDir[MaxAxis] ) {
                MidAxis = MaxAxis;
                MaxAxis = 1;
            }

            if(IsInside(Box,Cast.Origin))
            {
                Vector3 Intersects;
                Intersects[MinAxis] = 0;
                Intersects[MidAxis] = 0;
                Intersects[MaxAxis] = 1;
                /*Plane Side(Intersects,)
                if(CastDir[MaxAxis]>0)
                {

                }else{

                }
                return GeometryRayTestResult(true,Ray(,Vector3));*/
            }

            SegmentPosPair Distances(0,std::numeric_limits<Real>::infinity());

            ::CalculateAxis(MaxAxis,Cast,Box,Distances);
            if( AbsoluteDir[MidAxis] < std::numeric_limits<Real>::epsilon() ) {
                if( Cast.GetOrigin()[MidAxis] < Box.MinExt[MidAxis] || Cast.GetOrigin()[MidAxis] > Box.MaxExt[MidAxis] ||
                    Cast.GetOrigin()[MinAxis] < Box.MinExt[MinAxis] || Cast.GetOrigin()[MinAxis] > Box.MaxExt[MinAxis] )
                {
                    return GeometryRayTestResult(false,Ray());
                }
            }else{
                ::CalculateAxis(MidAxis,Cast,Box,Distances);
                if( AbsoluteDir[MinAxis] < std::numeric_limits<Real>::epsilon() ) {
                    if( Cast.GetOrigin()[MinAxis] < Box.MinExt[MinAxis] || Cast.GetOrigin()[MinAxis] > Box.MaxExt[MinAxis] ) {
                        return GeometryRayTestResult(false,Ray());
                    }
                }else{
                    ::CalculateAxis(MinAxis,Cast,Box,Distances);
                }
            }

            Ray Ret( Cast.GetOrigin() + (CastDir * Distances.first), Cast.GetOrigin() + (CastDir * Distances.second) );
            return GeometryRayTestResult(true,Ret);
        }