示例#1
0
void R3MeshSearchTree::
FindIntersection(const R3Ray& ray, R3MeshIntersection& closest,
  RNScalar min_t, RNScalar& max_t,
  int (*IsCompatible)(const R3Point&, const R3Vector&, R3Mesh *, R3MeshFace *, void *), void *compatible_data,
  R3MeshFace *face) const
{
  // Check compatibility
  if (IsCompatible) {
    if (!(*IsCompatible)(ray.Start(), ray.Vector(), mesh, face, compatible_data)) return;
  }

  // Check intersection with plane (this is redundant, but allows checking min_t and max_t)
  RNScalar plane_t;
  if (!R3Intersects(ray, mesh->FacePlane(face), NULL, &plane_t)) return;
  if (plane_t >= max_t) return;
  if (plane_t < min_t) return;

  // Check intersection with face
  R3MeshIntersection face_intersection;
  if (!mesh->Intersection(ray, face, &face_intersection)) return;
  if (face_intersection.t >= max_t) return;
  if (face_intersection.t < min_t) return;

  // Update closest intersection
  closest.type = R3_MESH_FACE_TYPE;
  closest.face = face;
  closest.point = face_intersection.point;
  closest.t = face_intersection.t;
  max_t = face_intersection.t;
}
示例#2
0
文件: R3Cont.C 项目: acplus/peptalk
RNBoolean R3Contains(const R3Ray& ray, const R3Box& box)
{
    // Return whether ray contains box
    if (!R3Contains(ray.Line(), box)) return FALSE;
    RNOctant octant = ray.Vector().Octant();
    if (!R3Contains(ray, box.Corner(~octant & 0x7))) return FALSE;
    return TRUE;
}
// compute intersection between a sphere and a ray
R3Intersection ComputeIntersection(R3Sphere *sphere, R3Ray &ray)
{
  R3Intersection i;
  bool in_front_of_center = false;
  bool internal = false;

  R3Vector l = sphere->Center() - ray.Start();
  double tca = l.Dot(ray.Vector());
  if (tca < 0) // case where ray originates within sphere and points away from its center
  {
    tca = -tca;
    in_front_of_center = true;
    internal = true;
  }
  double d2 = l.Dot(l) - tca * tca;
  double r2 = sphere->Radius() * sphere->Radius();
  if (d2 > r2) // case where ray misses sphere entirely
  {
    i.hit = false;
    return i;
  }
  double thc = sqrt(r2 - d2);
  double t;
  if (!in_front_of_center)
  {
    t = tca - thc;
    if (t < 0)
    {
      t = tca + thc;
      internal = true;
    }
  }
  else
  {
    t = thc - tca;
  }

  if (t < 0)
  {
    i.hit = false;
    return i;
  }

  R3Point p = ray.Point(t);
  R3Vector n = p - sphere->Center();
  n.Normalize();
  if (internal)
    n = -n;

  // populate intersection data
  i.hit = true;
  i.normal = n;
  i.position = p;
  i.t = t;

  return i;
}
示例#4
0
static void
DrawText(const R2Point& p, const char *s)
{
  // Draw text string s and position p
  R3Ray ray = viewer->WorldRay((int) p[0], (int) p[1]);
  R3Point position = ray.Point(2 * viewer->Camera().Near());
  glRasterPos3d(position[0], position[1], position[2]);
  while (*s) glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, *(s++));
}
示例#5
0
double R3Distance(const R3Point& point, const R3Ray& ray)
{
  // Check if start point is closest
  R3Vector v = point - ray.Start();
  double dir = v.Dot(ray.Vector());
  if (dir < 0) return v.Length();

  // Return distance from point to ray line
  return R3Distance(point, ray.Line());
}
示例#6
0
int IntersectPlane(R3Plane *p, R3Ray r, R3Point *position, R3Vector *normal, double *t) {
	double denom = r.Vector().Dot(p->Normal());
	if(denom == 0) {
		return 0;
	} else {
		*t = - (r.Start().Vector().Dot(p->Normal()) + p->D()) / denom;
		*position = r.Start() + *t * r.Vector();
		*normal = p->Normal();
		return 1;
	}
}
// compute the ray reflected from the incoming ray r at intersection i
R3Ray GetReflectedRay(R3Intersection i, R3Ray r)
{
  // add offset to point to ensure the same intersection is not found again due to floating point error
  R3Point offset = i.position + i.normal * EPSILON;
  R3Vector v = -r.Vector();
  return R3Ray(offset, 2 * v.Dot(i.normal) * i.normal - v);
}
示例#8
0
int IntersectMesh(R3Mesh *m, R3Ray r, R3Point *position, R3Vector *normal, double *t) {
	*t = DBL_MAX;
	for(int i=0; i < m->NFaces(); i++) {
		R3MeshFace *f = m->Face(i);
		if(f->vertices.size() != 3) continue;
		
		R3Vector trianglenormal = (f->vertices[1]->position - f->vertices[0]->position);
		trianglenormal.Cross(f->vertices[2]->position - f->vertices[0]->position);
		trianglenormal.Normalize();

		R3Plane triangleplane(f->vertices[0]->position, trianglenormal);

		R3Point intersectionpoint;
		double t_intersection;
		if(IntersectPlane(&triangleplane, r, &intersectionpoint, &trianglenormal, &t_intersection) !=0 ) {
			// check inside triangle
			int withintriangle = 1;
			for(int j=0; j<3; j++) {
				R3Vector v1 = f->vertices[j%3]->position - r.Start();
				R3Vector v2 = f->vertices[(j+1)%3]->position - r.Start();
				R3Vector n1 = v2;
				n1.Cross(v1);
				n1.Normalize();
				R3Plane p(r.Start(), n1);
				if(R3SignedDistance(p, intersectionpoint) < 0) {
					withintriangle = 0;
					break;
				}
			}
			
			if(withintriangle == 1 && t_intersection > 0 && t_intersection < *t) {
				*t = t_intersection;
				*position = intersectionpoint;
				*normal = trianglenormal;
			}
		}

	}

	if(*t < DBL_MAX) {
		return 1;
	}
	else {
		return 0;
	}
}
示例#9
0
double R3SignedDistance(const R3Plane& plane, const R3Ray& ray)
{
  // Return signed distance from plane to ray
  double d1 = R3SignedDistance(plane, ray.Start());
  if (d1 > 0) {
    // Start point is above plane
    double dot = ray.Vector().Dot(plane.Normal());
    if (dot < 0) return 0.0;
    else return d1;
  }
  else if (d1 < 0) {
    // Start point is below plane
    double dot = ray.Vector().Dot(plane.Normal());
    if (dot > 0) return 0.0;
    else return d1;
  }
  else {
    // Start point is on plane
    return 0.0;
  }
}
示例#10
0
int IntersectSphere(R3Sphere *s, R3Ray r, R3Point *position, R3Vector *normal, double *t) {
	R3Vector l = s->Center() - r.Start();
	double tca = l.Dot(r.Vector());
	if(tca < 0) return 0;

	double d2 = l.Dot(l) - tca*tca;
	if(d2 > s->Radius() * s->Radius()) return 0;

	double thc = sqrt(s->Radius() * s->Radius() - d2);
	*t = thc > 0 ? tca - thc : tca + thc;
	if(*t < 0) {
		*t = thc > 0 ? tca + thc : tca - thc;
	}
	if(*t < 0) {
		return 0;
	}
	
	*position = r.Start() + *t * r.Vector();
	*normal = *position - s->Center();
	normal->Normalize();

	return 1;
}
示例#11
0
double R3Distance(const R3Ray& ray, const R3Segment& segment)
{
  // There's got to be a better way ???

  // Get vectors in more convenient form
  const R3Vector v1 = ray.Vector();
  const R3Vector v2 = segment.Vector();

  // Compute useful intermediate values
  const double v1v1 = 1.0;  // v1.Dot(v1);
  const double v2v2 = 1.0;  // v2.Dot(v2);
  double v1v2 = v1.Dot(v2);
  double denom = v1v2*v1v2 - v1v1*v2v2;

  // Check if ray and segment are parallel
  if (denom == 0) {
    // Not right ???
    // Look at directions of vectors, then check relative starts and stops
    return R3Distance(segment.Line(), ray.Line());
  }
  else {
    // Find closest points
    const R3Vector p1 = ray.Start().Vector();
    const R3Vector p2 = segment.Start().Vector();
    double p1v1 = v1.Dot(p1);
    double p2v2 = v2.Dot(p2);
    double p1v2 = v2.Dot(p1);
    double p2v1 = v1.Dot(p2);
    double ray_t = (v1v2*p2v2 + v2v2*p1v1 - v1v2*p1v2 - v2v2*p2v1) / denom;
    double segment_t = (v1v2*p1v1 + v1v1*p2v2 - v1v2*p2v1 - v1v1*p1v2) / denom;
    R3Point ray_point = (ray_t <= 0.0) ? ray.Start() : ray.Point(ray_t);
    R3Point segment_point = (segment_t <= 0.0) ? segment.Start() : 
      (segment_t >= segment.Length()) ? segment.End() : segment.Ray().Point(segment_t);
    double distance = R3Distance(ray_point, segment_point);
    return distance;
  }
}
示例#12
0
// compute ray refracted from incoming ray r using Snell's Law
// NOTE: I assume that refracting objects will always be non-intersecting and that all intersections passed into this function
// will be from empty space with an IOR of 1 to the interior of a shape
R3Ray GetRefractedRay(R3Intersection i, R3Ray r, double ior, R3Scene *scene)
{
  // this time push the point inside the object
  R3Point internal_offset = i.position - i.normal * EPSILON;

  // calculate the ray that will be cast through the object
  R3Vector v = -r.Vector();
  double cos_vn = v.Dot(i.normal);
  R3Vector internal_vec = i.normal * (cos_vn / ior - sqrt(1 - (1 - cos_vn * cos_vn) / (ior * ior))) - v / ior;
  R3Ray trans_ray(internal_offset, internal_vec);

  // cast this ray and determine it's exit point from the refracting object
  R3Intersection exit_i = ComputeIntersection(scene, scene->Root(), trans_ray, numeric_limits<double>::infinity());
  assert (exit_i.hit);

  // calculate the refracted exit ray and 
  R3Point external_offset = exit_i.position - exit_i.normal * EPSILON;
  v = -trans_ray.Vector();
  cos_vn = v.Dot(exit_i.normal);
  R3Vector external_vec = exit_i.normal * (cos_vn * ior - sqrt(1 - (1 - cos_vn * cos_vn) * (ior * ior))) - v * ior;
  return R3Ray(external_offset, external_vec);
}
示例#13
0
RNBoolean R3Parallel(const R3Ray& ray, const R3Plane& plane)
{
    // Return whether ray and plane are parallel
    return R3Perpendicular(ray.Vector(), plane.Normal());
}
示例#14
0
RNBoolean R3Perpendicular(const R3Ray& ray1, const R3Ray& ray2)
{
    // Return whether ray1 and ray2 are perpendicular
    return R3Perpendicular(ray1.Vector(), ray2.Vector());
}
示例#15
0
RNBoolean R3Perpendicular(const R3Ray& ray, const R3Span& span)
{
    // Return whether ray and span are perpendicular
    return R3Perpendicular(ray.Vector(), span.Vector());
}
示例#16
0
RNBoolean R3Perpendicular(const R3Vector& vector, const R3Ray& ray)
{
    // Return whether vector and ray are perpendicular
    return R3Perpendicular(vector, ray.Vector());
}
示例#17
0
RNBoolean R3Perpendicular(const R3Line& line, const R3Ray& ray)
{
    // Return whether line and ray are perpendicular
    return R3Perpendicular(line.Vector(), ray.Vector());
}
示例#18
0
// compute intersection between a triangle face and a ray
R3Intersection ComputeIntersection(R3MeshFace *tri, R3Ray &ray, double min_t)
{
  assert (tri->vertices.size() == 3);

  R3Intersection i;

  R3Point t1 = tri->vertices[0]->position;
  R3Point t2 = tri->vertices[1]->position;
  R3Point t3 = tri->vertices[2]->position;

  // intersect ray with triangle's plane
  R3Plane plane = tri->plane;
  double t = -(ray.Start().Vector().Dot(plane.Normal()) + plane.D()) 
    / (ray.Vector().Dot(plane.Normal()));

  // early return if not closer than minimum intersection for the mesh
  if (t > min_t || t < 0)
  {
    i.hit = false;
    return i;
  }


  // check if intersection is within triangle using barycentric coordinate method
  R3Point p = ray.Point(t);

  R3Vector v;

  v = t2 - t1;
  v.Cross(t3 - t1);
  double area = v.Length() / 2;

  v = t2 - t1;
  v.Cross(p - t1);
  if (v.Dot(plane.Normal()) < 0)
  {
    i.hit = false;
    return i;
  }
  double a = v.Length() / (2 * area);

  v = p - t1;
  v.Cross(t3 - t1);
  if (v.Dot(plane.Normal()) < 0)
  {
    i.hit = false;
    return i;
  }
  double b = v.Length() / (2 * area);

  if (a <= 1 && a >= 0 && b <= 1 && b >= 0 && a + b <= 1)
  {
    i.hit = true;
    if (ray.Vector().Dot(plane.Normal()) < 0)
    {
      i.normal = plane.Normal();
    }
    else
    {
      i.normal = -plane.Normal();
    }
    i.position = p;
    i.t = t;
    return i;
  } 
  else
  {
    i.hit = false;
    return i;
  }
}
示例#19
0
// return point of intersection between ray and plane
R3Point RayPlaneIntersection(R3Plane plane, R3Ray ray)
{
  double t = -(ray.Start().Vector().Dot(plane.Normal()) + plane.D()) 
    / (ray.Vector().Dot(plane.Normal()));
  return ray.Point(t);
}
示例#20
0
int IntersectCone(R3Cone *c, R3Ray r, R3Point *position, R3Vector *normal, double *t) {
	R3Vector v = r.Vector();
	R3Point s = r.Start();
	*t = DBL_MAX;

	double k = pow(c->Radius() / c->Height(), 2.0);
	double y_apex = c->Center()[1] + c->Height() / 2.0;
	// check cone side
	double eqa = v[0]*v[0] + v[2]*v[2] - k*v[1]*v[1];
	double eqb = 2.0*v[0]*(s[0] - c->Center()[0]) + 2.0*v[2]*(s[2] - c->Center()[2]) - 2.0*k*v[1]*(s[1] - y_apex);
	double eqc = pow(s[0] - c->Center()[0], 2.0) + pow(s[2] - c->Center()[2], 2.0) - k*pow(s[1] - y_apex, 2.0);

	double t1, t2;
	t1 = (-eqb + sqrt(eqb*eqb - 4.0*eqa*eqc))/2.0/eqa;
	t2 = (-eqb - sqrt(eqb*eqb - 4.0*eqa*eqc))/2.0/eqa;

	R3Point possible1, possible2;
	possible1 = r.Start() + r.Vector()*t1;
	possible2 = r.Start() + r.Vector()*t2;

	// Check if in y range
	if(possible1[1] < c->Center()[1] - c->Height()/2.0 || possible1[1] > c->Center()[1] + c->Height()/2.0) {
		t1 = -1;
	}
	if(possible2[1] < c->Center()[1] - c->Height()/2.0 || possible2[1] > c->Center()[1] + c->Height()/2.0) {
		t2 = -1;
	}
	if(t1 > 0 && t2 > 0) {
		if(t1 > t2) {
			*t = t2;
			*position = possible2;
			*normal = R3Vector(possible2[0] - c->Center()[0], 0, possible2[2] - c->Center()[2]);
			normal->Normalize();
			(*normal)[1] = k;
		}
		else {
			*t = t1;
			*position = possible1;
			*normal = R3Vector(possible1[0] - c->Center()[0], 0, possible1[2] - c->Center()[2]);
			normal->Normalize();
			(*normal)[1] = k;
		}
	}
	else if(t1 > 0) {
		*t = t1;
		*position = possible1;
		*normal = R3Vector(possible1[0] - c->Center()[0], 0, possible1[2] - c->Center()[2]);
		normal->Normalize();
		(*normal)[1] = k;
	}
	else if(t2 > 0) {
		*t = t2;
		*position = possible2;
		*normal = R3Vector(possible2[0] - c->Center()[0], 0, possible2[2] - c->Center()[2]);
		normal->Normalize();
		(*normal)[1] = k;
	}

	//Check endcaps
	R3Vector norm_y(0, -1, 0);
	R3Point planepoint(c->Center()[0], c->Center()[1] - c->Height()/2.0, c->Center()[2]);
	R3Plane plane(planepoint, norm_y);
	
	R3Point endcap_p;
	double endcap_t;
	if(IntersectPlane(&plane, r, &endcap_p, &norm_y, &endcap_t) == 1) {
		if(pow(endcap_p[0] - c->Center()[0], 2.0) + pow(endcap_p[2] - c->Center()[2], 2.0) < c->Radius()*c->Radius() && endcap_t > 0) {
			if(endcap_t < *t) {
				*t = endcap_t;
				*position = endcap_p;
				*normal = norm_y;
			}
		}
	}

	if(*t < DBL_MAX) {
		return 1;
	}
	else {
		return 0;
	}
}
示例#21
0
// compute intersection between a box and a ray
R3Intersection ComputeIntersection(R3Box *box, R3Ray &ray)
{
  R3Intersection min_intersection;
  min_intersection.t = numeric_limits<double>::infinity();
  min_intersection.hit = false;

  // check cases where:
  // 1) ray originates on the positive side of the max and points negative
  // 2) ray originates on the negative side of the min and points positive
  // 3) ray originates within the box and points either way
  // for each of X, Y and Z

  // I wrote the function out like this to eliminate most unnecessary checks that would
  // come along with a "cleaner" implementation. This tradeoff between optimization
  // and clean code is a good one because this intersection function is used for bounding boxes,
  // a critical part of ray intersection.

  // X DIRECTION
  if (ray.Start().X() <= box->XMin())
  {
    if (ray.Vector().X() > 0)
    {
      double t = (box->XMin() - ray.Start().X()) / ray.Vector().X();
      R3Point p = ray.Point(t);
      if (t >= 0 && t < min_intersection.t && CheckBoxX(p, box))
      {
        min_intersection.hit = true;
        min_intersection.normal = R3Vector(-1, 0, 0);
        min_intersection.position = p;
        min_intersection.t = t;
      }
    }
    else
      return min_intersection;
  }
  else if (ray.Start().X() >= box->XMax())
  {
    if (ray.Vector().X() < 0)
    {
      double t = (box->XMax() - ray.Start().X()) / ray.Vector().X();
      R3Point p = ray.Point(t);
      if (t >= 0 && t < min_intersection.t && CheckBoxX(p, box))
      {
        min_intersection.hit = true;
        min_intersection.normal = R3Vector(1, 0, 0);
        min_intersection.position = p;
        min_intersection.t = t;
      }
    }
    else
      return min_intersection;
  }
  else
  {
    if (ray.Vector().X() > 0)
    {
      double t = (box->XMax() - ray.Start().X()) / ray.Vector().X();
      R3Point p = ray.Point(t);
      if (t >= 0 && t < min_intersection.t && CheckBoxX(p, box))
      {
        min_intersection.hit = true;
        min_intersection.normal = R3Vector(-1, 0, 0);
        min_intersection.position = p;
        min_intersection.t = t;
      }
    }
    else if (ray.Vector().X() < 0)
    {
      double t = (box->XMin() - ray.Start().X()) / ray.Vector().X();
      R3Point p = ray.Point(t);
      if (t >= 0 && t < min_intersection.t && CheckBoxX(p, box))
      {
        min_intersection.hit = true;
        min_intersection.normal = R3Vector(1, 0, 0);
        min_intersection.position = p;
        min_intersection.t = t;
      }
    }
  }

  // Y DIRECTION
  if (ray.Start().Y() <= box->YMin())
  {
    if (ray.Vector().Y() > 0)
    {
      double t = (box->YMin() - ray.Start().Y()) / ray.Vector().Y();
      R3Point p = ray.Point(t);
      if (t >= 0 && t < min_intersection.t && CheckBoxY(p, box))
      {
        min_intersection.hit = true;
        min_intersection.normal = R3Vector(0, -1, 0);
        min_intersection.position = p;
        min_intersection.t = t;
      }
    }
    else
      return min_intersection;
  }
  else if (ray.Start().Y() >= box->YMax())
  {
    if (ray.Vector().Y() < 0)
    {
      double t = (box->YMax() - ray.Start().Y()) / ray.Vector().Y();
      R3Point p = ray.Point(t);
      if (t >= 0 && t < min_intersection.t && CheckBoxY(p, box))
      {
        min_intersection.hit = true;
        min_intersection.normal = R3Vector(0, 1, 0);
        min_intersection.position = p;
        min_intersection.t = t;
      }
    }
    else
      return min_intersection;
  }
  else
  {
    if (ray.Vector().Y() > 0)
    {
      double t = (box->YMax() - ray.Start().Y()) / ray.Vector().Y();
      R3Point p = ray.Point(t);
      if (t >= 0 && t < min_intersection.t && CheckBoxY(p, box))
      {
        min_intersection.hit = true;
        min_intersection.normal = R3Vector(0, -1, 0);
        min_intersection.position = p;
        min_intersection.t = t;
      }
    }
    else if (ray.Vector().Y() < 0)
    {
      double t = (box->YMin() - ray.Start().Y()) / ray.Vector().Y();
      R3Point p = ray.Point(t);
      if (t >= 0 && t < min_intersection.t && CheckBoxY(p, box))
      {
        min_intersection.hit = true;
        min_intersection.normal = R3Vector(0, 1, 0);
        min_intersection.position = p;
        min_intersection.t = t;
      }
    }
  }

  // Z DIRECTION
  if (ray.Start().Z() <= box->ZMin())
  {
    if (ray.Vector().Z() > 0)
    {
      double t = (box->ZMin() - ray.Start().Z()) / ray.Vector().Z();
      R3Point p = ray.Point(t);
      if (t >= 0 && t < min_intersection.t && CheckBoxZ(p, box))
      {
        min_intersection.hit = true;
        min_intersection.normal = R3Vector(0, 0, -1);
        min_intersection.position = p;
        min_intersection.t = t;
      }
    }
    else
      return min_intersection;
  }
  else if (ray.Start().Z() >= box->ZMax())
  {
    if (ray.Vector().Z() < 0)
    {
      double t = (box->ZMax() - ray.Start().Z()) / ray.Vector().Z();
      R3Point p = ray.Point(t);
      if (t >= 0 && t < min_intersection.t && CheckBoxZ(p, box))
      {
        min_intersection.hit = true;
        min_intersection.normal = R3Vector(0, 0, 1);
        min_intersection.position = p;
        min_intersection.t = t;
      }
    }
    else
      return min_intersection;
  }
  else
  {
    if (ray.Vector().Z() > 0)
    {
      double t = (box->ZMax() - ray.Start().Z()) / ray.Vector().Z();
      R3Point p = ray.Point(t);
      if (t >= 0 && t < min_intersection.t && CheckBoxZ(p, box))
      {
        min_intersection.hit = true;
        min_intersection.normal = R3Vector(0, 0, -1);
        min_intersection.position = p;
        min_intersection.t = t;
      }
    }
    else if (ray.Vector().Z() < 0)
    {
      double t = (box->ZMin() - ray.Start().Z()) / ray.Vector().Z();
      R3Point p = ray.Point(t);
      if (t >= 0 && t < min_intersection.t && CheckBoxZ(p, box))
      {
        min_intersection.hit = true;
        min_intersection.normal = R3Vector(0, 0, 1);
        min_intersection.position = p;
        min_intersection.t = t;
      }
    }
  }

  return min_intersection;
}
示例#22
0
// compute the nearest intersection between a ray and a scene node
R3Intersection ComputeIntersection(R3Scene *scene, R3Node *node, R3Ray ray, double min_t)
{
  // transform the ray and minimum t from parent node coordinates to this node's coordinates
  R3Vector v_orig = ray.Vector();
  v_orig.InverseTransform(node->transformation);
  double min_t_trans = min_t * v_orig.Length();
  ray.InverseTransform(node->transformation);

  // initialize intersection as infinitely far away
  R3Intersection min_intersection;
  min_intersection.hit = false;
  min_intersection.t = min_t_trans;

  // check this node if it contains a shape
  if (node->shape != NULL && node->is_obstacle)
  {
    R3Intersection i;
    i.hit = false;
    i.t = numeric_limits<double>::infinity();

    // intersect with node shape
    switch (node->shape->type)
    {
      case R3_BOX_SHAPE:
      {
        i = ComputeIntersection(node->shape->box, ray);
      }
      break;
      case R3_SPHERE_SHAPE:
      {
        i = ComputeIntersection(node->shape->sphere, ray);
      }
      break;
      case R3_MESH_SHAPE:
      {
        i = ComputeIntersection(node->shape->mesh, ray, min_intersection.t);
      }
      break;
      // not implemented
      case R3_COIN_SHAPE:
      case R3_CYLINDER_SHAPE:
        i = ComputeIntersection(node->shape->cylinder, ray);
      case R3_CONE_SHAPE:
        break;
      case R3_SEGMENT_SHAPE:
        break;
      case R3_CIRCLE_SHAPE:
        break;
      case R3_NUM_SHAPE_TYPES:
        break;
    }
    if (node->is_coin) {
      printf("I'm a coin");
      i = ComputeIntersection(&(node->bbox), ray);
    }
    // update minimum if found
    if (i.hit && i.t < min_intersection.t)
    {
      i.node = node;
      min_intersection = i;
    }
  }

  // recursively intersect to children nodes
  for (unsigned int i = 0; i < node->children.size(); i++)
  { 
    // check if ray intersects with the child node
    R3Intersection child_bbox_intersection = ComputeIntersection(&(node->children[i]->bbox), ray);
    // if true, intersect with this child node
    if (child_bbox_intersection.hit && child_bbox_intersection.t < min_intersection.t)
    {
      R3Intersection child_intersection = ComputeIntersection(scene, node->children[i], ray, min_intersection.t);
      // update intersection if necessary
      if (child_intersection.hit && child_intersection.t < min_intersection.t)
      {
        min_intersection = child_intersection;
      }
    }
  }

  // transform intersection from this node's coordinates to the parent node coordinates
  if (min_intersection.hit)
  {
    min_intersection.normal.InverseTransform(node->transformation.Transpose());
    min_intersection.normal.Normalize();
    min_intersection.position.Transform(node->transformation);
    R3Vector v2 = ray.Vector();
    v2.Transform(node->transformation);
    min_intersection.t = min_intersection.t * v2.Length();
  }
  return min_intersection;
}
示例#23
0
int IntersectNode(R3Node *node, R3Ray r, R3Point *position, R3Vector *normal, double *t, R3Node **intersectingnode, R3Node *excludenode) {
	*t = DBL_MAX;
	R3Ray orig_r = r;
	R3Point intersectionpoint;
	R3Vector intersectionnormal;
	double t_intersection;

	R3Matrix tmatrix = node->transformation;
	R3Matrix tinvmatrix = tmatrix.Inverse();
	r.Transform(tinvmatrix);

	if(node->shape != NULL && excludenode != node) {
		R3Shape *shape = node->shape;
		int intersects = -1;
		if(shape->type == R3_SPHERE_SHAPE) {
			R3Sphere *s = shape->sphere;
			intersects = IntersectSphere(s, r, &intersectionpoint, &intersectionnormal, &t_intersection);
		}
		else if(shape->type == R3_BOX_SHAPE) {
			R3Box *b = shape->box;
			intersects = IntersectBox(b, r, &intersectionpoint, &intersectionnormal, &t_intersection);
		}
		else if(shape->type == R3_MESH_SHAPE) {
			R3Mesh *m = shape->mesh;
			intersects = IntersectMesh(m, r, &intersectionpoint, &intersectionnormal, &t_intersection);
		}
		else if(shape->type == R3_CYLINDER_SHAPE) {
			R3Cylinder *c = shape->cylinder;
			intersects = IntersectCylinder(c, r, &intersectionpoint, &intersectionnormal, &t_intersection);
		}
		else if(shape->type == R3_CONE_SHAPE) {
			R3Cone *c = shape->cone;
			intersects = IntersectCone(c, r, &intersectionpoint, &intersectionnormal, &t_intersection);
		}

		if(intersects == 1) {
			if(t_intersection > 0 && t_intersection < *t) {
				*t = t_intersection;
				*position = intersectionpoint;
				*normal = intersectionnormal;
				*intersectingnode = node;
			}
		}
	}

	for(unsigned int i=0; i<node->children.size(); i++) {
		R3Node *child = node->children[i];
		R3Node *temp_intersectingnode;
		
		if(IntersectBox(&(child->bbox), r, &intersectionpoint, &intersectionnormal, &t_intersection) == 1) {
      if(t_intersection > *t) continue;
		}
		else {
      continue;
		}
		
		if(IntersectNode(child, r, &intersectionpoint, &intersectionnormal, &t_intersection, &temp_intersectingnode, excludenode) == 1) {
			if(t_intersection > 0 && t_intersection < *t) {
				*t = t_intersection;
				*position = intersectionpoint;
				*normal = intersectionnormal;
				*intersectingnode = temp_intersectingnode;
			}
		}
	}

	if(*t < DBL_MAX) {
		normal->Transform(tmatrix);
		normal->Normalize();
		position->Transform(tmatrix);

		if(orig_r.Vector()[0] != 0)
			*t = (*position - orig_r.Start())[0] / orig_r.Vector()[0];
		else if(orig_r.Vector()[1] != 0)
			*t = (*position - orig_r.Start())[1] / orig_r.Vector()[1];
		else
			*t = (*position - orig_r.Start())[2] / orig_r.Vector()[2];

		return 1;
	}
	else {
		return 0;
	}
}
示例#24
0
RNBoolean R3Parallel(const R3Ray& ray1, const R3Ray& ray2)
{
    // Return whether ray1 and ray2 are parallel
    return R3Parallel(ray1.Vector(), ray2.Vector());
}
示例#25
0
RNBoolean R3Parallel(const R3Vector& vector, const R3Ray& ray)
{
    // Return whether vector and ray are parallel
    return R3Parallel(vector, ray.Vector());
}
示例#26
0
int IntersectCylinder(R3Cylinder *c, R3Ray r, R3Point *position, R3Vector *normal, double *t) {
	R3Vector v = r.Vector();
	R3Point s = r.Start();
	*t = DBL_MAX;

	// check cylinder sides on infinite
	double eqa = v[0]*v[0] + v[2]*v[2];
	double eqb = 2.0*v[0]*(s[0] - c->Center()[0]) + 2.0*v[2]*(s[2] - c->Center()[2]);
	double eqc = pow(s[0] - c->Center()[0], 2.0) + pow(s[2] - c->Center()[2], 2.0) - c->Radius()*c->Radius();

	double t1, t2;
	t1 = (-eqb + sqrt(eqb*eqb - 4.0*eqa*eqc))/2.0/eqa;
	t2 = (-eqb - sqrt(eqb*eqb - 4.0*eqa*eqc))/2.0/eqa;

	R3Point possible1, possible2;
	possible1 = r.Start() + r.Vector()*t1;
	possible2 = r.Start() + r.Vector()*t2;

	// Check if in y range
	if(possible1[1] < c->Center()[1] - c->Height()/2.0 || possible1[1] > c->Center()[1] + c->Height()/2.0) {
		t1 = -1;
	}
	if(possible2[1] < c->Center()[1] - c->Height()/2.0 || possible2[1] > c->Center()[1] + c->Height()/2.0) {
		t2 = -1;
	}
	if(t1 > 0 && t2 > 0) {
		if(t1 > t2) {
			*t = t2;
			*position = possible2;
			*normal = R3Vector(possible2[0] - c->Center()[0], 0, possible2[2] - c->Center()[2]);
			normal->Normalize();
		}
		else {
			*t = t1;
			*position = possible1;
			*normal = R3Vector(possible1[0] - c->Center()[0], 0, possible1[2] - c->Center()[2]);
			normal->Normalize();
		}
	}
	else if(t1 > 0) {
		*t = t1;
		*position = possible1;
		*normal = R3Vector(possible1[0] - c->Center()[0], 0, possible1[2] - c->Center()[2]);
		normal->Normalize();
	}
	else if(t2 > 0) {
		*t = t2;
		*position = possible2;
		*normal = R3Vector(possible2[0] - c->Center()[0], 0, possible2[2] - c->Center()[2]);
		normal->Normalize();
	}

	//Check endcaps
	for(int i=0; i<2; i++) {
		R3Vector norm_y(0, i == 0 ? 1 : -1, 0);
		double sign = (i == 0 ? 1.0 : -1.0);
		R3Point planepoint(c->Center()[0], c->Center()[1] + sign*c->Height()/2.0, c->Center()[2]);
		R3Plane plane(planepoint, norm_y);
		
		R3Point endcap_p;
		double endcap_t;
		if(IntersectPlane(&plane, r, &endcap_p, &norm_y, &endcap_t) == 1) {
			if(pow(endcap_p[0] - c->Center()[0], 2.0) + pow(endcap_p[2] - c->Center()[2], 2.0) < c->Radius()*c->Radius() && endcap_t > 0) {
				if(endcap_t < *t) {
					*t = endcap_t;
					*position = endcap_p;
					*normal = norm_y;
				}
			}
		}
	}

	if(*t < DBL_MAX) {
		return 1;
	}
	else {
		return 0;
	}
}
示例#27
0
RNBoolean R3Parallel(const R3Line& line, const R3Ray& ray)
{
    // Return whether line and ray are parallel
    return R3Parallel(line.Vector(), ray.Vector());
}
示例#28
0
// Compute the radiance emitted back along a given ray from a given intersection
R3Rgb ComputeRadiance(R3Scene *scene, R3Ray &ray, R3Intersection &intersection, int depth, int max_depth, int distrib)
{
  R3Rgb il(0, 0, 0, 1);
  R3Material *mat = intersection.node->material;
  // add a small epsilon normal to the intersection point so light and secondary rays don't intersect with the same surface
  R3Point offset_intersection_pos = intersection.position + intersection.normal * EPSILON;
  // v = a unit vector pointing from the intersection to the ray origin
  R3Vector v = -ray.Vector();

  // if we are not using distributed ray tracing...
  if (distrib == 0)
  {
    // include lighting from all scene lights
    for (int i = 0; i < scene->NLights(); i++)
    {
      R3Light *light = scene->Light(i);

      // l = a unit vector pointing from the intersection to a light
      // d = the distance between the intersection and a light
      R3Vector l;
      double d;
      if (light->type == R3_DIRECTIONAL_LIGHT)
      {
        l = -light->direction;
        d = numeric_limits<double>::infinity();
      }
      else
      {
        l = (light->position - intersection.position);
        l.Normalize();
        d = (light->position - intersection.position).Length();
      }

      // construct a ray from the intersection toward the light
      R3Ray light_ray(offset_intersection_pos, l);

      // compute a shadow intersection and if one exists (that is between the intersection and the light), ignore the light
      R3Intersection shadow_intersection = ComputeIntersection(scene, scene->Root(), light_ray, d);
      if (shadow_intersection.hit && shadow_intersection.t < d)
        continue;

      // compute the luminance of the light at the intersection position
      R3Rgb light_il = ComputeLuminance(light, intersection.position);

      // evaluate the Phong BRDF equations for diffuse and specular reflection
      double cos_nl = l.Dot(intersection.normal);

      // r = l reflected across the intersection normal
      R3Vector r = 2 * cos_nl * intersection.normal - l; 
      double cos_vr = v.Dot(r);
      // if the light is shining on the front of the surface, include diffuse lighting
      // if the light is also less than 90 degrees from the camera vector, include specular lighting
      if (cos_nl > 0)
      {
        il += light_il * mat->kd * cos_nl;
        if (cos_vr > 0)
          il += light_il * mat->ks * pow(cos_vr, mat->shininess);
      }
    }
  }
  else // if we ARE using distributed...
  {
    if (depth < max_depth)
    {
      int nrays = 0;
      R3Rgb dist_il(0, 0, 0, 1);
      while (nrays < distrib)
      {
        // randomly sample outgoing directions using random variables with normal distributions
        double u1 = (double)rand()/RAND_MAX;
        double u2 = (double)rand()/RAND_MAX;
        double u3 = (double)rand()/RAND_MAX;
        double u4 = (double)rand()/RAND_MAX;

        double s1 = sqrt(-2 * log(u1));
        double rx = s1 * cos(2 * 3.14159 * u2);
        double ry = s1 * sin(2 * 3.14159 * u2);
        double s2 = sqrt(-2 * log(u3));
        double rz = s2 * cos(2 * 3.14159 * u4);

        R3Vector l(rx, ry, rz);
        l.Normalize();

        // check if vector is in the right hemisphere
        if (l.Dot(intersection.normal) < 0)
          continue;

        // generate a random ray and recursively compute the radiance it contributes
        R3Ray rray(offset_intersection_pos, l);
        R3Rgb rgb = ComputeRadiance(scene, rray, depth + 1, max_depth, distrib);
        
        // evaluate the Phong BRDF equations for diffuse and specular reflection
        double cos_nl = l.Dot(intersection.normal);

        // r = l reflected across the intersection normal
        R3Vector r = 2 * cos_nl * intersection.normal - l; 
        double cos_vr = v.Dot(r);
        // if the light is shining on the front of the surface, include diffuse lighting
        // if the light is also less than 90 degrees from the camera vector, include specular lighting
        if (cos_nl > 0)
        {
          dist_il += rgb * mat->kd * cos_nl;
          if (cos_vr > 0)
            dist_il += rgb * mat->ks * pow(cos_vr, mat->shininess);
        }

        nrays++;
      }

      il += dist_il / nrays;
    }
  }

  // if the material has a specular component and the maximum depth hasn't been reached, reflect the camera ray from the
  // intersection surface and recusively evaluate its radiance
  if (!mat->ks.IsBlack() && depth < max_depth)
  {
    R3Ray spec_ray = GetReflectedRay(intersection, ray);
    R3Rgb spec = ComputeRadiance(scene, spec_ray, depth + 1, max_depth, distrib);
    il += spec * mat->ks;
  }

  // add refraction component for both distributed and non-distributed techniques
  if (!mat->kt.IsBlack() && depth < max_depth)
  {
    R3Ray trans_ray = GetRefractedRay(intersection, ray, mat->indexofrefraction, scene);
    R3Rgb trans = ComputeRadiance(scene, trans_ray, depth + 1, max_depth, distrib);
    il += trans * mat->kt;
  }

  // add ambient and emission components
  il += mat->emission;
  il += mat->ka * scene->ambient;

  return il;
}
示例#29
0
RNBoolean R3Parallel(const R3Ray& ray, const R3Span& span)
{
    // Return whether ray and span are parallel
    return R3Parallel(ray.Vector(), span.Vector());
}
示例#30
0
R3Intersection ComputeIntersection(R3Cylinder *cylinder, R3Ray r) {
  R3Intersection ret;
  R3Point p0 = r.Point(0);
  R3Vector v = r.Vector();
  double h = cylinder->Height();
  
  // check the two caps
  // Bottom First
  R3Plane bottom = R3negxz_plane;
  R3Point bottom_center = R3Point(0, -h/2, 0);
  bottom.Translate(bottom_center - R3null_point);
  
  double denom = r.Vector().Dot(bottom.Normal());
  double t = (denom == 0) ? -1 : -(R3Vector(p0[0], p0[1], p0[2]).Dot(bottom.Normal()) + bottom.D()) / denom;
  double dist = R3Distance(r.Point(t), bottom_center);
  if ((t > EPSILON) && (!ret.hit || t < ret.t) && (dist < cylinder->Radius())) {
    ret.t = t;
    ret.normal = bottom.Normal();
    ret.position = r.Point(t);
    ret.hit = true;
  }
  
  // Now Top
  R3Plane top = R3posxz_plane;
  R3Point top_center = R3Point(0, cylinder->Height()/2, 0);
  top.Translate(top_center - R3null_point);
  
  denom = r.Vector().Dot(top.Normal());
  t = (denom == 0) ? -1 : -(R3Vector(p0[0], p0[1], p0[2]).Dot(top.Normal()) + top.D()) / denom;
  dist = R3Distance(r.Point(t), top_center);
  if ((t > EPSILON) && (!ret.hit || t < ret.t) && (dist < cylinder->Radius())) {
    ret.t = t;
    ret.normal = top.Normal();
    ret.position = r.Point(t);
    ret.hit = true;
  }
  
  // Now check the side
  // we know (p0[0] + v[0]*t)^2 + (p0[0] + v[0]*t)^2 = r^2
  // so we solve the quadratic
  double A = v[0]*v[0] + v[2]*v[2];
  double B = 2*p0[0]*v[0] + 2*p0[2]*v[2];
  double C = p0[0]*p0[0] + p0[2]*p0[2] - cylinder->Radius()*cylinder->Radius();
  double det = B*B - 4 * A * C;
  if (det < 0) return ret;
  double t_plus = (-B + sqrt(det)) / (2*A);
  double t_minus = (-B - sqrt(det)) / (2*A);
  
  R3Point loc = r.Point(t_minus);
  if (((t_minus > EPSILON) && (!ret.hit || t_minus < ret.t)) &&
      ((loc[1] > -h/2) && (loc[1] < h/2)))
  {
    ret.t = t_minus;
    ret.position = loc;
    ret.normal = R3Point(loc[0], 0, loc[2]) - R3null_point;
    ret.normal.Normalize();
    ret.hit = true;
  }
  loc = r.Point(t_plus);
  if (((t_plus > EPSILON) && (!ret.hit || t_plus < ret.t)) &&
      ((loc[1] > -h/2) && (loc[1] < h/2))) {
    ret.t = t_plus;
    ret.position = loc;
    ret.normal = R3Point(loc[0], 0, loc[2]) - R3null_point;
    ret.normal.Normalize();
    ret.hit = true;
  }
  return ret;
}