示例#1
0
bool Metaball::intersectLocal(const ray& r, isect& i) const
{
	bool inside = false;
	if (calvalue(r.getPosition(), ball1pos, ball2pos)>threshold)inside = true;

	//determine possible intersect range
	double t11=0, t12=0, t21=0, t22=0;
	double tmin, tmax;
	bool i1, i2;
	i1 = intersectCircle(r, t11, t12, ball1pos);
	i2 = intersectCircle(r, t21, t22, ball2pos);
	if (!i1 && !i2) return false;
	else if (!i1 && i2)
	{
		tmin = t21;
		tmax = t22;
	}
	else if (i1 && !i2)
	{
		tmin = t11;
		tmax = t12;
	}
	else
	{
		tmin = min(t11, t21);
		tmax = max(t12, t22);
	}

	for (double t = tmin; t < tmax; t += 0.001)
	{
		vec3f point = r.getPosition() + t * r.getDirection();
		double value = calvalue(point, ball1pos, ball2pos);

		if ((!inside && value > threshold) || (inside && value < threshold))
		{
			// prevent fake intersect
			if (inside && t < 0.01)return false;

			vec3f normal;
			normal += 2 * (point - ball1pos) / ((point - ball1pos).length()*(point - ball1pos).length());
			normal += 2 * (point - ball2pos) / ((point - ball2pos).length()*(point - ball2pos).length());
			normal = normal.normalize();
			i.t = t;
			i.N = normal;
			i.obj = this;
			return true;
		}
	}
	return false;
}
示例#2
0
// Intersect ray r with the triangle abc.  If it hits returns true,
// and puts the t parameter, barycentric coordinates, normal, object id,
// and object material in the isect object
bool TrimeshFace::intersectLocal( const ray& r, isect& i ) const
{
  const Vec3d& a = parent->vertices[ids[0]];
  const Vec3d& b = parent->vertices[ids[1]];
  const Vec3d& c = parent->vertices[ids[2]];

  // tangent vectors
  Vec3d t1 = b - a;
  Vec3d t2 = c - a;
  
  Vec3d n = crossProd(t1,t2);

  double D = -n*a;

  // if the surface is parallel to the ray there is no intersection
  if(r.getDirection()*n == 0)
  {
    return false;
  }  

  double t = -(n*r.getPosition() + D)/(n*r.getDirection() );
  if (t <= RAY_EPSILON)
    return false;

  // point of intersection with the same plane (doesn't mean intersection with triangle) p(t)=p+t*d
  Vec3d p = r.at(t);

  // triangle area
  double A = n.length()/2.0;

  // barycentric coords
  double wa = crossProd(c-b, p-b).length() / (2.0*A);
  double wb = crossProd(a-c, p-c).length() / (2.0*A);
  double wc = crossProd(b-a, p-a).length() / (2.0*A);

  if((wa >= 0.0) && (wb >= 0.0) && (wc >= 0.0) && (wa+wb+wc-1.0 <= 0.00001)) {
    i.setT(t);
    i.setBary(wa, wb, wc);
    if (parent->normals.size() == 0) {
      i.setN(n);
    } else {
      Vec3d inter_n = wa*parent->normals[ids[0]] + wb*parent->normals[ids[1]]
                    + wc*parent->normals[ids[2]];
      inter_n.normalize();
      i.setN(inter_n);
    }
    i.setObject(this);
    if (parent->materials.size() == 0) {
      i.setMaterial(this->getMaterial() );
    } else {
      Material inter_m = wa*(*parent->materials[ids[0]]);
      inter_m += wb*(*parent->materials[ids[1]]);
      inter_m += wc*(*parent->materials[ids[2]]);
      i.setMaterial(inter_m);
    }
    return true;
  }

  return false;
}
示例#3
0
文件: Cone.cpp 项目: JeffOwOSun/Trace
bool Cone::intersectBody( const ray& r, isect& i ) const
{
	vec3f d = r.getDirection();
	vec3f p = r.getPosition();

	double a = (d[0]*d[0]) + (d[1]*d[1]) - (C*d[2]*d[2]);
	double b = 2.0 * (d[0]*p[0] + d[1]*p[1] - C*d[2]*p[2]) - B*d[2];
	double c = (p[0]*p[0]) + (p[1]*p[1]) - A - (B*p[2]) - (C*p[2]*p[2]);

	double disc = b*b - 4.0*a*c;

	if( disc <= 0.0 ) {
		return false;
	}

	disc = sqrt( disc );

	double t1 = (-b - disc) / (2.0 * a);
	double t2 = (-b + disc) / (2.0 * a);

	if( t2 < RAY_EPSILON ) {
		return false;
	}

	if( t1 > RAY_EPSILON ) {
		// Two intersections.
		vec3f P = r.at( t1 );
		double z = P[2];
		if( z >= 0.0 && z <= height ) {
			// It's okay.
			i.t = t1;
			double p3 = -C*P[2] + (b_radius - t_radius)*b_radius / height;
			i.N = vec3f(P[0], P[1], p3).normalize();
#ifdef _DEBUG
			printf("two intersections!\n");
#endif
			return true;
		}
	}

	vec3f P = r.at( t2 );
	double z = P[2];
	if( z >= 0.0 && z <= height ) {
		i.t = t2;
		double p3 = -C*P[2] + (b_radius - t_radius)*b_radius / height;
		i.N = vec3f(P[0], P[1], p3).normalize();
		// In case we are _inside_ the _uncapped_ cone, we need to flip the normal.
		// Essentially, the cone in this case is a double-sided surface
		// and has _2_ normals
	
		if( !capped && (i.N).dot( r.getDirection() ) > 0 )
				i.N = -i.N;
#ifdef _DEBUG
		printf("one intersection!\n");
#endif
        return true;
	}

	return false;
}
示例#4
0
bool intersectCircle(const ray& r0, double& tnear, double& tfar, const vec3f& center)
{
	ray r(r0.getPosition() - center, r0.getDirection());

	vec3f v = -r.getPosition();
	double b = v.dot(r.getDirection());
	double discriminant = b*b - v.dot(v) + 1;

	if (discriminant < 0.0) {
		return false;
	}

	discriminant = sqrt(discriminant);
	double t2 = b + discriminant;

	if (t2 <= RAY_EPSILON) {
		return false;
	}



	double t1 = b - discriminant;

	if (t1 > RAY_EPSILON) {
		tnear = t1;
		tfar = t2;
	}
	else {
		tnear = 0;
		tfar = t2;
	}

	return true;
}
示例#5
0
bool Sphere::intersectLocal( const ray& r, isect& i ) const
{
	Vec3d v = -r.getPosition();
	double b = v * r.getDirection();
	double discriminant = b*b - v*v + 1;

	if( discriminant < 0.0 ) {
		return false;
	}

	discriminant = sqrt( discriminant );
	double t2 = b + discriminant;

	if( t2 <= RAY_EPSILON ) {
		return false;
	}

	i.obj = this;

	double t1 = b - discriminant;

	if( t1 > RAY_EPSILON ) {
		i.t = t1;
		i.N = r.at( t1 );
		i.N.normalize();
	} else {
		i.t = t2;
		i.N = r.at( t2 );
		i.N.normalize();
	}

	return true;
}
示例#6
0
bool Square::intersectLocal( const ray& r, isect& i ) const
{
	vec3f p = r.getPosition();
	vec3f d = r.getDirection();

	if( d[2] == 0.0 ) {
		return false;
	}

	double t = -p[2]/d[2];

	if( t <= RAY_EPSILON ) {
		return false;
	}

	vec3f P = r.at( t );

	if( P[0] < -0.5 || P[0] > 0.5 ) {	
		return false;
	}

	if( P[1] < -0.5 || P[1] > 0.5 ) {	
		return false;
	}

	i.obj = this;
	i.t = t;
	if( d[2] > 0.0 ) {
		i.N = vec3f( 0.0, 0.0, -1.0 );
	} else {
		i.N = vec3f( 0.0, 0.0, 1.0 );
	}

	return true;
}
示例#7
0
// Apply the phong model to this point on the surface of the object, returning
// the color of that point. Uses shaddowAttenuation which sends a shadow ray
// to check if there is an intersection that blocks the light sources.
Vec3d Material::shade( Scene *scene, const ray& r, const isect& i ) const
{
  Vec3d retVal = ke(i) + prod(ka(i), scene->ambient());
  
  // Applies calculations for each light source
  for (vector<Light*>::const_iterator litr = scene->beginLights(); 
       litr != scene->endLights(); ++litr) {
    Vec3d point = r.getPosition() + r.getDirection() * i.t;
    Light* pLight = *litr;
  
    Vec3d reflectionAngle = 2 * (i.N * pLight->getDirection(point)) * i.N - pLight->getDirection(point);

    Vec3d diffIntensity = kd(i) * (max(0, i.N * pLight->getDirection(point)));

    Vec3d viewerAngle = scene->getCamera().getEye() - point;
    viewerAngle.normalize();
    Vec3d specIntensity = ks(i) * pow(max(0, viewerAngle * reflectionAngle), shininess(i));

    Vec3d lcolor = pLight->getColor(point);

    Vec3d totalColor = prod(diffIntensity + specIntensity, lcolor);
    totalColor = totalColor * pLight->distanceAttenuation(point);
    totalColor = prod(totalColor, pLight->shadowAttenuation(point));

    retVal = retVal + totalColor;	
  }
  return retVal;
}
bool Cylinder::intersectCaps( const ray& r, isect& i ) const
{
	if( !capped ) {
		return false;
	}

	double pz = r.getPosition()[2];
	double dz = r.getDirection()[2];

	if( 0.0 == dz ) {
		return false;
	}

	double t1;
	double t2;

	if( dz > 0.0 ) {
		t1 = (-pz)/dz;
		t2 = (1.0-pz)/dz;
	} else {
		t1 = (1.0-pz)/dz;
		t2 = (-pz)/dz;
	}

	if( t2 < RAY_EPSILON ) {
		return false;
	}

	if( t1 >= RAY_EPSILON ) {
		vec3f p( r.at( t1 ) );
		if( (p[0]*p[0] + p[1]*p[1]) <= 1.0 ) {
			i.t = t1;
			if( dz > 0.0 ) {
				// Intersection with cap at z = 0.
				i.N = vec3f( 0.0, 0.0, -1.0 );
			} else {
				i.N = vec3f( 0.0, 0.0, 1.0 );
			}
			return true;
		}
	}

	vec3f p( r.at( t2 ) );
	if( (p[0]*p[0] + p[1]*p[1]) <= 1.0 ) {
		i.t = t2;
		if( dz > 0.0 ) {
			// Intersection with cap at z = 1.
			i.N = vec3f( 0.0, 0.0, 1.0 );
		} else {
			i.N = vec3f( 0.0, 0.0, -1.0 );
		}
		return true;
	}

	return false;
}
示例#9
0
文件: Cone.cpp 项目: logchan/COMP4411
bool Cone::intersectBody( const ray& r, isect& i ) const
{
	vec3f d = r.getDirection();
	vec3f p = r.getPosition();

	double a = (d[0]*d[0]) + (d[1]*d[1]) - (C*d[2]*d[2]);
	double b = 2.0 * (d[0]*p[0] + d[1]*p[1] - C*d[2]*p[2]) - B*d[2];
	double c = (p[0]*p[0]) + (p[1]*p[1]) - A - (B*p[2]) - (C*p[2]*p[2]);

	double disc = b*b - 4.0*a*c;

	if( disc <= 0.0 ) {
		return false;
	}

	disc = sqrt( disc );

	double t1 = (-b - disc) / (2.0 * a);
	double t2 = (-b + disc) / (2.0 * a);

	if( t2 < RAY_EPSILON ) {
		return false;
	}

	if( t1 > RAY_EPSILON ) {
		// Two intersections.
		vec3f P = r.at( t1 );
		double z = P[2];
		if( z >= 0.0 && z <= height ) {
			double n3 = -C*P[2] + (b_radius - t_radius)*b_radius / height;
			i.t = t1;
            i.N = vec3f( P[0], P[1], n3).normalize();
				
			if (!capped && (i.N).dot(r.getDirection()) > 0)
				i.N = -i.N;

			return true;
		}
	}

	vec3f P = r.at( t2 );
	double z = P[2];
	if( z >= 0.0 && z <= height ) {
		double n3 = -C*P[2] + (b_radius - t_radius)*b_radius / height;
		i.t = t2;
        i.N = vec3f( P[0], P[1], n3).normalize();
	
		if( !capped && (i.N).dot( r.getDirection() ) > 0 )
				i.N = -i.N;

        return true;
	}

	return false;
}
示例#10
0
文件: scene.cpp 项目: caomw/RayTracer
// if the ray hits the box, put the "t" value of the intersection
// closest to the origin in tMin and the "t" value of the far intersection
// in tMax and return true, else return false.
// Using Kay/Kajiya algorithm.
bool BoundingBox::intersect(const ray& r, double& tMin, double& tMax) const
{
	vec3f R0 = r.getPosition();
	vec3f Rd = r.getDirection();

	tMin = -1.0e308; // 1.0e308 is close to infinity... close enough for us!
	tMax = 1.0e308;
	double ttemp;
	
	for (int currentaxis = 0; currentaxis < 3; currentaxis++)
	{
		double vd = Rd[currentaxis];
		
		// if the ray is parallel to the face's plane (=0.0)
		if( vd > -RAY_EPSILON && vd < RAY_EPSILON ) {
			if(R0[currentaxis] <= min[currentaxis] - RAY_EPSILON || R0[currentaxis] >= max[currentaxis] + RAY_EPSILON) {
				return false;
			}
			else {
				continue;
			}
		}

		double v1 = min[currentaxis] - R0[currentaxis];
		double v2 = max[currentaxis] - R0[currentaxis];

		// two slab intersections
		double t1 = v1/vd;
		double t2 = v2/vd;
		
		if ( t1 > t2 ) { // swap t1 & t2
			ttemp = t1;
			t1 = t2;
			t2 = ttemp;
		}

		if (t1 > tMin)
			tMin = t1;
		if (t2 < tMax)
			tMax = t2;

		if (tMin > tMax) // box is missed
			return false;
		if (tMax < -RAY_EPSILON) // box is behind ray
			return false;
	}
	return true; // it made it past all 3 axes.
}
示例#11
0
文件: Box.cpp 项目: caomw/RayTracer
bool Box::intersectLocal( const ray& r, isect& i ) const
{
	BoundingBox bounds = ComputeLocalBoundingBox();
	vec3f p = r.getPosition();
	vec3f d = r.getDirection();
	//find tmin and tmax
	vec3f tmin;
	vec3f tmax;
	vec3f nmin(0, 0, 0);
	vec3f nmax(0, 0, 0);
	double min;
	double max;
	for(int j=0; j<3; j++) {
		if(d[j]>=0) {
			tmin[j] = (bounds.min[j] - p[j]) / d[j];
			tmax[j] = (bounds.max[j] - p[j]) / d[j];
			nmin[j] = -1;	
			nmax[j] = 1;
		} else {
			tmin[j] = (bounds.max[j] - p[j]) / d[j];
			tmax[j] = (bounds.min[j] - p[j]) / d[j];
			nmin[j] = 1;
			nmax[j] = -1;
		}
	}

	//min of tmax, max of tmin
	max = std::min( std::min(tmax[0], tmax[1]), tmax[2]);
	min = std::max( std::max(tmin[0], tmin[1]), tmin[2]);
	if(min > max || max < RAY_EPSILON) return false;
	i.obj = this;
	vec3f N(0, 0, 0);
	if(min >= RAY_EPSILON) {
		i.t = min;
		for(int i=0; i<3; i++) {
			if(tmin[i] == min) { N[i] = nmin[i]; break; }
		}
	} else {
		i.t = max;
		for(int i=0; i<3; i++) {
			if(tmax[i] == max) { N[i] = nmax[i]; break; }
		}
	}
	i.N = N;
	return true;
}
示例#12
0
bool Geometry::intersect(const ray&r, isect&i) const {
	double tmin, tmax;
	if (hasBoundingBoxCapability() && !(bounds.intersect(r, tmin, tmax))) return false;
	// Transform the ray into the object's local coordinate space
	Vec3d pos = transform->globalToLocalCoords(r.getPosition());
	Vec3d dir = transform->globalToLocalCoords(r.getPosition() + r.getDirection()) - pos;
	double length = dir.length();
	dir /= length;

	ray localRay( pos, dir, r.type() );

	if (intersectLocal(localRay, i)) {
		// Transform the intersection point & normal returned back into global space.
		i.N = transform->localToGlobalCoordsNormal(i.N);
		i.t /= length;
		return true;
	} else return false;
}
示例#13
0
文件: scene.cpp 项目: caomw/RayTracer
bool Geometry::intersect(const ray&r, isect&i) const
{
    // Transform the ray into the object's local coordinate space
    vec3f pos = transform->globalToLocalCoords(r.getPosition());
    vec3f dir = transform->globalToLocalCoords(r.getPosition() + r.getDirection()) - pos;
    double length = dir.length();
    dir /= length;

    ray localRay( pos, dir );

    if (intersectLocal(localRay, i)) {
        // Transform the intersection point & normal returned back into global space.
		i.N = transform->localToGlobalCoordsNormal(i.N);
		i.t /= length;
		return true;
    } else {
        return false;
    }
}
示例#14
0
//Test
// now the object is in the local coordinate rather than the global
bool Square::intersectLocal( const ray& r, isect& i ) const
{
	// get the parameters of the ray 
	Vec3d p = r.getPosition();
	Vec3d d = r.getDirection();

	// if the ray is perpendicular to the z-axis
	if( d[2] == 0.0 ) {
		return false;
	}

	// calculate the value of t
	double t = -p[2]/d[2];

	// if the intersection is too close to the source
	// then we don't count that as a intersection
	if( t <= RAY_EPSILON ) {
		return false;
	}

	
	Vec3d P = r.at( t );

	if( P[0] < -0.5 || P[0] > 0.5 ) {	
		return false;
	}

	if( P[1] < -0.5 || P[1] > 0.5 ) {	
		return false;
	}

	i.obj = this;
	i.t = t;
	if( d[2] > 0.0 ) {
		i.N = Vec3d( 0.0, 0.0, -1.0 );
	} else {
		i.N = Vec3d( 0.0, 0.0, 1.0 );
	}

    i.setUVCoordinates( Vec2d(P[0] + 0.5, P[1] + 0.5) );
	return true;
}
示例#15
0
vec3f PointLight::_shadowAttenuation(const vec3f& P, const ray& r) const
{
	double distance = (position - P).length();
	vec3f d = r.getDirection();
	vec3f result = getColor(P);
	vec3f curP = r.getPosition();
	isect isecP;
	ray newr(curP, d);
	while (scene->intersect(newr, isecP))
	{
		//prevent going beyond this light
		if ((distance -= isecP.t) < RAY_EPSILON) return result;
		//if not transparent return black
		if (isecP.getMaterial().kt.iszero()) return vec3f(0, 0, 0);
		//use current intersection point as new light source
		curP = r.at(isecP.t);
		newr = ray(curP, d);
		result = prod(result, isecP.getMaterial().kt);
	}
	return result;
}
示例#16
0
//Test
bool Square::intersectLocal(ray& r, isect& i) const
{
	Vec3d p = r.getPosition();
	Vec3d d = r.getDirection();

	if( d[2] == 0.0 ) {
		return false;
	}

	double t = -p[2]/d[2];

	if( t <= RAY_EPSILON ) {
		return false;
	}

	Vec3d P = r.at( t );

	if( P[0] < -0.5 || P[0] > 0.5 ) {	
		return false;
	}

	if( P[1] < -0.5 || P[1] > 0.5 ) {	
		return false;
	}

	i.obj = this;
	i.setMaterial(this->getMaterial());
	i.t = t;
	if( d[2] > 0.0 ) {
		i.N = Vec3d( 0.0, 0.0, -1.0 );
	} else {
		i.N = Vec3d( 0.0, 0.0, 1.0 );
	}

    i.setUVCoordinates( Vec2d(P[0] + 0.5, P[1] + 0.5) );
	return true;
}
示例#17
0
bool Sphere::intersectLocal( const ray& r, isect& i ) const
{
    // YOUR CODE HERE:
    // Add sphere intersection code here.
    // it currently ignores all spheres and just return false.

	Vec3d p = r.getPosition();
	Vec3d d = r.getDirection();

	// a unit sphere
	double a = d*d;
	double b = 2.0*(p*d);
	double c = p*p - 1.0;

	// d cannot be zero vector actually
	//if( 0.0 == a ) {
	//	// This implies that x1 = 0.0 and y1 = 0.0, which further
	//	// implies that the ray is aligned with the body of the cylinder,
	//	// so no intersection.
	//	return false;
	//}

	// early failure methods:
	//	if the ray and the sphere intersect
	//	then the angle btw rouge and d are \geq 0
	Vec3d rouge = Vec3d(0, 0, 0) - p ;
	rouge.normalize();
	double cos_isect = rouge * d ;
	if ( cos_isect < 0 )
		return false;
	//	it seems that the radius of sphere is 1.0
	//	then we can do the following, calculate the tangent angle
	//	and the compare it with our ray angle towards center of the sphere - origin
	double cos_tan = sqrt(1 - 1 / rouge.length());
	if ( cos_isect < cos_tan )
		return false;


	double discriminant = b*b - 4.0*a*c;

	if( discriminant < 0.0 ) {
		return false;
	}
	
	discriminant = sqrt( discriminant );

	double t2 = (-b + discriminant) / (2.0 * a);

	if( t2 <= RAY_EPSILON ) {
		return false;
	}

	double t1 = (-b - discriminant) / (2.0 * a);

	i.obj = this;
	if( t1 > RAY_EPSILON ) {
		// Two intersections. Pick smaller one
		Vec3d P = r.at( t1 );
		double z = P[2];
		if( z >= -1.0 && z <= 1.0 ) {
			// Just check
			i.t = t1;
			i.N = Vec3d( P[0], P[1], P[2]);
			return true;
		}
	}


	return false;
  
}
示例#18
0
bool Cone::intersectLocal(ray& r, isect& i) const
{
	bool ret = false;
	const int x = 0, y = 1, z = 2;	// For the dumb array indexes for the vectors

	Vec3d normal;
	
	Vec3d R0 = r.getPosition();
	Vec3d Rd = r.getDirection();
	double pz = R0[2];
	double dz = Rd[2];
	
	double a = Rd[x]*Rd[x] + Rd[y]*Rd[y] - beta_squared * Rd[z]*Rd[z];

	if( a == 0.0) return false;		// We're in the x-y plane, no intersection

	double b = 2 * (R0[x]*Rd[x] + R0[y]*Rd[y] - beta_squared * ((R0[z] + gamma) * Rd[z]));
	double c = -beta_squared*(gamma + R0[z])*(gamma + R0[z]) + R0[x] * R0[x] + R0[y] * R0[y];

	double discriminant = b * b - 4 * a * c;
	
	double farRoot, nearRoot, theRoot = RAY_EPSILON;
	bool farGood, nearGood;
	
	if(discriminant <= 0) return false;		// No intersection

	discriminant = sqrt(discriminant);

	// We have two roots, so calculate them
	nearRoot = (-b + discriminant) / ( 2 * a );
	farRoot = (-b - discriminant) / ( 2 * a );
	
	// This is confusing, but it figures out which
	// root is closer and puts into theRoot
	nearGood = isGoodRoot(r.at(nearRoot));
	if(nearGood && (nearRoot > theRoot))
	{
		theRoot = nearRoot;
		normal = Vec3d((r.at(theRoot))[x], (r.at(theRoot))[y], -2.0 * beta_squared * (r.at(theRoot)[z] + gamma));
	}
	farGood = isGoodRoot(r.at(farRoot));
	if(farGood && ( (nearGood && farRoot < theRoot) || farRoot > RAY_EPSILON) ) 
	{
		theRoot = farRoot;
		normal = Vec3d((r.at(theRoot))[x], (r.at(theRoot))[y], -2.0 * beta_squared * (r.at(theRoot)[z] + gamma));
	}

	// In case we are _inside_ the _uncapped_ cone, we need to flip the normal.
	// Essentially, the cone in this case is a double-sided surface
	// and has _2_ normals
	if( !capped && (normal * r.getDirection()) > 0 )
		normal = -normal;

	// These are to help with finding caps
	double t1 = (-pz)/dz;
	double t2 = (height-pz)/dz;
	
	Vec3d p( r.at( t1 ) );
	
	if(capped) {
		if( p[0]*p[0] + p[1]*p[1] <=  b_radius*b_radius)
		{
			if(t1 < theRoot && t1 > RAY_EPSILON)
			{
				theRoot = t1;
				if( dz > 0.0 ) {
					// Intersection with cap at z = 0.
					normal = Vec3d( 0.0, 0.0, -1.0 );
				} else {
					normal = Vec3d( 0.0, 0.0, 1.0 );
				}
			}
		}
		Vec3d q( r.at( t2 ) );
		if( q[0]*q[0] + q[1]*q[1] <=  t_radius*t_radius)
		{
			if(t2 < theRoot && t2 > RAY_EPSILON)
			{
				theRoot = t2;
				if( dz > 0.0 ) {
					// Intersection with interior of cap at z = 1.
					normal = Vec3d( 0.0, 0.0, 1.0 );
				} else {
					normal = Vec3d( 0.0, 0.0, -1.0 );
				}
			}
		}
	}
	
	if(theRoot <= RAY_EPSILON) return false;
	
	i.setT(theRoot);
	normal.normalize();
	i.setN(normal);
	i.obj = this;
	i.setMaterial(this->getMaterial());
	return true;
	
	return ret;
}
bool Cylinder::intersectBody( const ray& r, isect& i ) const
{
	double x0 = r.getPosition()[0];
	double y0 = r.getPosition()[1];
	double x1 = r.getDirection()[0];
	double y1 = r.getDirection()[1];

	double a = x1*x1+y1*y1;
	double b = 2.0*(x0*x1 + y0*y1);
	double c = x0*x0 + y0*y0 - 1.0;

	if( 0.0 == a ) {
		// This implies that x1 = 0.0 and y1 = 0.0, which further
		// implies that the ray is aligned with the body of the cylinder,
		// so no intersection.
		return false;
	}

	double discriminant = b*b - 4.0*a*c;

	if( discriminant < 0.0 ) {
		return false;
	}
	
	discriminant = sqrt( discriminant );

	double t2 = (-b + discriminant) / (2.0 * a);

	if( t2 <= RAY_EPSILON ) {
		return false;
	}

	double t1 = (-b - discriminant) / (2.0 * a);

	if( t1 > RAY_EPSILON ) {
		// Two intersections.
		vec3f P = r.at( t1 );
		double z = P[2];
		if( z >= 0.0 && z <= 1.0 ) {
			// It's okay.
			i.t = t1;
			i.N = vec3f( P[0], P[1], 0.0 ).normalize();
			return true;
		}
	}

	vec3f P = r.at( t2 );
	double z = P[2];
	if( z >= 0.0 && z <= 1.0 ) {
		i.t = t2;

		vec3f normal( P[0], P[1], 0.0 );
		// In case we are _inside_ the _uncapped_ cone, we need to flip the normal.
		// Essentially, the cone in this case is a double-sided surface
		// and has _2_ normals
		if( !capped && normal.dot( r.getDirection() ) > 0 )
			normal = -normal;

		i.N = normal.normalize();
		return true;
	}

	return false;
}
示例#20
0
bool Box::intersectLocal( const ray& r, isect& i ) const
{

        Vec3d p = r.getPosition();
        Vec3d d = r.getDirection();

        int it;
        double x, y, t, bestT; 
        int mod0, mod1, mod2, bestIndex;

        bestT = HUGE_DOUBLE;
        bestIndex = -1;

        for(it=0; it<6; it++){ 
                mod0 = it%3;

                if(d[mod0] == 0){
                        continue;
                }
                
                t = ((it/3) - 0.5 - p[mod0]) / d[mod0];                 

                if(t < RAY_EPSILON || t > bestT){
                        continue;
                }

                mod1 = (it+1)%3;
                mod2 = (it+2)%3;
                x = p[mod1]+t*d[mod1];
                y = p[mod2]+t*d[mod2];
                
                if(     x<=0.5 && x>=-0.5 &&
                        y<=0.5 && y>=-0.5)
                {
                        if(bestT > t){
                                bestT = t;
                                bestIndex = it;
                        }
                }                       
                
        }

        if(bestIndex < 0) return false;
        
        i.setT(bestT);
        i.setObject(this);

		Vec3d intersect_point = r.at(i.t);

		int i1 = (bestIndex + 1) % 3;
		int i2 = (bestIndex + 2) % 3;

        if(bestIndex < 3)
		{
                i.setN(Vec3d(-double(bestIndex == 0), -double(bestIndex == 1), -double(bestIndex == 2)));
				i.setUVCoordinates( Vec2d(	0.5 - intersect_point[ min(i1, i2) ], 
											0.5 + intersect_point[ max(i1, i2) ] ) );
		}
        else
		{
                i.setN(Vec3d(double(bestIndex==3), double(bestIndex == 4), double(bestIndex == 5)));
				i.setUVCoordinates( Vec2d(	0.5 + intersect_point[ min(i1, i2) ],
											0.5 + intersect_point[ max(i1, i2) ] ) );

		}
        return true;

}
示例#21
0
	bool RayIntersectsAABB(const ray& intersectionRay, float* tEntry, float* tExit, const vector4& aabbMinExtents, const vector4& aabbMaxExtents)
	{
		// Test against front plane.
		const vector4& rayPosition = intersectionRay.getPosition();
		const vector4& rayDirection = intersectionRay.getDirection();

		bool tFound = false;
		float minimumTValue = FLT_MAX;
		float maximumTValue = 0.0f;

		// Containment test. Is the ray inside the aabb?
		if (rayPosition.extractX() >= aabbMinExtents.extractX() &&
			rayPosition.extractX() <= aabbMaxExtents.extractX() &&
			rayPosition.extractY() >= aabbMinExtents.extractY() &&
			rayPosition.extractY() <= aabbMaxExtents.extractY() &&
			rayPosition.extractZ() >= aabbMinExtents.extractZ() &&
			rayPosition.extractZ() <= aabbMaxExtents.extractZ())
		{
			minimumTValue = 0.0f;

			tFound = true;
		}

		// Intersect ray with the minimum x plane of the aabb.
		plane minXPlane(vector4(aabbMinExtents.extractX(), 0.0f, 0.0f, 1.0f), vector4(-1.0f, 0.0f, 0.0f, 0.0f));

		float minXPlaneIntersection;
		if (MathLib::intersectRayWithPlane(intersectionRay, minXPlane, &minXPlaneIntersection))
		{
			// Construct the point on the plane. Test if in bounds of the aabb.
			vector4 point;
			vector4_addScaledVector(rayPosition, rayDirection, minXPlaneIntersection, point);

			if (point.extractY() >= aabbMinExtents.extractY() &&
				point.extractY() <= aabbMaxExtents.extractY() &&
				point.extractZ() >= aabbMinExtents.extractZ() &&
				point.extractZ() <= aabbMaxExtents.extractZ())
			{
				if (minXPlaneIntersection >= 0.0f)
					tFound = true;

				if (minXPlaneIntersection < minimumTValue)
					minimumTValue = minXPlaneIntersection;

				if (minXPlaneIntersection > maximumTValue)
					maximumTValue = minXPlaneIntersection;
			}
		}

		// Intersect ray with the maximum x plane of the aabb.
		plane maxXPlane(vector4(aabbMaxExtents.extractX(), 0.0f, 0.0f, 1.0f), vector4(1.0f, 0.0f, 0.0f, 0.0f));

		float maxXPlaneIntersection;
		if (MathLib::intersectRayWithPlane(intersectionRay, maxXPlane, &maxXPlaneIntersection))
		{
			// Construct the point on the plane. Test if in bounds of the aabb.
			vector4 point;
			vector4_addScaledVector(rayPosition, rayDirection, maxXPlaneIntersection, point);

			if (point.extractY() >= aabbMinExtents.extractY() &&
				point.extractY() <= aabbMaxExtents.extractY() &&
				point.extractZ() >= aabbMinExtents.extractZ() &&
				point.extractZ() <= aabbMaxExtents.extractZ())
			{
				if (maxXPlaneIntersection >= 0.0f)
					tFound = true;

				if (maxXPlaneIntersection < minimumTValue)
					minimumTValue = maxXPlaneIntersection;

				if (maxXPlaneIntersection > maximumTValue)
					maximumTValue = maxXPlaneIntersection;
			}
		}

		// Intersect ray with the minimum y plane of the aabb.
		plane minYPlane(vector4(0.0f, aabbMinExtents.extractY(), 0.0f, 1.0f), vector4(0.0f, -1.0f, 0.0f, 0.0f));

		float minYPlaneIntersection;
		if (MathLib::intersectRayWithPlane(intersectionRay, minYPlane, &minYPlaneIntersection))
		{
			// Construct the point on the plane. Test if in bounds of the aabb.
			vector4 point;
			vector4_addScaledVector(rayPosition, rayDirection, minYPlaneIntersection, point);

			if (point.extractX() >= aabbMinExtents.extractX() &&
				point.extractX() <= aabbMaxExtents.extractX() &&
				point.extractZ() >= aabbMinExtents.extractZ() &&
				point.extractZ() <= aabbMaxExtents.extractZ())
			{
				if (minYPlaneIntersection >= 0.0f)
					tFound = true;

				if (minYPlaneIntersection < minimumTValue)
					minimumTValue = minYPlaneIntersection;

				if (minYPlaneIntersection > maximumTValue)
					maximumTValue = minYPlaneIntersection;
			}
		}

		// Intersect ray with the maximum y plane of the aabb.
		plane maxYPlane(vector4(0.0f, aabbMaxExtents.extractY(), 0.0f, 1.0f), vector4(0.0f, 1.0f, 0.0f, 0.0f));

		float maxYPlaneIntersection;
		if (MathLib::intersectRayWithPlane(intersectionRay, maxYPlane, &maxYPlaneIntersection))
		{
			// Construct the point on the plane. Test if in bounds of the aabb.
			vector4 point;
			vector4_addScaledVector(rayPosition, rayDirection, maxYPlaneIntersection, point);

			if (point.extractX() >= aabbMinExtents.extractX() &&
				point.extractX() <= aabbMaxExtents.extractX() &&
				point.extractZ() >= aabbMinExtents.extractZ() &&
				point.extractZ() <= aabbMaxExtents.extractZ())
			{
				if (maxYPlaneIntersection >= 0.0f)
					tFound = true;

				if (maxYPlaneIntersection < minimumTValue)
					minimumTValue = maxYPlaneIntersection;

				if (maxYPlaneIntersection > maximumTValue)
					maximumTValue = maxYPlaneIntersection;
			}
		}

		// Intersect ray with the minimum z plane of the aabb.
		plane minZPlane(vector4(0.0f, 0.0f, aabbMinExtents.extractZ(), 1.0f), vector4(0.0f, 0.0f, -1.0f, 0.0f));

		float minZPlaneIntersection;
		if (MathLib::intersectRayWithPlane(intersectionRay, minZPlane, &minZPlaneIntersection))
		{
			// Construct the point on the plane. Test if in bounds of the aabb.
			vector4 point;
			vector4_addScaledVector(rayPosition, rayDirection, minZPlaneIntersection, point);

			if (point.extractX() >= aabbMinExtents.extractX() &&
				point.extractX() <= aabbMaxExtents.extractX() &&
				point.extractY() >= aabbMinExtents.extractY() &&
				point.extractY() <= aabbMaxExtents.extractY())
			{
				if (minZPlaneIntersection >= 0.0f)
					tFound = true;

				if (minZPlaneIntersection < minimumTValue)
					minimumTValue = minZPlaneIntersection;

				if (minZPlaneIntersection > maximumTValue)
					maximumTValue = minZPlaneIntersection;
			}
		}

		// Intersect ray with the maximum z plane of the aabb.
		plane maxZPlane(vector4(0.0f, 0.0f, aabbMaxExtents.extractZ(), 1.0f), vector4(0.0f, 0.0f, 1.0f, 0.0f));

		float maxZPlaneIntersection;
		if (MathLib::intersectRayWithPlane(intersectionRay, maxZPlane, &maxZPlaneIntersection))
		{
			// Construct the point on the plane. Test if in bounds of the aabb.
			vector4 point;
			vector4_addScaledVector(rayPosition, rayDirection, maxZPlaneIntersection, point);

			if (point.extractX() >= aabbMinExtents.extractX() &&
				point.extractX() <= aabbMaxExtents.extractX() &&
				point.extractY() >= aabbMinExtents.extractY() &&
				point.extractY() <= aabbMaxExtents.extractY())
			{
				if (maxZPlaneIntersection >= 0.0f)
					tFound = true;

				if (maxZPlaneIntersection < minimumTValue)
					minimumTValue = maxZPlaneIntersection;

				if (maxZPlaneIntersection > maximumTValue)
					maximumTValue = maxZPlaneIntersection;
			}
		}

		if (tFound)
		{
			*tEntry = minimumTValue;
			*tExit = maximumTValue;
		}

		return tFound;
	}
示例#22
0
文件: Cone.cpp 项目: JeffOwOSun/Trace
bool Cone::intersectCaps( const ray& r, isect& i ) const
{
	if( !capped ) {
		return false;
	}

	double pz = r.getPosition()[2];
	double dz = r.getDirection()[2];

	if( 0.0 == dz ) {
		return false;
	}

	double t1;
	double t2;
	double r1;
	double r2;

	if( dz > 0.0 ) {
		t1 = (-pz)/dz;
		t2 = (height-pz)/dz;
		r1 = b_radius;
		r2 = t_radius;
	} else {
		t1 = (height-pz)/dz;
		t2 = (-pz)/dz;
		r1 = t_radius;
		r2 = b_radius;
	}

	if( t2 < RAY_EPSILON ) {
		return false;
	}

	if( t1 >= RAY_EPSILON ) {
		vec3f p( r.at( t1 ) );
		if( (p[0]*p[0] + p[1]*p[1]) <= r1 * r1 ) {
			i.t = t1;
			if( dz > 0.0 ) {
				// Intersection with cap at z = 0.
				i.N = vec3f( 0.0, 0.0, -1.0 );
			} else {
				i.N = vec3f( 0.0, 0.0, 1.0 );
			}
			return true;
		}
	}

	vec3f p( r.at( t2 ) );
	if( (p[0]*p[0] + p[1]*p[1]) <= r2 * r2 ) {
		i.t = t2;
		if( dz > 0.0 ) {
			// Intersection with interior of cap at z = 1.
			i.N = vec3f( 0.0, 0.0, 1.0 );
		} else {
			i.N = vec3f( 0.0, 0.0, -1.0 );
		}
		return true;
	}

	return false;
}
示例#23
0
bool Box::intersectLocal(const ray& r, isect& i) const
{
	// YOUR CODE HERE:
	// Add box intersection code here.
	// it currently ignores all boxes and just returns false.

	double iNear = -std::numeric_limits<double>::max();
	double iFar = std::numeric_limits<double>::max();

	vec3f rayDir = r.getDirection();
	vec3f rayPos = r.getPosition();

	// t1, t2 is used to compute the intersection distance of the planes
	double t1 = 0.0f, t2 = 0.0f;
	int intersect = -1;

	// for each pair of planes associated with X, Y and Z
	for (int i = 0; i < 3; i++)
	{
		if (rayDir[i] == 0)
		{
			if (rayDir[i] < -0.5 || rayDir[i] > 0.5)
				return false;
		}

		t1 = (-0.5 - rayPos[i]) / rayDir[i];
		t2 = (0.5 - rayPos[i]) / rayDir[i];

		// t1 intersection with near plane
		if (t1 > t2)
		{
			double temp = t2;
			t2 = t1;
			t1 = temp;
		}

		if (t1 > iNear){
			iNear = t1;
			intersect = i;
		}
		if (t2 < iFar)
			iFar = t2;
		if (iNear > iFar || iFar < 0)
			return false;
	}

	i.obj = this;
	i.t = iNear;

	if (intersect == 0)
	{
		if (rayDir[0] < 0.0)
			i.N = vec3f(1.0, 0.0, 0.0);
		else
			i.N = vec3f(-1.0, 0.0, 0.0);
	}
	else if (intersect == 1)
	{
		if (rayDir[1] < 0.0)
			i.N = vec3f(0.0, 1.0, 0.0);
		else
			i.N = vec3f(0.0, -1.0, 0.0);
	}
	else if (intersect == 2)
	{
		if (rayDir[2] < 0.0)
			i.N = vec3f(0.0, 0.0, 1.0);
		else
			i.N = vec3f(0.0, 0.0, -1.0);
	}


	return true;
}