Пример #1
0
bool Face::plane_intersect(const Ray &r, Hit &h, bool intersect_backfacing, bool* backfacing_hit) {

	// insert the explicit equation for the ray into the implicit equation of the plane

	// equation for a plane
	// ax + by + cz = d;
	// normal . p + direction = 0
	// plug in ray
	// origin + direction * t = p(t)
	// origin . normal + t * direction . normal = d;
	// t = d - origin.normal / direction.normal;

	Vec3f normal = computeNormal();
	double d = normal.Dot3((*this)[0]->get());

	double numer = d - r.getOrigin().Dot3(normal);
	double denom = r.getDirection().Dot3(normal);

	if (denom == 0) return 0;	// parallel to plane

	if (!intersect_backfacing && normal.Dot3(r.getDirection()) >= 0) 
		return 0; // hit the backside

	double t = numer / denom;
	if (t > EPSILON && t < h.getT()) {
		h.set(t,this->getMaterial(),normal,this);
		assert (h.getT() >= EPSILON);
		//hit the backside but that's okay in this case
		if (normal.Dot3(r.getDirection()) >= 0){
			*backfacing_hit = true;
		}
		return 1;
	}
	return 0;
}
Пример #2
0
bool Plane::intersect(const Ray & r, Hit & h, float tmin)
{
	assert (tmin >= 0.0f);

	Vec3f org = r.getOrigin();
	Vec3f dir = r.getDirection();

	if (dir.Dot3(normal) < 1.0e-7 && dir.Dot3(normal) > -1.0e-7) {
		return false;
	}					// Appromately parrell to plane

	float tempT = (offset - org.Dot3(normal)) / dir.Dot3(normal);
	if (tempT <= 1e-6) {
		return false;
	}
	else if (tempT >= tmin && tempT < h.getT()) 
	{
		// Update Hit Point
		normal.Normalize();
		h.set(tempT, NULL, normal, color, r);

		return true;
	}
	
	return false;
}
Пример #3
0
bool Sphere::intersect(const Ray &r, Hit &h, float tmin)
{
	Vec3f v = center - r.getOrigin();
	float tp = v.Dot3(r.getDirection());
	float det = tp*tp - v.Dot3(v) + radius*radius;
	//intersect
	if(det > 0)
	{
		//t'
		det = sqrtf(det); 

		float t1 = tp - det;
		float t2 = tp + det;

		if(t1 > tmin && t1 < h.getT())
		{
			Vec3f normal = (r.pointAtParameter(t1) - center);
			normal /= radius;
			normal.Normalize();
			h.set(t1,material,normal,r);
			return 1;
		}
		else if(t2 > tmin && t2 < h.getT())
		{
			//sphere's normal
			Vec3f normal = (r.pointAtParameter(t2) - center);
			normal /= radius;
			normal.Normalize();
			h.set(t2,material,normal,r);
			return 1;
		}
	}
	return 0;
}
Пример #4
0
float sphere::testIntersection(Vec3f eye, Vec3f dir)
{
	float disc = pow(dir.Dot3(eye - center), 2) - dir.Dot3(dir) * ((eye - center).Dot3(eye - center) - radius * radius);
	if(disc < 0) return MAX_DIST;
	float t1 = (-1 * dir.Dot3(eye - center) + sqrt(disc)) / dir.Dot3(dir);
	float t2 = (-1 * dir.Dot3(eye - center) - sqrt(disc)) / dir.Dot3(dir);
	if(t1 < 0 || t2 < 0)
		return MAX_DIST;
	return min(t1, t2);
}
Пример #5
0
float Edge::DihedralAngle(){
  /*
   * Warning this function returns NULL 
   * when there is an edge without two 
   * adjcent triangles
   *
   */

  // Is there even an angle here?
  if(opposite == NULL)
    return (float)NULL;

  // Find the angle of the face of a triangle
  Triangle* a = triangle;
  Triangle* b = opposite->getTriangle();

  Vec3f normalA = a->getNormal();
  Vec3f normalB = b->getNormal();

  // Using Equation theta = acos( (a . b) / (|a||b|)) 
  double top = normalA.Dot3(normalB);
  double bottom = normalA.Length() * normalB.Length();
  double result = acos(top/bottom);
  return result;

}
Пример #6
0
Vec3f mirrorDirection(const Vec3f &normal, const Vec3f &incoming)
{
	//(反射光方向:R = V - 2(V.N)N )
	Vec3f reflectDir = incoming - 2 * (incoming.Dot3(normal))*normal;
	reflectDir.Normalize();
	return reflectDir;
}
Пример #7
0
Vec3f RayTracer::shadow(const Vec3f &point,
			const Vec3f &pointOnLight,
			const Face *f,
			const Ray &ray,
			const Hit &hit) const
{
        const Vec3f normal(hit.getNormal());
        const Material *m = hit.getMaterial();

	Vec3f dirToLight = pointOnLight - point;
	dirToLight.Normalize();
	/* If dot product < 0, surface is not facing light */
	if (normal.Dot3(dirToLight) > 0) {
		Ray rayToLight(point, dirToLight);
		Hit hLight;
		bool blocked = CastRay(rayToLight, hLight, false);
		while (std::fabs(hLight.getT()) < SURFACE_EPSILON &&
				std::fabs((pointOnLight - point).Length()) > SURFACE_EPSILON) {
			rayToLight = Ray(rayToLight.pointAtParameter(SURFACE_EPSILON),
					dirToLight);
			blocked = CastRay(rayToLight, hLight, false);
		}
		if (hLight.getT() == FLT_MAX || hLight.getMaterial() != f->getMaterial()) {
			return Vec3f(0, 0, 0);
		}

		const Vec3f lightColor = 0.2 * f->getMaterial()->getEmittedColor() * f->getArea();
		return m->Shade(ray,hit,dirToLight,lightColor,args);
	}
	return Vec3f(0, 0, 0);
}
Пример #8
0
Vec3f RayTracer::mirrorDirection(const Vec3f &normal, const Vec3f &incoming) const
{
	Vec3f reflectionDir;
	reflectionDir = incoming - normal * (incoming.Dot3(normal)) * 2;
	reflectionDir.Normalize();
	return reflectionDir;
}
Пример #9
0
bool Sphere::intersect(const Ray &r, Hit &h, float tmin)
{
	//直线方程 P = t*D + R    ①
	//圆方程  ||P||= raduis   ②
	//将①带入②, 由点乘的性质(满足分配率,交换律),求得t^2+2RDt+R^2-r^2=0
	//得t = -RD±sqrt(RD^2-R^2+r^2)
	//选择距离较近的那个点t = -RD-sqrt(RD^2-R^2+r^2)
	Vec3f D = r.getDirection();
	Vec3f R = r.getOrigin()-center;


	float R2 = R.Dot3(R);
	float RD = R.Dot3(D);
	
	float b2_4ac = RD*RD-R2+radius*radius;//R2 RD RDRD这些其实可以存在ray里,但是算法研究以程序清晰为要
	if(b2_4ac<0)return 0;
	float t;
	t = -RD - sqrt(b2_4ac);
	if(t<0){
		t = -RD + sqrt(b2_4ac);
		if(t < 0)return 0;
	}
	if(t<h.getT())
	{
		h.set(t, &color, r);
	}

	return 1;
}
void PhotonMapping::TracePhoton(const Vec3f &position, const Vec3f &direction, 
				const Vec3f &energy, int iter) {
  
  if(iter>args->num_bounces){
    return;
  }

  Hit h = Hit();
  Ray R = Ray(position, direction);
  bool intersect = raytracer->CastRay(R, h, false);
  if(!intersect){
    return;
  }
  Material *m = h.getMaterial();
  Vec3f normal = h.getNormal();
  Vec3f point = R.pointAtParameter(h.getT());
  Vec3f opDirec = direction;
  opDirec.Negate();
  opDirec.Normalize();
  Vec3f diffuse = m->getDiffuseColor(), reflec = m->getReflectiveColor();
  double diffuseAnswer = diffuse.x()+diffuse.y()+diffuse.z();
  double reflecAnswer = reflec.x()+reflec.y()+reflec.z();
  double total = reflecAnswer+diffuseAnswer;
  diffuseAnswer /= total;
  reflecAnswer /= total;
  double seed = GLOBAL_mtrand.rand();
  if(seed <= diffuseAnswer && seed >= 0){
    Vec3f newEnergy = energy * diffuse;
    Vec3f newPosition = point;
    Vec3f newDirection = Vec3f(GLOBAL_mtrand.rand(),GLOBAL_mtrand.rand(),GLOBAL_mtrand.rand());
    newDirection.Normalize();
    Photon answer = Photon(point,opDirec,newEnergy,iter+1);
    kdtree->AddPhoton(answer);
    TracePhoton(newPosition, newDirection, newEnergy, iter+1);
  }
  else if(seed>diffuseAnswer && seed <= 1){
    Vec3f newEnergy = energy * reflec;
    Vec3f newPosition = point;
    Vec3f newDirection = direction - 2 * direction.Dot3(normal) * normal;
    Photon answer = Photon(point,opDirec,newEnergy,iter+1);
    kdtree->AddPhoton(answer);
    TracePhoton(newPosition, newDirection, newEnergy, iter+1);
  }
  // ==============================================
  // ASSIGNMENT: IMPLEMENT RECURSIVE PHOTON TRACING
  // ==============================================

  // Trace the photon through the scene.  At each diffuse or
  // reflective bounce, store the photon in the kd tree.

  // One optimization is to *not* store the first bounce, since that
  // direct light can be efficiently computed using classic ray
  // tracing.



}
Vec3f PhotonMapping::GatherIndirect(const Vec3f &point, const Vec3f &normal, const Vec3f &direction_from) const {


  if (kdtree == NULL) { 
    std::cout << "WARNING: Photons have not been traced throughout the scene." << std::endl;
    return Vec3f(0,0,0); 
  }


  // ================================================================
  // ASSIGNMENT: GATHER THE INDIRECT ILLUMINATION FROM THE PHOTON MAP
  // ================================================================


  // collect the closest args->num_photons_to_collect photons
  // determine the radius that was necessary to collect that many photons
  // average the energy of those photons over that radius
  double radius=1;

  std::vector<Photon> potentials;
  while (potentials.size()<args->num_photons_to_collect)
  {
	  BoundingBox b(point-Vec3f(radius,radius,radius),point+Vec3f(radius,radius,radius));

	  kdtree->CollectPhotonsInBox(b,potentials);
	  for (int i=0;i<potentials.size();i++)
	  {
		  if (normal.Dot3(potentials[i].getDirectionFrom())>0)
		  {
			  potentials.erase(potentials.begin()+i);
			  i--;
		  }
		  else if ((potentials[i].getPosition()-point).Length()>radius)
		  {
			  potentials.erase(potentials.begin()+i);
			  i--;
		  }
	  }

	  radius*=2;


  }
  assert(potentials.size()>=args->num_photons_to_collect);
  for (unsigned int i=0;i<potentials.size();i++)
	  potentials[i].setPoint(point);
  std::sort(potentials.begin(),potentials.end(),comparePhotons);

  radius = (potentials[args->num_photons_to_collect-1].getPosition()-point).Length()/2;
  Vec3f color;
  for (int i=0;i<args->num_photons_to_collect;i++)
	  color+=potentials[i].getEnergy();
  color*=1/(radius*radius);
  //std::cout<<radius<<"\n";
  // return the color
  return color;
}
Пример #12
0
Vec3f PhongMaterial::Shade(const Ray& ray, const Hit& hit, const Vec3f& dirToLight, const Vec3f& lightColor) const {
	Vec3f v = ray.getDirection() * -1.0f;
    Vec3f n = hit.getNormal();
	// Vec3f h = dirToLight + ray.getDirection() * -1.0f;
	// h.Normalize();
	float diffuse = dirToLight.Dot3(n);
	Vec3f r = n * 2.0 * n.Dot3(dirToLight) - dirToLight;
	float specular = v.Dot3(r);
	
	if (diffuse < 0.0f) diffuse = 0.0f;
	if (specular < 0.0f) specular = 0.0f;
	
	Vec3f color = this->getDiffuseColor();
	color = color * diffuse + m_specularColor * pow(specular, m_exponent);
	color.Scale(lightColor);
	
	return color;
}
Пример #13
0
float triangle::testIntersection(Vec3f eye, Vec3f dir)
{
	//see the book/slides for a description of how to use Cramer's rule to solve
	//for the intersection(s) of a line and a plane, implement it here and
	//return the minimum distance (if barycentric coordinates indicate it hit
	//the triangle) otherwise 9999999
	
	Vec3f edge1 =  alpha;
	Vec3f edge2 =  beta;

	Vec3f pvec;
	Vec3f::Cross3(pvec,dir, edge2);
	
	float det = edge1.Dot3(pvec);
	
	// no intersection
	if(det > (-1 * EPSILON) && det < EPSILON)
            return MISS;
	
	float invDet = 1/det;
	Vec3f tvec = eye-point0;
	
	float u = tvec.Dot3(pvec) * invDet;
	
	if(u < 0 || u > 1)
		return MISS;
	
	Vec3f qvec;
	Vec3f::Cross3(qvec,tvec, edge1);
        
	float v = dir.Dot3(qvec) * invDet;
	
	if(v < 0 || (u + v) > 1)
		return MISS;          
      
	float dist = edge2.Dot3(qvec) * invDet;
	
	if(dist < 0)
		return MISS;
	
	return dist;
}
Пример #14
0
bool Sphere::intersect(const Ray &r, Hit &h, float tmin)
{
    Vec3f temp = r.getOrigin() - mCenterPoint;
    Vec3f rayDirection = r.getDirection();

    double a = rayDirection.Dot3(rayDirection);
    double b = 2*rayDirection.Dot3(temp);
    double c = temp.Dot3(temp) - mRadius*mRadius;

#ifdef DEBUG
    //cout << "temp="  << temp<<endl;
    //printf("Sphere::intersect, a=%f, b=%f, c=%f\n", a, b, c);
#endif

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

    if (discriminant > 0)
    {
        discriminant = sqrt(discriminant);
        double t = (- b - discriminant) / (2*a);

        if (t < tmin)
            t = (- b + discriminant) / (2*a);

        if (t < tmin || t > T_MAX)
            return false;

#ifdef DEBUG
      //  printf("Sphere::intersect, there is a hit, t=%f\n", t);
#endif
        Vec3f normal = r.getOrigin() + t * r.getDirection() - mCenterPoint;
        normal.Normalize();
        h.set(t, mMaterial, normal, r);
        return true;
    }

    return false;
}
Пример #15
0
//何时返回true?非全反射时 何时返回false
bool RayTracer::transmittedDirection(const Vec3f &normal, const Vec3f &incoming, float index_i, float index_t, Vec3f &transmitted) const
{
	float nr = index_i / index_t;
	Vec3f I = incoming*(-1.0f);
	float cosI = I.Dot3(normal);
	float isAllTrans = 1 - nr*nr*(1 - cosI*cosI);
	if(isAllTrans < 0)  //全反射
		return false;

	float cosT = sqrt(isAllTrans);
	transmitted = normal*(nr*cosI - cosT) - I*nr;
	transmitted.Normalize();
	return true;
}
Пример #16
0
Vec3f Material::Shade(const Ray &ray, const Hit &hit, 
                      const Vec3f &dirToLight, 
                      const Vec3f &lightColor, ArgParser *args) const {
  
  Vec3f point = ray.pointAtParameter(hit.getT());
  Vec3f n = hit.getNormal();
  Vec3f e = ray.getDirection()*-1.0f;
  Vec3f l = dirToLight;
  
  Vec3f answer = Vec3f(0,0,0);

  // emitted component
  // -----------------
  answer += getEmittedColor();

  // diffuse component
  // -----------------
  double dot_nl = n.Dot3(l);
  if (dot_nl < 0) dot_nl = 0;
  answer += lightColor * getDiffuseColor(hit.get_s(),hit.get_t()) * dot_nl;

  // specular component (Phong)
  // ------------------
  // make up reasonable values for other Phong parameters
  Vec3f specularColor = reflectiveColor;
  double exponent = 100;

  // compute ideal reflection angle
  Vec3f r = (l*-1.0f) + n * (2 * dot_nl);
  r.Normalize();
  double dot_er = e.Dot3(r);
  if (dot_er < 0) dot_er = 0;
  answer += lightColor*specularColor*pow(dot_er,exponent)* dot_nl;

  return answer;
}
Пример #17
0
Vec3f PhongMaterial::Shade(const Ray &ray, const Hit &hit, const Vec3f &dirToLight, const Vec3f &lightColor) const
{
    Vec3f eyeDir = ray.getDirection();
    eyeDir.Negate();

    Vec3f eyePlusLight = eyeDir + dirToLight;
    eyePlusLight.Normalize(); 
    
    float hn = eyePlusLight.Dot3(hit.getNormal());
    hn = pow(hn, mPhongComponent);

    Vec3f color = lightColor * mHighLightColor;
    color = hn * color;

    return color;
}
Пример #18
0
void Radiosity::insertInterpolatedColor(int index, Face *f, Vertex *v) {
    std::vector<Face*> faces;
    CollectFacesWithVertex(v,f,faces);
    double total = 0;
    Vec3f color = Vec3f(0,0,0);
    Vec3f normal = f->computeNormal();
    for (unsigned int i = 0; i < faces.size(); i++) {
        Vec3f normal2 = faces[i]->computeNormal();
        double area = faces[i]->getArea();
        if (normal.Dot3(normal2) < 0.5) continue;
        assert (area > 0);
        total += area;
        color += area * whichVisualization(RENDER_RADIANCE,faces[i],faces[i]->getRadiosityPatchIndex());
    }
    assert (total > 0);
    color /= total;
    insertColor(color);
}
Пример #19
0
bool transmittedDirection(const Vec3f &normal, const Vec3f &incoming,
	float index_i, float index_t, Vec3f &transmitted)
{
	//折射光方向:T = e(N.I) - sqrt(1 - e ^ 2(1 - (N.I) ^ 2)))N - eI
	//从物体内部向外:T = (-N.I - sqrt(1 - 1 / e ^ 2(1 - N.I) ^ 2) * 1 / e)N - I / e
	//The dot product of the normal and ray direction is negative when we are outside 
	//the object, and positive when we are inside. 

	//不需要在这里判断光线是在内还是在外,求法是一样的
	//不同的是一方面normal是反的,另一方面比值是互倒的
	Vec3f I = incoming;
	I.Negate();
	float e = index_i / index_t;
	float tmp = normal.Dot3(I);
	float sqrt_value = 1 - e*e*(1 - tmp*tmp);
	if (sqrt_value < 0)
		return false;
	transmitted = (e*tmp - sqrt(sqrt_value))*normal - e*I;
	return true;
}
Пример #20
0
Vec3f RayTracer::reflections(const Ray &ray, const Hit &hit, int bounce_count, double roughness) const
{
	if (bounce_count <= 0)
		return Vec3f(0, 0, 0);
	const Vec3f point = ray.pointAtParameter(hit.getT());

	/* Get mirror direction */
	const Vec3f orig_dir = ray.getDirection();
	Vec3f norm = hit.getNormal();
	norm.Normalize();
	const Vec3f new_dir = orig_dir - 2 * orig_dir.Dot3(norm) * norm;

	const Ray new_ray(point, new_dir);
	Vec3f rand_vec(0, 0, 0);
	double answerx = 0, answery = 0, answerz = 0;
	/* sphere projection, what if the center of the sphere misses the
	 * object?
	 */

	{
		for (int i = 0; i <= args->num_glossy_samples; ++i) {
			/* Getting gloss ray */
			Ray start_ray(new_ray.getOrigin(),
					new_ray.getDirection() + rand_vec);
			const Vec3f answer(reflection(start_ray, bounce_count - 1));

			answerx += answer.x();
			answery += answer.y();
			answerz += answer.z();
			rand_vec = Vec3f(roughness * (static_cast<double>(rand()) / RAND_MAX),
				roughness * (static_cast<double>(rand()) / RAND_MAX),
				roughness * (static_cast<double>(rand()) / RAND_MAX));
		}
	}
	Vec3f answer = Vec3f(answerx, answery, answerz);
	answer *= static_cast<double>(1)/(args->num_glossy_samples + 1);
	return answer;
}
Пример #21
0
Vec3f scene::rayTrace(Vec3f eye, Vec3f dir, int recurseDepth)
{
    //start with black, add color as we go
    Vec3f answer(0,0,0);

    //test for intersection against all our objects
    float dist = myObjGroup->testIntersections(eye, dir);
    //if we saw nothing, return the background color of our scene
    if (dist==9999999)
        return bgColor;

    Vec3f textureColor;

    //get the material index and normal vector(at the point we saw) of the object we saw
    int matIndex = myObjGroup->getClosest()->getMatIndex();
    Vec3f normal = myObjGroup->getClosest()->getNormal(eye, dir * dist);

    //determine texture color

    if (myMaterials.at(matIndex).texture==NULL)
        //this is multiplicative, rather than additive
        //so if there is no texture, just use ones
        textureColor.Set(1,1,1);
    else
    {
        //if there is a texture image, ask the object for the image coordinates (between 0 and 1)
        Vec3f coords = myObjGroup->getClosest()->getTextureCoords(eye, dir * dist);

        //get the color from that image location
        textureColor.Set(
            PIC_PIXEL(myMaterials.at(matIndex).texture,(int)(myMaterials.at(matIndex).texture->nx*coords.x()),(int)(myMaterials.at(matIndex).texture->ny*coords.y()),0),
            PIC_PIXEL(myMaterials.at(matIndex).texture,(int)(myMaterials.at(matIndex).texture->nx*coords.x()),(int)(myMaterials.at(matIndex).texture->ny*coords.y()),1),
            PIC_PIXEL(myMaterials.at(matIndex).texture,(int)(myMaterials.at(matIndex).texture->nx*coords.x()),(int)(myMaterials.at(matIndex).texture->ny*coords.y()),2));
        textureColor = textureColor*(1/255.0);
    }

    // add ambient light/color to our answer
    answer += multiplyColorVectors(ambLight, myMaterials.at(matIndex).diffuseCol);

    // set point slightly above the actual surface, prevents
    // issues with that point intersecting itself
    Vec3f point = eye + (dir * dist) + (normal * .0001);
    Vec3f real_point = eye + (dir * dist);

    // get the diffuse color of our material
    Vec3f diffuseColor = myMaterials.at(matIndex).diffuseCol;

    // iterate through lights
    for (int iter = 0; iter < myLights.size(); iter++) {

        Vec3f lightPos = myLights.at(iter).position;
        Vec3f direction= lightPos - point;

        direction.Normalize();
        float distance = myObjGroup->testIntersections(point, direction);

        // if nothing between point and light
        if (distance == 9999999) {
            Vec3f color = multiplyColorVectors(diffuseColor, myLights.at(iter).color);
            float nl    = abs(direction.Dot3(normal));

            answer += (color * nl);

            // now do the specular
            // we need vector that goes from point to eye
            Vec3f backDir = dir * -1.0f;

            Vec3f h		= (backDir + direction);
            h.Normalize();

            Vec3f Cp	=  myMaterials.at(matIndex).specularCol;
            float p		= myMaterials.at(matIndex).shininess;
            float nh	= abs(normal.Dot3(h));

            nh			= pow(nh, p);
            answer		+= multiplyColorVectors(myLights.at(iter).color, Cp) * nh;
        }
    }
    //if the light can see the surface point,
    //add its diffuse color to a total diffuse for the point (using our illumination model)
    //use testIntersection to help decide this

    //add the diffuse light times the accumulated diffuse light to our answer

    if (recurseDepth < 3) {
        Vec3f e = dir * -1.0f;
        e.Normalize();
        Vec3f r = dir + normal * 2.0f * e.Dot3(normal);
        r.Normalize();

        Vec3f bounced = rayTrace(point, r, recurseDepth + 1);
        answer += (multiplyColorVectors(bounced, myMaterials.at(matIndex).reflectiveCol));

        // refraction
        Vec3f transparentColor	= myMaterials.at(matIndex).transparentCol;
        float transpar			= transparentColor.Dot3(transparentColor);

        if (transpar > 0.0f) {
            float exitAngle, entryAngle;

            if (dir.Dot3(normal) < 0.0f) {
                entryAngle = acos(dir.Dot3(normal * -1.0f));
                exitAngle = entryAngle * myMaterials.at(matIndex).refractionIndex;
            } else {
                entryAngle = acos(dir.Dot3(normal));
                exitAngle = entryAngle / myMaterials.at(matIndex).refractionIndex;
            }

            Vec3f b = (dir + (normal * cos(entryAngle))) * (1.0f /sin(entryAngle));
            b.Normalize();
            Vec3f refracted = (b * sin(exitAngle)) - (normal * cos(exitAngle));
            refracted.Normalize();

            answer += multiplyColorVectors(rayTrace(real_point, refracted, recurseDepth + 1), myMaterials.at(matIndex).transparentCol);
        }
    }
    //put a limit on the depth of recursion
    //if (recurseDepth<3)
    //{
    //reflect our view across the normal
    //recusively raytrace from the surface point along the reflected view
    //add the color seen times the reflective color


    //if going into material (dot prod of dir and normal is negative), bend toward normal
    //find entry angle using inverse cos of dot product of dir and -normal
    //multiply entry angle by index of refraction to get exit angle
    //else, bend away
    //find entry angle using inverse cos of dot product of dir and normal
    //divide entry angle by index of refraction to get exit angle
    //recursively raytrace from the other side of the object along the new direction
    //add the color seen times the transparent color
    //}

    //multiply whatever color we have found by the texture color
    answer=multiplyColorVectors(answer,textureColor);
    return answer;
}