Пример #1
0
// cast ray and return the color of the closest intersected surface point, 
// or the background color if there is no object intersection
Vector_3D<double> Render_World::
Cast_Ray(Ray& ray,const Ray& parent_ray)
{
 	const Object* obj = Closest_Intersection(ray);
	Vector_3D<double> intersection_point = ray.Point(ray.t_max);

	//if no object intersection, create dummy variables to satisfy Shader function reqs
	//and set color to background
	if (obj == 0) {
		Vector_3D<double> dummy_vec(0,0,0);
		Sphere* obj = new Sphere(dummy_vec, 1.0);
		Vector_3D<double> color = background_shader->Shade_Surface(ray, *obj, dummy_vec, dummy_vec); 
		delete obj;
		return color; 
	}
	
	// call corresponding shader with ray/object information
    Vector_3D<double> color = obj->material_shader->Shade_Surface(ray, *obj, intersection_point, obj->Normal(intersection_point));  

    return color;
}
Пример #2
0
double Sphere::RayIntersect(Ray &ray, IntersectData *intersectData)
{
	double A = 1.0; // normalized ray vector
	double B = 2.0 * (ray.Vector().x * (ray.Point().x - center.x) + ray.Vector().y * (ray.Point().y - center.y) + ray.Vector().z * (ray.Point().z - center.z));
	double C = pow(ray.Point().x - center.x, 2.0) + pow(ray.Point().y - center.y, 2.0) + pow(ray.Point().z - center.z, 2.0) - radius * radius;
	double Det = B * B - 4.0 * A * C;

	if (Det >= 0.0)
	{
		double t = (-B - sqrt(Det)) / 2;

		if (t > 0.0)
		{
			if (intersectData)
			{
				Point3D contact = (Vector3D)ray.Point() + ray.Vector() * t;
				Vector3D normal = (Vector3D)contact - center;
				normal = normal.Normalize();

				intersectData->contact = contact;
				intersectData->normal = normal;
				intersectData->color = color;
			}

			return t;
		}

		t = (-B + sqrt(Det)) / 2;

		if (t > 0.0)
		{
			if (intersectData)
			{
				Point3D contact = (Vector3D)ray.Point() + ray.Vector() * t;
				Vector3D normal = (Vector3D)contact - center;
				normal = normal.Normalize();

				intersectData->contact = contact;
				intersectData->normal = normal;
				intersectData->color = color;

				return t;
			}
		}
	}

	return INFINITY;
}
Пример #3
0
bool Sphere::Intersect( Ray const &ray, float *tHit, float *epsilon, DifferentialGeometry *geom ) const {
    Transform tf = Tform();
    Ray r = ray * Inverse( tf );

    float t;
    if( !Intersect( ray, &t ) )
        return false;

    // compute differential geometry
    Vec4 p = ray.Point( t );

    float x = p.X();
    float y = p.Y();
    float z = p.Z();

    if( x == 0.0f && z == 0.0f ) {
        // can't have both atan2 arguments be zero
        z = kEpsilon * m_radius;
    }
    float theta = atan2( p.X(), p.Z() );

    if( theta < 0.0f ) {
        // remap theta to [0, 2pi] to match sphere's definition
        theta += k2Pi;
    }

    float phi = Acos( Clamp( z / m_radius, -1.0f, 1.0f ) );

    // parameterize sphere hit
    float u = theta * kInv2Pi;
    float v = phi * kInvPi;

    float sTheta, cTheta;
    float sPhi, cPhi;
    SinCos( theta, &sTheta, &cTheta );
    SinCos( phi, &sPhi, &cPhi );

    Vec4 dpdu( k2Pi * z, 0.0f, -k2Pi * x, 0.0f );
    Vec4 dpdv( kPi * y * sTheta, -kPi * m_radius * sPhi, kPi * y * cTheta, 0.0f );
    Vec4 d2pdu2( -k2Pi * k2Pi * x, 0.0f, -k2Pi * k2Pi * z, 0.0f );
    Vec4 d2pduv( k2Pi * kPi * y * cTheta, 0.0f, -k2Pi * kPi * y * sTheta, 0.0f );
    Vec4 d2pdv2( -kPi * kPi * x, -kPi * kPi * y, -kPi * kPi * z, 0.0f );

    // change in normal is computed using Weingarten equations
    Scalar E = Dot( dpdu, dpdu );
    Scalar F = Dot( dpdu, dpdv );
    Scalar G = Dot( dpdv, dpdv );
    Vec4 N = Normalize( Cross(  dpdu, dpdv ) );
    Scalar e = Dot( N, d2pdu2 );
    Scalar f = Dot( N, d2pduv );
    Scalar g = Dot( N, d2pdv2 );

    Scalar h = 1.0f / ( E * G - F * F );
    Vec4 dndu = ( f * F - e * G ) * h * dpdu + ( e * F - f * E ) * h * dpdv;
    Vec4 dndv = ( g * F - f * G ) * h * dpdu + ( f * F - g * E ) * h * dpdv;

    *tHit = t;
    *epsilon = 5e-4f * t;

    // return world space differential geometry
    *geom = DifferentialGeometry( Handle(), p * tf, dpdu * tf, dpdv * tf, Normal( dndu ) * tf, Normal( dndv ) * tf, u, v );

    return true;
}