Exemple #1
0
bool Plane::intersect(const Ray& ray, IntersectionData& intersectionData)
{
	if ((ray.Start().Y() > this->Y() && ray.Direction().Y() > VerySmall) ||
		(ray.Start().Y() < this->Y() && ray.Direction().Y() < VerySmall))
	{
		return false;
	}

	double yRayDirection = ray.Direction().Y();
	double yDifference = ray.Start().Y() - this->Y();
	double multiplier = yDifference / -yRayDirection;

	if (multiplier > intersectionData.getDistance())
	{
		return false;
	}

	Vector intersectionPoint = ray.Start() + ray.Direction() * multiplier;

	if (fabs(intersectionPoint.X()) > this->Limit() || fabs(intersectionPoint.Z()) > this->Limit())
	{
		return false;
	}

	intersectionData.setIntersectionPoint(intersectionPoint);
	intersectionData.setDistance(multiplier);
	intersectionData.setNormal(Vector(0.0, 1.0, 0.0));
	intersectionData.setTextureU(intersectionData.IntersectionPoint().X());
	intersectionData.setTextureV(intersectionData.IntersectionPoint().Z());

	return true;
}
Exemple #2
0
//------------------------------------------------------------------------------
bool Plane::Intersect( const Ray& _ray, Intersection& o_intersection) const
{
	float rayParameter = ( m_distance - m_normal.Dot( _ray.Origin() ) ) / m_normal.Dot( _ray.Direction() );

	if (rayParameter < 0.0f)
		return false;

	Vector position = _ray.Origin() + _ray.Direction() * rayParameter;

	o_intersection =  Intersection( position, m_normal,Vector2D(0,0), rayParameter, m_pMaterial );
	return true;
}
bool DielectricMaterial::Scatter( const Ray& ray, const HitRecord& record, Vector3& attenuation, Ray& scattered ) const
{
	attenuation = Vector3( 1.f, 1.f, 1.f );
	const float dirDotNormal = ray.Direction().Dot( record.normal );

	Vector3 outwardNormal;
	float niOverNt;
	float cosine;
	
	if ( dirDotNormal > 0.f )
	{
		outwardNormal = -record.normal;
		niOverNt = refractionIndex;
		//cosine = refractionIndex * dirDotNormal / ray.Direction().Length();
		cosine = dirDotNormal / ray.Direction().Length();
		cosine = std::sqrt( 1.f - refractionIndex * refractionIndex * ( 1.f - cosine * cosine ) );
	}
	else
	{
		outwardNormal = record.normal;
		niOverNt = 1.f / refractionIndex;
		cosine = -dirDotNormal / ray.Direction().Length();
	}

	const Vector3 reflected = Reflect( ray.Direction(), record.normal );

	float reflectProbability;
	Vector3 refracted;
	if ( Refract( ray.Direction(), outwardNormal, niOverNt, refracted ) )
	{
		reflectProbability = Schlick( cosine, refractionIndex );
	}
	else
	{
		reflectProbability = 1.f;
	}

	if ( Rand01() < reflectProbability )
	{
		scattered = Ray( record.point, reflected );
	}
	else
	{
		scattered = Ray( record.point, refracted );
	}

	return true;
}
Exemple #4
0
Color RayTracer::Render(const Ray& rRay, bool vIsReflecting, const Shape* pReflectingFrom )
{
	mRecursions++;
	Shape* closest_shape;
	Point intersect_point;
	Color result;
	if (vIsReflecting)
		closest_shape = QueryScene(rRay, intersect_point, vIsReflecting, pReflectingFrom);
	else
		closest_shape = QueryScene(rRay, intersect_point);

	if (closest_shape == NULL && !vIsReflecting)
	{
		mRecursions = 0;
		return mBackgroundColor;
	}
	if (closest_shape == NULL && vIsReflecting)
	{
		mRecursions = 0;
		return mAmbientColor*mAmbientIntensity;
	}
	if ( mRecursions > mRecursionLimit )
	{
		mRecursions = 0;
		return Color(0,0,0); // mAmbientColor*mAmbientIntensity;
	}
	result = closest_shape->ShapeColor()*Shade(closest_shape, intersect_point);

	Ray backwards_ray(intersect_point,rRay.Direction()*-1);
	if ( closest_shape->DiffuseReflectivity() > 0.0 )
		result = result + (Render( closest_shape->Reflect(intersect_point,backwards_ray), true, closest_shape )*closest_shape->DiffuseReflectivity());

	return (result + mSpecularColor);
}
Color FresnelTexture::getTextureColor(const Ray& ray, double u, double v, Vector& normal) const
{
	Vector faceForwardNormal = Vector::faceForward(ray.Direction(), normal);

	double indexOfRefraction = this->indexOfRefraction;
	
	// If the ray is entering the geometry we must use the reciprocal of the index of refraction
	if (Vector::dotProduct(ray.Direction(), normal) > 0.0)
	{
		indexOfRefraction = 1.0 / indexOfRefraction;
	}

	double fresnelCoefficient = this->fresnel(ray.Direction(), faceForwardNormal, indexOfRefraction);

	Color resultColor(fresnelCoefficient, fresnelCoefficient, fresnelCoefficient);

	return resultColor;
}
Exemple #6
0
Ray Shape::Reflect(const Point& rReflectFrom, const Ray& rIncidentRay) const
{
	Ray result; // the reflected ray
	Vector result_direction; // the reflected direction vector
	Vector incident_unit = rIncidentRay.Direction().Normalize();
	Vector normal = this->Normal(rReflectFrom, rIncidentRay.Origin() );
	if ( !normal.IsSameDirection(incident_unit) )
		normal.ReverseDirection(); // we want the normal in the same direction of the incident ray.

	result.Origin(rReflectFrom);
	result.Direction( normal*2.0*normal.Dot(incident_unit) - incident_unit );
/*
	if ( normal.Dot(rIncidentRay.Direction().Normalize()) < 0.0 )
		normal.ReverseDirection();

	result.Origin(rReflectFrom);
	result.Direction((normal*2.0) - rIncidentRay.Direction().Normalize());
*/

	return result;
}
Exemple #7
0
double RayTracer::Specular(const Shape* pShapeToShade, const Point& rPointOnShapeToShade, const Light* pLight)
{
	Ray reflected = pShapeToShade->Reflect(rPointOnShapeToShade,Ray(rPointOnShapeToShade, pLight->LightPoint()));

	Vector eye_vector(rPointOnShapeToShade, mEyePoint);
	Vector reflected_vector = reflected.Direction().Normalize();
	eye_vector.NormalizeThis();
	double dot_product = eye_vector.Dot(reflected_vector);	
	
	int n = pShapeToShade->SpecularSize();
	double specular_intensity = dot_product/(n - n*dot_product+ dot_product);
	return unit_limiter(specular_intensity*pLight->Intensity());
}
Exemple #8
0
//------------------------------------------------------------------------------
bool Sphere::Intersect( const Ray& _ray, Intersection& o_intersection ) const
{
	Vector p = Position() - _ray.Origin();
	float pDotRayDir = p.Dot( _ray.Direction() );
	// ray pointing away from sphere
	if(( pDotRayDir )<0 )
		return false;

	/* pDotRayDir distance between origin and P's projection on Ray
	  p.Dot( p ) magnitude sqaured of p
	 
	   O,             O,          
		|\             |\         
		| \            |  \        
	   R.  \ p        R.    \     p
		|   \ ,--      |      \ ,-- 
		|   '\         |      '\    
		| '   \        |    '    \
		|'_____.       |___'______ .  
	   Q '   r   P    Q    '   r   P
		  '
		figure 1 )          figure 2 )
	 
	  1 ) rSquared + RSquared = PSquared
	  2 ) rSquared + RSquared < PSquared
	 */
	float temp = m_radiusSquared + pDotRayDir * pDotRayDir - p.Dot( p );
	// no intersection
	if ( temp < 0.0f )
	{
		return false;
	}
	//rayParameter = pDotRayDir - sqrtf( temp );
	float rayParameter;
	// if ray origin is inside sphere
	if ( ( pDotRayDir - sqrtf( temp ) )  < 0.0f )
	{
		rayParameter = pDotRayDir + sqrtf( temp );
		Vector intersectionPos= _ray.GetPosition( rayParameter );
		Vector normal = ( intersectionPos - Position() ).Normalise();
		o_intersection =  Intersection( intersectionPos, normal, Vector2D(0,0), rayParameter, g_air );
		//intersection inside sphere;
		return true;
	}
		
	rayParameter = pDotRayDir - sqrtf( temp );
	Vector intersectionPos = _ray.GetPosition( rayParameter );
	Vector normal = ( intersectionPos - Position() ).Normalise();
	o_intersection =  Intersection( intersectionPos, normal, Vector2D(0,0), rayParameter, m_pMaterial );
	return true;
}
Exemple #9
0
// Light's Functions
void AreaLight::AccumulateIlluminationAtSurface(
    const Ray           &ray,
    const Vector<float> &surfaceNormal,
    const float         &surfaceRoughness,
    const Scene         &scene,
    Color &diffuse,
    Color &specular ) const
{
    if( _positions.empty() )
        return;

    Color areaLightDiffuse( 0 );
    Color areaLightSpecular( 0 );

    // Accumulate the illumination from all the positions
    for(VectorList::const_iterator itr = _positions.begin(); itr != _positions.end(); ++itr )
    {
        const Vector<float> &lightPosition = (*itr);

        Vector<float> lightRayDirection = lightPosition - ray.Origin();
        const float lightRayLength = lightRayDirection.Normalize();

        // If the light is out of range of the surface
        if( lightRayLength > _range )
            continue;

        // The illumination from this light
        const Ray lightRay( ray.Origin(), lightRayDirection, ray );
        const Color illuminationFromLight = Illumination( lightRay, lightRayLength, scene );

        if( illuminationFromLight.Magnitude2() < Maths::Tolerance )
            continue;

        // Calculate the illumination at the point on the surface
        const Color illumination = illuminationFromLight * ( 1 - lightRayLength * _oneOverRange );

        // Accumulate the diffuse
        areaLightDiffuse += illumination * Maths::Max<float>(0, surfaceNormal.Dot( lightRayDirection ));

        // Accumulate the specular
        areaLightSpecular += illuminationFromLight * powf( Maths::Max<float>(0, ray.Direction().Dot( lightRayDirection.Reflect( surfaceNormal ) ) ), surfaceRoughness );
    }

    diffuse += areaLightDiffuse * (1.0f / _positions.size());
    specular += areaLightSpecular * (1.0f / _positions.size());
}
Exemple #10
0
bool Plane::Intersect(const Ray& ray, Intersection& intersection, void* additional_data) const
{
	float dir_norm = ray.Direction().DotProduct(m_Orientation);

	if (abs(dir_norm) < std::numeric_limits<float>::epsilon())
		return false;

	float t = (m_Center - ray.Origin()).DotProduct(m_Orientation) / dir_norm;

	Range<float> range = ray.EffectRange();

	if (Math::Contain(t, range))
	{
		intersection.SetDistance(t);
		intersection.SetIntersectObject((IIntersectTarget*)this);
		intersection.SetTestObject(&ray);

		return true;
	}

	return false;
}
Exemple #11
0
//------------------------------------------------------------------------
Ray operator * ( const Matrix& _transform, const Ray& _ray )
{
    return Ray( _transform * _ray.Origin(), _transform * _ray.Direction(), _ray.GetMaterial() );
}
Exemple #12
0
bool Kdtree::intersect(Ray &r, HitInfo* pHitInfo )
{
    pHitInfo->bHasInfo = false;
    pHitInfo->hitTime = INFINITY;
    Point3 invDir(1.f/r.Direction().X(), 1.f/r.Direction().Y(), 1.f/r.Direction().Z());
    float tmin = 0;
    float tmax = 0;

    // intersect bounding box
    if(!m_Bounds.Intersect(r, tmin, tmax))
    {
        return false;
    }

    bool done = false;
    list<TODO> todo;
    BSPNode *current = &m_pTree[0];

    while(!done)
    {
        if(pHitInfo->hitTime < tmin)
        {
            break;
        }

        if(!current->isLeaf())
        {
            int axis = current->splitAxis();
            float split = current->SplitPos();
            split = (split > -EPSILON && split < EPSILON) ? 0 : split;
            float tplane = (split - r.Origin()[axis]) * invDir[axis];

            BSPNode *first, *second;
            // decide which child to check first
            int below = r.Origin()[axis] <= split;
            if(below)
            {
                first = &m_pTree[current->leftChild];
                second = &m_pTree[current->leftChild+1];
            }
            else
            {
                second = &m_pTree[current->leftChild];
                first = &m_pTree[current->leftChild+1];
            }

            if(tplane == 0)//(tplane > -EPS && tplane < EPS)
            {
                if(invDir[axis] > 0)
                    current = second;
                else
                    current = first;
            }
            else if(tplane >= tmax || tplane < 0)
                current = first;
            else if(tplane <= tmin)
                current = second;
            else
            {
                TODO temp;
                temp.node = second;
                temp.tmax = tmax;
                temp.tmin = tplane;
                todo.push_front(temp);
                current = first;
                tmax = tplane;
            }
        }
        else
        {
            // check all intersect in this leaf
            std::list<IPrimitive*>::const_iterator it;

            if(current->m_pPrimList)
            {
                for(int i = 0; i < current->nTriangle(); i++)
                {
                    HitInfo thisHit;
                    current->m_pPrimList[i]->intersect( r, &thisHit);
                    if( thisHit.hitTime < pHitInfo->hitTime )
                    {
                        *pHitInfo = thisHit;
                    }
                } // end checking all Primitives in this leaf
            }
            if(!todo.empty())
            {
                TODO temp = (*todo.begin());
                current = temp.node;
                tmin = temp.tmin;
                tmax = temp.tmax;
                todo.pop_front();
            }
            else
            {
                done = true;
            }

        } // end check leaf
    } // end while loop

    return pHitInfo->bHasInfo;
}
Vector3D RecursiveTraceStrategy::operator ()(const Ray &tracer, const int depth, const double refrIndex) const
{
    double usableEpsilion = std::numeric_limits<float>::epsilon(); // Epsilon for a float will always produce a usable delta for doubles (this is a little bit of a bad idea)

    //begin traversing the world
    //
    double closestDist = std::numeric_limits<double>::infinity();
    std::shared_ptr<Shape> closest;

    for(std::shared_ptr<Shape> s : _Shapes)
    {
        //find the distance from the origin to the point of intersection
        //
        double dist = s->Intersect(tracer);
        if(dist > 0)
        {
            if(dist > closestDist)
                continue;

            closestDist = dist;
            closest = s;
        }
    }

    if(closest == nullptr)
        return {0.0, 0.0, 0.0};

    Vector3D compositeColor = {0.0, 0.0, 0.0};

    //calculate the position vector of the point of intersection using the line along the current ray
    //
    Vector3D intersectPoint = tracer.Origin() + (tracer.Direction() * closestDist);

    //get the unit normal at the point of intersection to apply shading
    Vector3D unitNormal = closest->Normal(intersectPoint);

    // Get the material of the shape
    std::shared_ptr<const Material> shapeMat = closest->SurfaceMaterial();

    //traverse the world again looking for lights
    //
    for(std::shared_ptr<Light> l : _Lights)
    {
        //retrieve the position vector of the light source (treated as a uniform pointline source)
        Vector3D lightCenter = l->Position();

        //create a vector from the intersect point to the light source
        Vector3D toLight = (lightCenter - intersectPoint).Normalize();

        //calculate occlusion (for a pointlike source this is boolean)
        // Note that I'm adding a small offset in the direction we want to go so that we don't
        // intersect with the current shape
        Ray occlRay(intersectPoint + (usableEpsilion * toLight), toLight);
        double visibility = 1.0; // occlusion = 1 - visibility
        for(std::shared_ptr<Shape> o : _Shapes)
        {
            double d = o->Intersect(occlRay);

            if(d > 0)
            {
                visibility = 0.0;
                break;
            }
        }

        if(visibility > 0)
        {
            //apply lighting function
            //
            double radianceDist = shapeMat->Brdf(tracer.Direction(), toLight, unitNormal);

            std::shared_ptr<const Material> lightMat = l->LightMaterial();
            compositeColor += shapeMat->Color().Weight(lightMat->Color() * radianceDist * visibility);
        }
    }

    //apply reflections
    //
    double refl = shapeMat->Reflectance();
    double refr = shapeMat->Refractance();
    double rindex = shapeMat->IndexOfRefraction();

    if(refl > 0.0 && depth < _MaxTraceIterations)
    {
        Vector3D reflectionDir;
        reflectionDir = tracer.Direction() - 2.0 * (tracer.Direction() * unitNormal) * unitNormal;

        Ray reflected(intersectPoint + (usableEpsilion * reflectionDir), reflectionDir);

        Vector3D reflCol = (*this)(reflected, depth + 1, refrIndex);

        compositeColor += shapeMat->Color().Weight(refl * reflCol);
    }

    //apply refractions
    //
    if(refr > 0.0 && depth < _MaxTraceIterations)
    {
        // This is basically Snell's law
        double relIndex = refrIndex / rindex;

        Vector3D refractionNormal = unitNormal;

        // The cosine between the incident ray's direction and the unit normal should be non-positive (e.g. angle in [PI/2, PI]), otherwise normals need to be reversed
        if(refractionNormal * tracer.Direction() > 0)
            refractionNormal *= -1;

        double cosI = - (refractionNormal * tracer.Direction());
        double cosT2 = 1.0 - (relIndex * relIndex) * (1.0 - (cosI * cosI));
        if(cosT2 > 0.0)
        {
            Vector3D refractedDir = (relIndex * tracer.Direction()) + (relIndex * cosI - sqrt(cosT2)) * refractionNormal;
            Ray refracted(intersectPoint + (usableEpsilion * refractedDir), refractedDir);

            Vector3D refrCol = (*this)(refracted, depth + 1, rindex);

            compositeColor += shapeMat->Color().Weight(refr * refrCol);
        }
    }

    return compositeColor;
}
Exemple #14
0
//------------------------------------------------------------------------------
//from[http://www.flipcode.com/archives/Raytracing_Topics_Techniques-Part_7_Kd-Trees_and_More_Speed.shtml]
bool Triangle::Intersect( const Ray& _ray, Intersection& o_intersection ) const
{
	/*      v0
		/\
	 b /   \c
	v1/_____\ v2
		a
	*/
	Vector b = m_vertex[1] - m_vertex[0];
	Vector c = m_vertex[2] - m_vertex[0];
	Vector normal = b.Cross (c);
	//triangle is a line
	if( RealCompare( normal.Dot(normal), 0.0f, 0.0000000001 ) )
		return false;
	Normalise(normal);

	//ray-plane intersection
	float rayParameter = normal.Dot ( m_vertex[0] - _ray.Origin () ) / normal.Dot ( _ray.Direction () );
	//no intersection on the plane
	if ( rayParameter < 0.0f )
	{
		return false;
	}

	//if on the plane
	//solve the problem on 2d
	//get dominant axis of normal
    uint8_t axis = normal.DominantAxis();
	// p = p1*v1 + p2*v2 + p3*v3
	// p1+ p2+ p3 =1
	// p2 (  v2 - v1 ) + p3 (  v3 - v1 ) = intersection - v1
	Vector intersectionPos = _ray.Origin () + rayParameter * _ray.Direction ();
	Vector diff = intersectionPos - m_vertex[0];
	float bU, bV, cU, cV, diffU, diffV;
	uint8_t axisU = ( axis + 1 )%3;
	uint8_t axisV = ( axis + 2 )%3;
	diffU = diff[axisU];
	diffV = diff[axisV];
	bU = b[axisU];
	bV = b[axisV];
	cU = c[axisU];
	cV = c[axisV];
	float tmp =  bU * cV - bV * cU ;
	float p2 = (  cV * diffU - cU * diffV ) / tmp;
	if ( p2<0.0 )
	{
		return false;
	}
	float p3 = (  bU * diffV - bV * diffU ) / tmp;
	if (  p3<0.0 )
	{
		return false;
	}
	if (  p2+ p3> 1.0 )
	{
		return false;
	}
	float p1 = 1.0 - p2 - p3;
	Vector averageNormal = p1 * m_normal[0] + p2 * m_normal[1] + p3 * m_normal[2];
	Vector2D averageTexCoord = p1 * m_texture[0] + p2 * m_texture[1] + p3 * m_texture[2];
	Normalise(averageNormal);
	if( averageNormal.Dot( _ray.Direction() ) > 0 )
	{
		return false;
	}
	
	if( m_pMaterial->kf() > 0 && _ray.Direction().Dot( averageNormal ) > 0 )
	{
		//when calculating refraction for the ray inside object
		o_intersection = Intersection ( intersectionPos, averageNormal, averageTexCoord, rayParameter, g_air );
	}
	else if( m_pMaterial->kf()==0 && _ray.Direction().Dot(averageNormal ) > 0)
	{
		printf("back face\n");
		o_intersection = Intersection ( intersectionPos, averageNormal, averageTexCoord, rayParameter, m_pMaterial );
	}
	else
		o_intersection = Intersection ( intersectionPos, averageNormal, averageTexCoord, rayParameter, m_pMaterial );
	return true;
}