Example #1
0
	/**
	   directions leave from the point
	*/
	Color evaluate (const Vector3D& to_eye_, const Vector3D& to_light_) const {
		switch (m_model) {
		case DIFFUSE:
			if (m_normal.dot (to_eye_) * m_normal.dot (to_light_) < 0.f) {
				//not same hemisphere
				return Color (0.f);
			}
			return m_kd;
			break;
		case BLINN_PHONG:
		{
			if (m_normal.dot (to_eye_) * m_normal.dot (to_light_) < 0.f) {
				//not same hemisphere
				return Color (0.f);
			}
			//www.cs.ucl.ac.uk/staff/j.kautz/GameCourse/04_PointLights.pdf
			Vector3D half = (to_eye_ + to_light_).normalize();
            return m_kd + m_ks * (powf ((half.dot (m_normal)), m_shininess) * (m_shininess * 4) / (8.f * (float)M_PI));
			break;
		}
		case PURE_REFL:
			return m_kd; //no chance it is a reflection direction
			break;
		case FRESNEL:
			return Color (0.f); //no chance it is a reflection or refraction direction
			break;
		default:
			return Color (0.f);			
		}
	}
/**
 * Phong Shading
 */
void PointLight::shade( Ray3D& ray ) {
	Intersection intPoint = ray.intersection;

	// construct vectors
	Vector3D n = intPoint.normal;
	Vector3D de = -ray.dir;
	Vector3D s = get_position() - intPoint.point; // light source
	Vector3D m = ((2 * n.dot(s)) * n) - s; // perfect mirror directions

	// normalize
	n.normalize();
	s.normalize();
	m.normalize();
	de.normalize();

	// do the diffuse shading
	do_diffuse(s, n, ray);

	// do the specular shading
	Colour specular(0, 0, 0);

	double mdde = m.dot(de);
	if ( mdde >= 0 ) {
		specular =
			pow(mdde, intPoint.mat->specular_exp)
			* intPoint.mat->specular * _col_specular;
	}

	if ( ray.shadowed ) {
		ray.col = ray.col + (_shadow_opacity * specular);
	} else {
		ray.col = ray.col + specular;
	}
}
bool AbstractSphere::rayCast(const Ray& r,Segment& sg) const {
    /*
    http://www.siggraph.org/education/materials/HyperGraph/raytrace/rtinter1.htm
    http://www.gamedev.net/topic/476158-ray-sphere-intersection/
    */
    //calc B
    // We solve this second-degree equation in t:
    // distance(p+t*v,center)==radius
    // If we define w = p-center
    // we can write that as
    // <w+t*v,w+t*v> == radius*radius
    // <w,w> + 2.0f*t*<w,v> + t*t*<v,v> - radius*radius == 0
    // <v,v>*t*t + 2.0f*<w,v>*t + <w,w>-radius*radius == 0
    // A*t*t + B*t*t + C*t*t == 0
    Vector3D w = r.point;
    float A = r.dir.dot(r.dir);
    float B = 2*w.dot(r.dir);
    float C = w.dot(w) - radius*radius;
    //calc d
    float D = B*B-4.0f*A*C;
    float sqrtD=sqrt(D);
    //points
    sg.t[0]=r.point+r.dir*(-B - sqrtD)/(2.0f*A);
    sg.t[1]=r.point+r.dir*(-B + sqrtD)/(2.0f*A);
    //
    return D >=0;
}
Example #4
0
bool intersectTriangle(const Point3D &o, const Vector3D &d, float *t, const Point3D &p0,  const Point3D &p1,  const Point3D &p2){
  Vector3D e1, e2;
  e1.difference(p1, p0);
  e2.difference(p2, p0);

  Vector3D p;
  p.cross(d, e2);

  double a = e1.dot(p);
  if (fabs(a) < EPSILON)
    return false;

  double f = 1/a;
  Vector3D s;
  s.difference(o, p0);
  double u = f * s.dot(p);
  if((u < 0.0) || (u > 1.0))
    return false;

  Vector3D q;
  q.cross(s, e1);

  double v = f * d.dot(q);
  if((v < 0.0) || ((u + v) > 1.0))
    return false;

  *t = f*e2.dot(q);
  return true;
}
Example #5
0
bool Mesh::intersect(const Ray& ray, Intersection& j) const
{
  bool intersected = false;

  // Check if bounding ball has been intersected first
  // If not then the mesh cannot have been intersected
  Intersection k;
  bool bball_intersected = m_boundingBall.intersect(ray, k);
  if(bball_intersected)
  {
    // Loop through each face and check if there is an intersection
    double prev_t = std::numeric_limits<double>::infinity();
    for(auto face : m_faces)
    {
      // Compute the normal for the face
      Point3D P0 = m_verts[face[0]];
      Point3D P1 = m_verts[face[1]];
      Point3D P2 = m_verts[face[2]];

      Vector3D n = (P1-P0).cross(P2-P0).normalized();

      // Now check if the ray intersects the polygon containing the face
      // If denom is 0 then the ray does not intersect the plane at all
      double denom = n.dot(ray.direction());
      if(fabs(denom) < std::numeric_limits<double>::epsilon()) continue;

      // If t is negative or a previous intersection has a smaller t (meaning it is closer to the
      // ray's origin) then disregard this face and continue
      double t = n.dot(P0 - ray.origin()) / denom;
      if(t < 0 || prev_t < t) continue;

      // Calculate intersection point
      Point3D Q = ray.origin() + t*ray.direction();

      bool outside = false;
      for(size_t i = 0; i < face.size(); i++)
      {
        Point3D Q0 = (i == 0) ? m_verts[face.back()] : m_verts[face[i-1]];
        Point3D Q1 = m_verts[face[i]];

        if((Q1-Q0).cross(Q-Q0).dot(n) < 0)
        {
          outside = true;
          break;
        }
      }

      if(!outside)
      {
        // It is within the bounds of the polygon
        intersected = true;
        prev_t = t;
        j.q = Q;
        j.n = n;
      }
    }
  }

  return intersected;
}
Example #6
0
bool UnitSphere::intersect( Ray3D& ray, const Matrix4x4& worldToModel,
		const Matrix4x4& modelToWorld ) {
	// TODO: implement intersection code for UnitSphere, which is centred 
	// on the origin.  
	//
	// Your goal here is to fill ray.intersection with correct values
	// should an intersection occur.  This includes intersection.point, 
	// intersection.normal, intersection.none, intersection.t_value.   
	//
	// HINT: Remember to first transform the ray into object space  
	// to simplify the intersection test.
	Point3D world_origin(0, 0, 0);
	
	double lambda;
	
	Vector3D d = worldToModel * ray.dir;
	Point3D a = worldToModel * ray.origin;
	Point3D c(0, 0, 0);
	Vector3D nmb = a - c;
	
	double A = d.dot(d);
	double B = nmb.dot(d);
	double C = nmb.dot(nmb) - 1;
	
	double D = (B * B) - (A * C);
	
	if (D < 0){
		return false;
	}
	else if(D == 0){
		lambda = - (B / A);
	}
	else{
		double lambda1 = - (B / A) + (sqrt(D) / A);
		double lambda2 = - (B / A) - (sqrt(D) / A);
		lambda = std::min(lambda1, lambda2);
		if (lambda < 0){
			lambda = std::max(lambda1, lambda2);
			if (lambda < 0){
				return false;
			}
		}
	}
	Point3D intersect_point = a + (lambda * d);
    Vector3D normal_vector = intersect_point - c;
    normal_vector.normalize();
    
	ray.intersection.t_value = lambda;
    ray.intersection.normal = transNorm(worldToModel, normal_vector);
    ray.intersection.normal.normalize();
    ray.intersection.point = modelToWorld * intersect_point;
    ray.intersection.none = false;
	return true;
}
Example #7
0
// find the distance between a ray and a plane.
float Physics::distRayPlane(Vector3D vRayOrigin, Vector3D vnRayVector, Vector3D vnPlaneNormal, float planeD)
{
    float cosAlpha;
    float deltaD;

    cosAlpha = vnRayVector.dot(vnPlaneNormal);

    // parallel to the plane (alpha=90)
    if (cosAlpha == 0) -1.0f;

    deltaD = planeD - vRayOrigin.dot(vnPlaneNormal);
    
	return (deltaD/cosAlpha);
}
Example #8
0
	Color refract_dir (const Vector3D& to_eye_, Vector3D * p_to_light_) const {
		float cos_theta = m_normal.dot (to_eye_);
		
		bool entering = (cos_theta > 0.f);
		float ior_i, ior_t;

		if (entering) {
			ior_i = 1.f; //assume non-nested refractive objects
			ior_t = m_ior;
		} else {
			ior_i = m_ior;
			ior_t = 1.f;
		}

		float ior_ratio = ior_i / ior_t;
		
		float cos_squared = 1.f - ior_ratio * ior_ratio * (1.f - cos_theta * cos_theta);

		if (cos_squared < 0.f) {
			//no transmitted media, it is a total internal reflection
			//(light is totally reflected instead of being transmitted).
			return Color (0.f);
		}

		Vector3D normal_part = m_normal * (ior_ratio * cos_theta - (entering ? 1.f : -1.f) * sqrtf (cos_squared));
		Vector3D eye_part = to_eye_ * ior_ratio;
		*p_to_light_ = normal_part - eye_part;
		
		float ref_fresnel_0 = (ior_i - ior_t) / (ior_i + ior_t);
		ref_fresnel_0 *= ref_fresnel_0;

		float ref_fresnel = ref_fresnel_0 + (1.f - ref_fresnel_0) * powf (1.f - fabsf (cos_theta), 5.f);

		return m_kt * (1.f - ref_fresnel);
	}
Example #9
0
Point3D Shot::getWallIntersectionPoint(BoundingWall* wall) {
    if (!isBeam) {
        return Object3D::getWallIntersectionPoint(wall);
    }

    Point3D toReturn(*position);
    Point3D pointOnPlane = wall->normal.scalarMultiply(-wall->wallSize);

    // Calculate intersection between beam and wall.
    Vector3D normalizedDirection = velocity->getNormalized();
    Vector3D wallNormal = wall->normal.scalarMultiply(-1); // To make it face away from the center.
    double rayDotNormal = normalizedDirection.dot(wallNormal);
    if (rayDotNormal <= 0) {
        wall->actuallyHit = false;
        return toReturn;
    }

    Vector3D rayOriginToPointOnPlane(*position, pointOnPlane);

    double distance = rayOriginToPointOnPlane.dot(wallNormal) / rayDotNormal;
    if (distance < 0) {
        wall->actuallyHit = false;
        return toReturn;
    }

    toReturn.addUpdate(normalizedDirection.scalarMultiply(distance));
    return toReturn;
}
Example #10
0
bool UnitSphere::intersect( Ray3D& ray, const Matrix4x4& worldToModel,
		const Matrix4x4& modelToWorld ) {
	// TODO: implement intersection code for UnitSphere, which is centred 
	// on the origin.  
	//
	// Your goal here is to fill ray.intersection with correct values
	// should an intersection occur.  This includes intersection.point, 
	// intersection.normal, intersection.none, intersection.t_value.   
	//
	// HINT: Remember to first transform the ray into object space  
	// to simplify the intersection test.
    
    Vector3D d = worldToModel*ray.dir;
    // d.normalize();
    Point3D e = worldToModel*ray.origin;
    Point3D c;
    float A = d.dot(d);
    float B = d.dot(e-c);
    float C = (e-c).dot(e-c)-1.0;
    if ((B*B - A*C) < 0)
    {
        ray.intersection.none = true;
        return false;
    }
    else
    {
        float t1 = (-B - sqrt(B*B - A*C)) / A;
        float t2 = (-B + sqrt(B*B - A*C)) / A;
        float t = fmin(t1, t2);
        if (t > 0)
        {
            if (!ray.intersection.none && ray.intersection.t_value < t)
            {
                return false;
            }
            Vector3D n = e + t*d - c;
            n.normalize();
            ray.intersection.point = modelToWorld * (e + t*d);
            ray.intersection.normal = transNorm(worldToModel, n);
            ray.intersection.none = false;
            ray.intersection.t_value = t;
            return true;
        }
        else
            return false;
    }
}
TEST(Vector3, BinaryOperators) {
    Vector3F vec(3.f, 9.f, 4.f);
    vec = vec + 4.f;
    EXPECT_FLOAT_EQ(7.f, vec.x);
    EXPECT_FLOAT_EQ(13.f, vec.y);
    EXPECT_FLOAT_EQ(8.f, vec.z);

    vec = vec + Vector3F(-2.f, 1.f, 5.f);
    EXPECT_FLOAT_EQ(5.f, vec.x);
    EXPECT_FLOAT_EQ(14.f, vec.y);
    EXPECT_FLOAT_EQ(13.f, vec.z);

    vec = vec - 8.f;
    EXPECT_FLOAT_EQ(-3.f, vec.x);
    EXPECT_FLOAT_EQ(6.f, vec.y);
    EXPECT_FLOAT_EQ(5.f, vec.z);

    vec = vec - Vector3F(-5.f, 3.f, 12.f);
    EXPECT_FLOAT_EQ(2.f, vec.x);
    EXPECT_FLOAT_EQ(3.f, vec.y);
    EXPECT_FLOAT_EQ(-7.f, vec.z);

    vec = vec * 2.f;
    EXPECT_FLOAT_EQ(4.f, vec.x);
    EXPECT_FLOAT_EQ(6.f, vec.y);
    EXPECT_FLOAT_EQ(-14.f, vec.z);

    vec = vec * Vector3F(3.f, -2.f, 0.5f);
    EXPECT_FLOAT_EQ(12.f, vec.x);
    EXPECT_FLOAT_EQ(-12.f, vec.y);
    EXPECT_FLOAT_EQ(-7.f, vec.z);

    vec = vec / 4.f;
    EXPECT_FLOAT_EQ(3.f, vec.x);
    EXPECT_FLOAT_EQ(-3.f, vec.y);
    EXPECT_FLOAT_EQ(-1.75f, vec.z);

    vec = vec / Vector3F(3.f, -1.f, 0.25f);
    EXPECT_FLOAT_EQ(1.f, vec.x);
    EXPECT_FLOAT_EQ(3.f, vec.y);
    EXPECT_FLOAT_EQ(-7.f, vec.z);

    Vector3D v = Vector3D(2.0, 1.0, 3.0).normalized();
    Vector3D normal = Vector3D(1.0, 1.0, 1.0).normalized();

    Vector3D reflected = v.reflected(normal);
    Vector3D reflectedAnswer = Vector3D(-2.0, -3.0, -1.0).normalized();
    EXPECT_NEAR(reflected.distanceTo(reflectedAnswer), 0.0, 1e-9);

    Vector3D projected = v.projected(normal);
    EXPECT_NEAR(projected.dot(normal), 0.0, 1e-9);

    auto tangential = normal.tangential();
    EXPECT_NEAR(std::get<0>(tangential).dot(normal), 0.0, 1e-9);
    EXPECT_NEAR(std::get<1>(tangential).dot(normal), 0.0, 1e-9);
}
Example #12
0
Colour PhongMaterial::calculateLighting(const Vector3D& incident, const Vector3D& normal, const Vector3D& reflected, const Vector3D& viewer, const Colour& intensity) const {
  double incidentDotNormal = std::max(0.0, incident.dot(normal));

  Colour diffuse = m_kd * incidentDotNormal * intensity;

#ifdef BLINN_PHONG
  // Blinn-Phong.
  Vector3D h = viewer + incident;
  h.normalize();
  Colour specular = m_ks * pow(std::max(0.0, h.dot(normal)), m_shininess) * intensity;
#else
  // Phong.
  Colour specular = m_ks * pow(reflected.dot(viewer), m_shininess) * intensity;
#endif

  //std::cout << "incident " << incident << ", normal " << normal << ", viewer " << viewer << ", intensity " << intensity << ", result=" << diffuse+specular << std::endl;

  return diffuse + specular;
}
Example #13
0
void PointLight::shade( Ray3D& ray, Ray3D::intersection_func intersectCheck ) const {

    Material* mat = ray.intersection.mat;
    
    // compute direction towards light
    Vector3D lightDir = pos_ - ray.intersection.point;
    double distance = lightDir.normalize();
    ray.col += col_ambient_ * mat->ambient.at(ray.intersection.uv);

    // cos of angle from normal to lightDir
    double cosAngle = lightDir.dot(ray.intersection.normal);

    if (cosAngle < 0) {
        return;
    }
    // shadow check
    else {
        Ray3D lightRay(ray.intersection.point, lightDir);
        intersectCheck(lightRay);

        // if we intersect an object between the light and point
        // we are considering, then it is in shadow
        if (!lightRay.intersection.none && lightRay.intersection.t_value < distance ) {
            return;
        }
    }

    // diffuse
    ray.col += col_diffuse_ * mat->diffuse.at(ray.intersection.uv) * cosAngle;

    // direction of reflection of light ray
    Vector3D reflectDir = 2*cosAngle*ray.intersection.normal - lightDir;
    reflectDir.normalize();
    // cos of angle from reflection to ray back to viewer
    double rv = -reflectDir.dot(ray.dir);

    // specular
    if (rv > 0) {
        ray.col += col_specular_ * mat->specular.at(ray.intersection.uv)
                                 * pow(rv, mat->specular_exp);
    }
}
Example #14
0
AffineTrans3D initInvViewMatrix( Point3D const& eye, Vector3D view, Vector3D up) {
    AffineTrans3D mat; 
    Vector3D w;
    view.normalize();
    up = up - up.dot(view)*view;
    up.normalize();
    w = view.cross(up);

    mat.A.col(0) = w.v;
    mat.A.col(1) = up.v;
    mat.A.col(2) = -view.v;

    mat.t = eye.v;

    return mat; 
}
Example #15
0
/**
 * Calculate the diffuse value for a given ray, vector s and normal n
 */
void PointLight::do_diffuse(const Vector3D& s, const Vector3D& n, Ray3D& ray)
{
	// http://www.cdf.toronto.edu/~moore/csc418/Notes/Phong.pdf
	Colour ambient, diffuse;

	// ambient is simply mat * light
	ambient = ray.intersection.mat->ambient * _col_ambient;

	// for the diffuse light, depends on angle of light
	double sdn = s.dot(n);
	if (sdn >= 0)
		diffuse = sdn * ray.intersection.mat->diffuse * _col_diffuse;

	if ( ray.shadowed )
		ray.col = ray.col + (_shadow_opacity * diffuse) + ambient;
	else
		ray.col = ray.col + diffuse + ambient;
}
Example #16
0
// Compute the effect of the queued collisions on the given ball
void SuperCollider::bounce(Ball* ball)
{
	// Aggregate normals from the collision
	// Normalize the resultant normal (make it a unit vector)

	Vector3D collision_norm;
	int hitcount[7] = {0, 0, 0, 0, 0, 0, 0};
	double friction = 0.0;

	vector<Collision*>::const_iterator it;
	for (it = _collisions.begin(); it != _collisions.end(); it++)
	{
		vector<CollideSide>::const_iterator hit;
		for (hit = (*it)->hits.begin(); hit != (*it)->hits.end(); hit++)
		{
			CollideSide side = *hit;
			hitcount[side]++;
		}

		friction += (*it)->friction;

		delete *it;
	}
	_collisions.clear();

	for (int i = 0; i < 6; i++)
	{
		if (hitcount[i])
		{
			collision_norm = collision_norm + Collision::getNormal((CollideSide)i);
		}
	}

	collision_norm.normalize();

	Vector3D ballspeed = ball->getVelocity();
	//Vector3D ballspin = ball->getVelocity(true);
	Vector3D resultant = ballspeed - 2 * ballspeed.dot(collision_norm) * collision_norm;

	ball->setVelocity(resultant);

	//ballspin = friction * ballspin;
	//ball->setVelocity(ballspin, true);
}
Example #17
0
bool Mesh::faceIntersection(
    const Ray& ray, HitRecord* hitRecord, const Mesh::Face& face) {
  // Get a point on the plane
  Vector3D norm;
  double t;
  {
    const auto& p0 = m_verts[face[0]];
    const auto& p1 = m_verts[face[1]];
    const auto& p2 = m_verts[face[face.size()-1]];
    norm = (p1 - p0).cross(p2 - p0);
    auto rayNorm = ray.dir.dot(norm);

    // Parallel
    if (isZero(rayNorm)) return false;

    t = (p0 - ray.start).dot(norm) / rayNorm;
    // No intersection
    if (t < 0 || isZero(t)) {
      return false;
    }
  }

  // Intersection point
  auto planePt = ray.at(t);
  // Now check if planePt is "left" of everything
  for (size_t i = 0; i < face.size(); ++i) {
    // Go over points in order
    const auto& p1 = m_verts[face[i]];
    const auto& p2 = m_verts[face[(i + 1) % face.size()]];
    // from p1 to p2
    const auto side = p2 - p1;
    // cross from p1 to plane pt and dot against normal
    auto k = norm.dot(side.cross(planePt - p1));
    if (!isZero(k) && k < 0) {
      // Zero means on the side; negative means opposite dir from norm
      return false;
    }
  }

  // Update if this is a better t value
  return hitRecord->update(norm, planePt, t);
}
Example #18
0
	Color reflect_dir (const Vector3D& to_eye_, Vector3D * p_to_light_) const {

		float cos_theta = m_normal.dot (to_eye_);
				
		*p_to_light_ = -to_eye_ + m_normal * 2.f * cos_theta; //not abs_cos_theta, the normal may be in the wrong sense
		
		bool entering = (cos_theta > 0.f);
		float ior_i, ior_t;

		if (entering) {
			ior_i = 1.f; //assume non-nested refractive objects
			ior_t = m_ior;
		} else {
			ior_i = m_ior;
			ior_t = 1.f;
		}

		float ior_ratio = ior_i / ior_t;

		float cos_squared = 1.f - ior_ratio * ior_ratio * (1.f - cos_theta * cos_theta);

		if (cos_squared < 0.f) {
			//no transmitted media, it is a total internal reflection
			//(light is totally reflected instead of being transmitted).
			return m_kr;
		}
		
		//compute fresnel reflectance.		
		float ref_fresnel_0 = (ior_i - ior_t) / (ior_i + ior_t);
		ref_fresnel_0 *= ref_fresnel_0;

		float abs_cos_theta = fabsf (cos_theta);
		float ref_fresnel = ref_fresnel_0 + (1.f - ref_fresnel_0) * powf (1.f - abs_cos_theta, 5.f);

		return m_kr * ref_fresnel;
	}
Example #19
0
void a4_render(// What to render
               SceneNode* root,
               // Where to output the image
               const std::string& filename,
               // Image size
               int width, int height,
               // Viewing parameters
               const Point3D& eye, const Vector3D& view,
               const Vector3D& up, double fov,
               // Lighting parameters
               const Colour& ambient,
               const std::list<Light*>& lights
               )
{
    // Fill in raytracing code here.
    Image img(width, height, 3);
    Matrix4x4 inv_transf;
    //pinhole camera
    Vector3D m_cx = (view.cross(up));
    m_cx.normalize();
    Vector3D m_cy = (-up);

    double m_fovrad = (fov*M_PI)/360.0;
    double m_cw = tan(m_fovrad);
    double a =(double(width)/double(height));
    double m_ch = m_cw;

    //for percent display
    float done = 0;
#pragma omp parallel for default(shared) reduction(+:done) schedule(guided)
    for (int y = 0; y < height; y++) {
        done = done + 1.0f;
        display_percentage( done, (float)height);
        for (int x = 0; x < width; x++) {
            //background color
            // Red: increasing from top to bottom
            double red = (double)y / height;
            // Green: increasing from top and bottom to middle
            double green = ((red <= 0.5) ? 2.0*red : (2.0 - 2.0*red));
            // Blue: decreasing from top to bottom
            double blue = 1.0 - red;
            Colour back(red,green,blue);
            //antialiasing  http://www.codermind.com/articles/Raytracer-in-C++-Part-II-Specularity-post-processing.html
            double sampleRatio= 0.25;
            Colour aux(0.0, 0.0, 0.0);
            for (double fragmentx = double(x) ; fragmentx < x + 1.0; fragmentx += 0.5 )
                for (double fragmenty = double(y) ; fragmenty < y + 1.0; fragmenty += 0.5 )
                {
                    Vector3D m_raydir;
                    //get primary ray direction
                    m_raydir = view + (fragmentx / (double(width))*2.0 -1.0 )*m_cw*a*m_cx + ((fragmenty) / (double(height))*2.0 - 1.0) * m_ch*m_cy;
                    m_raydir.normalize();
                    //m_raydir = Vector3D(0.0,0.0,-1.0);
                    Ray r(eye,m_raydir);
                    //Ray r(Point3D(x,y,800),m_raydir);
                    double coef = 1.0;
                    int level = 0;
                    bool hit = false;
                    Colour tmp(0.0, 0.0, 0.0);
                    do{
                        // find the closest intersection
                        Intersection closest_isect;
                        hit = root->closest_intersect(r,closest_isect,inv_transf);
                        //if(!hit) cout<< "fail hit"<< endl;
                        if(hit){
                            //cout<< "success hit"<< endl;
                            // put color to pixel
                            Colour diffuse(0.0, 0.0, 0.0);
                            Colour specular(0.0, 0.0, 0.0);
                            Ray reflected_ray;//reflected ray
                            reflected_ray.origin()= closest_isect.position();

                            for (std::list<Light*>::const_iterator cl = lights.begin(); cl != lights.end(); ++cl){

                                Vector3D L = (*cl)->position - closest_isect.position();
                                double light_dist = L.length();
                                if((L.dot(closest_isect.normal())) <= 0.0 || light_dist < 0.0)// test if the point if lighted
                                    continue;
                                L.normalize();
                                reflected_ray.direction()=L;

                                // attenuation factor
                                double fatt = 1.0/((*cl)->falloff[0]+ (*cl)->falloff[1]*light_dist
                                                   + (*cl)->falloff[2]*light_dist*light_dist);
                                coef = fatt;
                                if(coef < double(1e-6)) break;

                                // test if point is in shadow
                                bool in_shadow = false;
                                Intersection aux_isect;
                                if(root->closest_intersect(reflected_ray,aux_isect,inv_transf,light_dist))
                                    in_shadow = true;

                                //ilumination
                                if(!in_shadow){
                                    double lambert = reflected_ray.direction().dot(closest_isect.normal())*fatt;
                                    diffuse = diffuse + (lambert*(*cl)->colour)*closest_isect.mtrl()->get_diffuse();
                                    // reflection by blinn-phong model reference:http://www.codermind.com/
                                    Vector3D blinnDir = reflected_ray.direction() - r.direction();
                                    double temp = blinnDir.length2();
                                    if (temp != 0.0 )
                                    {
                                        blinnDir.normalize();
                                        double blinnTerm = max(blinnDir.dot(closest_isect.normal()), 0.0);
                                        blinnTerm = pow(blinnTerm ,closest_isect.mtrl()->get_shininess())*fatt;

                                        specular =specular + blinnTerm*closest_isect.mtrl()->get_specular()*(*cl)->colour;
                                    }
                                }
                            }
                            tmp = tmp + ambient*closest_isect.mtrl()->get_diffuse() + diffuse + specular;
                            if(closest_isect.mtrl()->get_shininess() < eps)
                                break;
                            double reflet = 2.0*(r.direction().dot(closest_isect.normal()));
                            r.origin() = closest_isect.position() + eps*closest_isect.normal();
                            r.direction() = (r.direction() - reflet * closest_isect.normal());
                            r.direction().normalize();
                            level++;
                        }
                    }while((coef > double(1e-6)) && level < 5 && hit);

                    aux =aux + sampleRatio*tmp;
                }
            if(aux.R()!=0.0 || aux.G()!= 0.0 || aux.B()!= 0.0)
                back = aux;

            img(x, y, 0) = back.R();
            img(x, y, 1) =back.G();
            img(x, y, 2) = back.B();
        }
    }

    std::cerr << "Stub: a4_render(" << root << ",\n     "
              << filename << ", " << width << ", " << height << ",\n     "
              << eye << ", " << view << ", " << up << ", " << fov << ",\n     "
              << ambient << ",\n     {";

    for (std::list<Light*>::const_iterator I = lights.begin(); I != lights.end(); ++I) {
        if (I != lights.begin()) std::cerr << ", ";
        std::cerr << **I;
    }
    std::cerr << "});" << std::endl;
    img.savePng(filename);
}
Example #20
0
bool Sphere::touchesBox(const Box* that) const {
  const Vector3D p = that->closestPoint(_center);
  const Vector3D v = p.sub(_center);
  return v.dot(v) <= (_radius * _radius);
}
Example #21
0
bool Sphere::touchesSphere(const Sphere* that) const {
  const Vector3D d = _center.sub(that->_center);
  const double squaredDist = d.dot(d);
  const double radiusSum = _radius + that->_radius;
  return squaredDist <= (radiusSum * radiusSum);
}
Example #22
0
RGBAPixel GeometricObject::rayTrace(PointLight& lightSrc, Point3D& pt, Ray& viewRay, vector<GeometricObject*>& shapes){
    
    RGBAPixel color = material.color;
    if(texture != NULL)
        color = *mapToTexture(pt);
    
    Vector3D dir(lightSrc.o,pt);
    dir.normalize();
    
    Point3D tempPt(pt+dir.reflect()*0.01);
    Ray backtraceRay(tempPt,dir.reflect(), "shadow"); //from hit point on shape to light source
    double tHitLight = lightSrc.o.distance(pt);
    bool shadow = false;
    
    Point3D trash(0,0,0);
    for(int i = 0; i < shapes.size(); i++){
        if(shapes[i]->isLightSrc)
            continue;
        double tHitAnotherShape = shapes[i]->hit(backtraceRay,trash);
        if(tHitAnotherShape < tHitLight && tHitAnotherShape > 0){
            shadow = true;
            break;
        }
    }
    
    //pt's intersection with viewRay and geometry
    Vector3D n(this->getNormal(pt));
    n.normalize();
    
    double r = 0.0;
    double g = 0.0;
    double b = 0.0;
    
    //Ambient Lighting
    r += 0.04 * 30;
    g += 0.04 * 30;
    b += 0.04 * 30;
    
    RGBAPixel temp(r*color.red, g*color.green ,b*color.blue);
    
    if(shadow){
        return temp;
    }
    
    
    //Diffuse Lighting
    Vector3D reflectRay = (dir.reflect()).hat();
    double product = reflectRay.dot(n);
    if (product > 0){
        r += color.red*product * material.kd;
        g += color.green*product * material.kd;
        b += color.blue*product * material.kd;
    }
    
    //Specular Lighting
    
    
    double epsilon = 10.0;
    Vector3D rVec(dir - (n*dir.dot(n)*2.0));
    double spec = rVec.dot(viewRay.d.reflect());
    double rw0e;
    if(spec > 0)
        rw0e = pow(spec,epsilon);
    else
        rw0e = 0;
    if(product > 0){
        r += color.red*rw0e * material.ks * 0.5;
        g += color.green*rw0e * material.ks * 0.5;
        b += color.blue*rw0e * material.ks * 0.5;
    }
    r = r*material.directScale;
    g = g*material.directScale;
    b = b*material.directScale;
    
    //Reflections
    double minTime = 100000.0;
    double tHitAnotherShape = 0.0;
    Vector3D recViewDir(viewRay.d - (2*viewRay.d*n)*n); //direction of mirror reflection
    recViewDir.normalize();
    
    Ray recViewRay(pt,recViewDir, "view");
    recViewRay.recurseLevel = viewRay.recurseLevel+1;
    Point3D recPt;
    RGBAPixel recColor;
    
    //Mirror Reflection
    if(material.reflectProperty == "mirror" && viewRay.recurseLevel < 3){
        
        GeometricObject* nextShape = NULL;
        
        for(int k = 0; k < shapes.size(); k++){
            if(shapes[k] == this)
                continue;
            
            tHitAnotherShape = shapes[k]->hit(recViewRay,recPt);
            if(tHitAnotherShape > 0.0 && tHitAnotherShape < minTime){
                nextShape = shapes[k];
                minTime = tHitAnotherShape;
            }
        }
        if(nextShape != NULL){
            recColor = nextShape->rayTrace(lightSrc, recPt, recViewRay, shapes);
            r += (recColor.red); //* (1-material.directScale);
            g += (recColor.green);// * (1-material.directScale);
            b += (recColor.blue);// * (1-material.directScale);
        }
    }
    if(material.reflectProperty == "glossy" && viewRay.recurseLevel < 3){
        
        double tempR = 0.0;
        double tempG = 0.0;
        double tempB = 0.0;
        
        Vector3D axisA = Vector3D(1,0,0).cross(recViewDir).hat() * 1;
        Vector3D axisB = axisA.cross(recViewDir).hat() * 1;

        Point3D tempPt = pt + recViewDir - 0.5*axisA - 0.5*axisB;
        Rectangle rect(tempPt, axisA, axisB);
        
        vector<Point3D> samplepts = rect.generatePoints(100);
        
        for(int i = 0; i < samplepts.size(); i++){
            Vector3D indirectDir(pt,samplepts[i]);
            Ray indirectRay(pt,indirectDir);
            indirectRay.recurseLevel = viewRay.recurseLevel + 1;
            
            GeometricObject* nextShape = NULL;
            double minTime = 100000.0;
            double tHitAnotherShape = 0.0;
            for(int k = 0; k < shapes.size(); k++){
                if(shapes[k] == this)
                    continue;
                
                tHitAnotherShape = shapes[k]->hit(indirectRay,recPt);
                if(tHitAnotherShape > 0.0 && tHitAnotherShape < minTime){
                    nextShape = shapes[k];
                    minTime = tHitAnotherShape;
                }
                if(nextShape != NULL && nextShape->material.transparency == 0){
                    recColor = nextShape->rayTrace(lightSrc, recPt, recViewRay, shapes);
                    tempR += (recColor.red);
                    tempG += (recColor.green);
                    tempB += (recColor.blue);
                }
            }
        }
        r += tempR / samplepts.size();
        g += tempG / samplepts.size();
        b += tempB / samplepts.size();
    }
    
    if(material.transparency > 0 && viewRay.recurseLevel == 0){
        double tempR = 255;
        double tempG = 255;
        double tempB = 255;
        
        Vector3D invNormal = n.reflect();
        Ray inverseRay(pt,invNormal);
        inverseRay.recurseLevel = viewRay.recurseLevel + 1;
        GeometricObject* nextShape = NULL;
        double minTime = 100000.0;
        double tHitAnotherShape = 0.0;
        for(int k = 0; k < shapes.size(); k++){
            if(shapes[k] == this)
                continue;
            
            tHitAnotherShape = shapes[k]->hit(inverseRay,recPt);
            if(tHitAnotherShape > 0.0 && tHitAnotherShape < minTime){
                nextShape = shapes[k];
                minTime = tHitAnotherShape;
            }
            if(nextShape != NULL && nextShape != this){
                recColor = nextShape->rayTrace(lightSrc, recPt, inverseRay, shapes);
                tempR = (recColor.red);
                tempG = (recColor.green);
                tempB = (recColor.blue);
            }
        }
        r = tempR * material.transparency + (r*(1-material.transparency));
        g = tempG * material.transparency + (g*(1-material.transparency));
        b = tempB * material.transparency + (b*(1-material.transparency));
    }
    
    //cap off maximum color values
    r =std::min((int)r,255);
    g =std::min((int)g,255);
    b =std::min((int)b,255);
    
    temp(r,g,b);
    return temp;
}
Example #23
0
// where v is normal to the plane, and w is the vector to the point
double BoundingBox::projection(const Vector3D &v, const Vector3D &w) const
{
	double dot = v.dot(w);
	dot = dot / v.length();
	return dot;
}