Пример #1
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;
         }
     }
 }
Пример #2
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;
            }
        }
    }
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;
}
Пример #4
0
bool Find_Intersection(Intersection *isect, ObjectPtr object, const Ray& ray, const RayObjectCondition& postcondition, TraceThreadData *threadData)
{
    if(object != NULL)
    {
        DBL closest = HUGE_VAL;
        BBoxVector3d origin;
        BBoxVector3d invdir;
        BBoxDirection variant;

        Vector3d tmp(1.0 / ray.GetDirection()[X], 1.0 / ray.GetDirection()[Y], 1.0 /ray.GetDirection()[Z]);
        origin = BBoxVector3d(ray.Origin);
        invdir = BBoxVector3d(tmp);
        variant = (BBoxDirection)((int(invdir[X] < 0.0) << 2) | (int(invdir[Y] < 0.0) << 1) | int(invdir[Z] < 0.0));

        if(object->Intersect_BBox(variant, origin, invdir, closest) == false)
            return false;

        if(object->Bound.empty() == false)
        {
            if(Ray_In_Bound(ray, object->Bound, threadData) == false)
                return false;
        }

        IStack depthstack(threadData->stackPool);
        POV_REFPOOL_ASSERT(depthstack->empty()); // verify that the IStack pulled from the pool is in a cleaned-up condition

        if(object->All_Intersections(ray, depthstack, threadData))
        {
            bool found = false;
            double tmpDepth = 0;

            while(depthstack->size() > 0)
            {
                tmpDepth = depthstack->top().Depth;
                // TODO FIXME - This was SMALL_TOLERANCE, but that's too rough for some scenes [cjc] need to check what it was in the old code [trf]
                if(tmpDepth < closest && (ray.IsSubsurfaceRay() || tmpDepth >= MIN_ISECT_DEPTH) && postcondition(ray, object, tmpDepth))
                {
                    *isect = depthstack->top();
                    closest = tmpDepth;
                    found = true;
                }

                depthstack->pop();
            }

            return (found == true);
        }

        POV_REFPOOL_ASSERT(depthstack->empty()); // verify that the IStack is in a cleaned-up condition (again)
    }

    return false;
}
Пример #5
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);
 }
Пример #6
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;
		}
Пример #7
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;
}
Пример #8
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;
}
Пример #9
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() );
}
Пример #10
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;
}
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;
}
Пример #12
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;
}
Пример #13
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;
}
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::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;
}
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;
	}
	
}
Пример #17
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;
}
Пример #18
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;
}
Пример #19
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;
	}
}
Пример #20
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;
}
Пример #21
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;
}
Пример #23
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;
}
Пример #24
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;
}
Пример #25
0
bool Ray::operator== (const Ray& ray) const
{
	return m_direction == ray.GetDirection() && m_origin == ray.GetOrigin();
}
Пример #26
0
Color trace(const Scene& scene, Ray ray, int depth)
{
    const Color background(0,0,0);
    const int maxDepth = 3;
    if (depth >= maxDepth)
        return background;

    Color color(0,0,0);
    double distance = 0;
    const Primitive* prim = NULL;
    int intersectionType = 0;

    findNearsetIntersection(scene, ray, &prim, &distance, &intersectionType);

    if (prim != NULL)
    {
        if (prim->IsIlluminative())
        {
            return prim->GetMaterial().GetColor();
        }

        const Vector3 intersectionPoint = ray.GetPoint(distance);
        const Vector3 n = prim->GetNormal(intersectionPoint);

        if (prim->GetMaterial().GetDiffuse() > 0)
        {
            for (Scene::ConstIterator it = scene.Begin(); it != scene.End(); it++)
            {
                const double intensive = getIntensity((*it), intersectionPoint, n, scene);

                if (intensive != .0)
                {
                    Vector3 x = (prim->GetMaterial().GetColor());
                    Vector3 y = ((*it)->GetMaterial().GetColor());

                    color = color + (intensive * prim->GetMaterial().GetDiffuse()) * x * y;
                }
            }
        }

        //refraction
        {
            const Vector3 x = ray.GetDirection();
            const Vector3 y = intersectionType * (-n);

            double n;
            if (intersectionType == IntersectOutside)
                n = 1.0 / prim->GetMaterial().GetRefractionRate();
            else
                n = prim->GetMaterial().GetRefractionRate();

            const double sin_1 = sqrt(1 - Dot(x,y));
            const double sin_2 = n * sin_1;

            if (sin_2 < 1)
            {
                const double cos_2 = sqrt(1 - sin_2);
                Vector3 xPerpendicular = x - Dot(x,y)*y;
                Vector3 z = cos_2 * y + sin_2 * xPerpendicular;
                z.Normalize();

                if (prim->GetMaterial().GetRefraction() > 0)
                {
                    if (intersectionType == IntersectInside)
                    {
                        color = color +
                            prim->GetMaterial().GetRefraction() *
                            exp(-prim->GetMaterial().GetAbsorptionRate()*distance) *
                            trace(scene, Ray(intersectionPoint, z), depth + 1);
                    }
                    else
                        color = color +
                            prim->GetMaterial().GetRefraction() * trace(scene, Ray(intersectionPoint, z), depth + 1);
                }
            }
        }

        //reflection
        if (prim->GetMaterial().GetReflection() > 0)
        {
            const Vector3 a = ray.GetDirection();
            Vector3 newA = a - 2 * (Dot(a,n)) * n;
            color = color + prim->GetMaterial().GetReflection() * trace(scene, Ray(intersectionPoint, newA), depth + 1);
        }
    }
    return color;
}
Пример #27
0
bool BoundingBox::Intersect(const Ray &view_ray, float &distance_f) { 
	float t_near_f = 0.0f, t0_f, t1_f;
	float t_far_f = std::numeric_limits<float>::infinity();
	
	for(int i = 0; i < 3; ++i) {
		
		switch(i) {
			case 0: // X
				if(view_ray.GetDirection().x == 0) { 
					
					if((view_ray.GetPosition().x < this->GetMin().x) || (view_ray.GetPosition().x > this->GetMax().x)) 
						return false; // way off
					
				} else {
					t0_f = (this->GetMin().x - view_ray.GetPosition().x) / view_ray.GetDirection().x; // the first position for x, 
					t1_f = (this->GetMax().x - view_ray.GetPosition().x) / view_ray.GetDirection().x; // second... 
				}
				break;
				
			case 1: // Y
				if(view_ray.GetDirection().y == 0) {
					
					if((view_ray.GetPosition().y < this->GetMin().y) || (view_ray.GetPosition().y > this->GetMax().y)) 
						return false;
					
				} else {
					t0_f = (this->GetMin().y - view_ray.GetPosition().y) / view_ray.GetDirection().y;
					t1_f = (this->GetMax().y - view_ray.GetPosition().y) / view_ray.GetDirection().y;
				}
				break;
				
			case 2: // Z
				if(view_ray.GetDirection().z == 0) {
					
					if((view_ray.GetPosition().z < this->GetMin().z) || (view_ray.GetPosition().z > this->GetMax().z)) 
						return false;
					
				} else {
					t0_f = (this->GetMin().z - view_ray.GetPosition().z) / view_ray.GetDirection().z;
					t1_f = (this->GetMax().z - view_ray.GetPosition().z) / view_ray.GetDirection().z;
				}
				break;
				
			default:
				break;
		}
		
		// setting up the planes 
		
		if(t0_f > t1_f) 
			Math::Swap(t0_f, t1_f);
		
		t_near_f = Math::Max(t_near_f, t0_f);
		t_far_f = Math::Min(t1_f, t_far_f);
		
		// out of range, but the set-up is correct
		if((t_near_f > t_far_f) || (t_far_f < 0.0f)) 
			return false;
	}
	
	return true;
}