Пример #1
0
bool Tri::intersect(Ray& _ray, float* thit, Intersection* in) {
  Ray ray = _ray.transform(inverseTransform);
  if (!intersectP(ray)) { return false; }
  if (*thit < t) { return false; }

  p = ray.getPos() + ray.getDir() * t;
  w = p - a;
  vCrossW = glm::cross(v, w);
  uCrossW = glm::cross(u, w);

  if (glm::dot(vCrossW, vCrossU) < 0) { return false; }
  if (glm::dot(uCrossW, uCrossV) < 0) { return false; }

  beta = glm::length(vCrossW)/denom;
  gamma = glm::length(uCrossW)/denom;
  alpha = 1 - beta - gamma;

  if (!(beta <= 1 && gamma <= 1 && beta + gamma <= 1)) { return false; }

  *thit = t;
  in->localGeo.pos = mat4TimesVec3(getTransform(),
    (ray.getPos() + t * ray.getDir()), 1.0);
  in->localGeo.normal = getNormal();
  //shift position slightly towards normal (epsilon shift)
  in->localGeo.pos = in->localGeo.pos + in->localGeo.normal * epsilon;
  in->primitive = this;

  return true;
}
Пример #2
0
ptc::IntersectDescr Rectangle::intersect( const Ray& ray )
{
	const double dir_dot = normal_.dot( ray.getDir() );
	
	const bool is_grazing = std::abs( dir_dot ) <= 1e-4;
	const bool is_wrong_side = !getIsDoubleSided() && dir_dot >= -1e-4;
	
	if( is_grazing || is_wrong_side )
	{
		return IntersectDescr( this );
	}

	const Vector center_vec = center_ - ray.getOrigin();
	const double distance = -normal_.dot( center_vec );

	const double param = distance / -dir_dot;

	const Vector intersect = ray.getOrigin() + param * ray.getDir();
	const Vector intersect_vec = intersect - center_;

	const bool is_right_vec_ok = std::abs( right_.dot( intersect_vec ) ) <= .5 * width_;
	const bool is_up_vec_ok = std::abs( up_.dot( intersect_vec ) ) <= .5 * height_;

	if( is_right_vec_ok && is_up_vec_ok )
	{
		return IntersectDescr( param, intersect, normal_, ray.getDir(), this );
	}

	return IntersectDescr( this );
}
Пример #3
0
/**
 * Intersect a Ray with a plane defined by the 4 coefficients Ax + By + Cz + D = 0.
 * A,B,C are the plane normal
 */
bool planeIntersect(const Ray& r, const float *plane, PointF& intersection) {
    Normal normal(plane[0], plane[1], plane[2]);
    
    const PointF& rp = r.getPos();
    float dotNormalRayDir = Math::dot3(normal, r.getDir());
    
    // Is the ray perpendicular to the plane's normal?
    if (fabs(dotNormalRayDir) < PLANE_INTERSECTION_THRESHOLD) {
        return false;
    }
    
    // Determine which side of the plane the point is on
    float distFromPlane = Math::dot3(normal, rp) + plane[3];
    float t = distFromPlane/dotNormalRayDir;
    
    // > 0 if ray and normal are in the same direction and
    // the ray is on the normal side of the plane or
    // If the ray and normal point in opposite directions and
    // the ray is not on the normal side of the plane
    if (t > 0) {
        return false;
    }
    
    intersection = Math::vec3AXPlusB(r.getDir(), -t, r.getPos());
    return true;
}
Пример #4
0
//(r⃗ ·r⃗)t2 +2r⃗ ·(r⃗o −cen⃗ter)t+(r⃗o −cen⃗ter)·(r⃗o −cen⃗ter)−R2 =0
bool Sphere::intersect(const Ray& r, const float tmin, float &t_max){
	float t0, t1; // solutions for t if the ray intersects

    // analytic solution
	Vector3D L = r.getOrigin() - center;
	// std::cout << "L " << L << std::endl;
	float a = r.getDir().dot(r.getDir());
	// std::cout << "a " << a << std::endl;
	float b = 2 * r.getDir().dot(L);
	// std::cout << "b " << b << std::endl;
	float c = L.dot(L) - (radius * radius ) ;
	// std::cout << "c " << c << std::endl;

	if (!solveQuadratic(a, b, c, t0, t1)) return false;

	if (t0 > t1) std::swap(t0, t1);
	if (t0 < 0) {
	    t0 = t1; // if t0 is negative, let's use t1 instead
	    if (t0 < 0) 
	    	return false; // both t0 and t1 are negative
	}
	t_max = t0;

	return true;

}
Пример #5
0
bool intersect_search(Ray ray, Triangle* trig, int nTriangles, PoI* poi)
{
	float min_hit = 99999;
	int count = 0;
	float t_hit;
	for (count = 0; count < nTriangles; count ++)
	{
		Triangle t = trig[count];
		//t.scale(2, 1, 1); //scale by x-axis by 2
		

		bool hit = t.hit(ray, &t_hit);
		if (hit && t_hit < min_hit)
		{
			min_hit = t_hit;
			poi->setCollision(ray.getDir() * min_hit + ray.getPos());
			poi->setColor(t.kd);
			Vector myNorm = t.getNormal();
			//if normal faces the wrong way, then needs to do soemthing about it
        	//cos(angle) = dot_product / (a.len * b.len)
        	float cosine = myNorm.Vdot(ray.getDir()) / (myNorm.getMag() * ray.getDir().getMag());
        	if (cosine < 0)
        	{
       			myNorm = myNorm * -1;
        	}
			poi->setNormal(t.getNormal());
		}
	}
	if (min_hit != 99999)
	{
		return true;
	}
	return false;
}
Пример #6
0
Intersect Sphere::intersect(Ray r) {
    Intersect::Intersect ret = *new Intersect::Intersect();
    std::vector<float> d = r.getDir();
    std::vector<float> e = r.getEye();
    std::vector<float> eminusp(3);
    eminusp[0] = e[0] - position[0];
    eminusp[1] = e[1] - position[1];
    eminusp[2] = e[2] - position[2];
    float ddotd = d[0]*d[0]+d[1]*d[1]+d[2]*d[2];
    float empdot = eminusp[0]*eminusp[0] + eminusp[1]*eminusp[1] + eminusp[2]*eminusp[2];
    float ddoteminusp = d[0]*eminusp[0] + d[1]*eminusp[1] + d[2]*eminusp[2];
    float discriminant = sqrt(ddoteminusp * ddoteminusp - ddotd*(empdot - radius*radius));
    if (discriminant >= 0) {
        ret.setHit(true);
        float scalar = -1.0f;
        float * scale = &scalar;
        std::vector<float> scaled(3);
        scaled = vScale(-1, d);
        //scaled[0] = d[0]*(-1);
        //scaled[1] = d[1]*(-1);
        //scaled[2] = d[2]*(-1);
        float sdotemp = scaled[0]*eminusp[0] + scaled[1]*eminusp[1] + scaled[2]*eminusp[2];
        ret.setPoint(r.project((sdotemp+discriminant)/ddotd));
    }
    return ret;
}
Пример #7
0
  bool Sphere::checkRay (const Ray& ray, worldUnit& range, Vector& dist) const
  {
    dist = position.diff(ray.getStart());

    worldUnit a = ray.getDir().dotProduct(dist);

    auto squareLength = dist.dotProduct();
    worldUnit D = squareRadius - squareLength + a * a;

    //There is no intersection with sphere if D < 0
    if (D < 0.f)
    {
      return false;
    }

    worldUnit t = SQRT(D);

    if (squareLength >= squareRadius)
    { //We are outside sphere
      a -= t;
    }
    else
    { //We are inside sphere
      a += t;
    }

    if ( (a > 0.0f) && (a < range))
    {
      range = a;
      return true;
    }

    return false;
  }
RGB SubsurfacePathtracer::subsurface(RayIntersection* p_intersection, Ray *p_ray) {

	int SSS_SAMPLES = 30;
	RGB color;
	float absFactor = 0.01f;

	for(int i = 0; i < SSS_SAMPLES; i++) {
		RGB sampleColor;
		Ray ray = p_intersection->object->getShader()->getSubsurfaceSampledRay(p_intersection->object, p_intersection->point, p_intersection->normal, p_ray->getDir(), p_intersection->uv);
		RayIntersection intersection;
		
		//test any intersection (for inner occulsion)
		if(ray.nearestIntersection(scene->getObjects(), scene->getObjectCount(), &intersection)) {

			if(intersection.normal.dot(ray.getDir()) > 0) {
				sampleColor = p_intersection->object->getShader()->getDiffuseIrradiance(intersection.object, intersection.point, intersection.normal, intersection.uv, ray.getDir(), scene);
				
				float absortion = 1 - (intersection.dist * absFactor);

				if(absortion < 0) {
					absortion = 0;
				}

				//printf("%f\n", sampleColor.r);

				sampleColor = sampleColor * absortion;
				color = color + sampleColor;
			}
		}
	}

	color = color / (float)SSS_SAMPLES;

	return color;
}
Пример #9
0
Intersect Triangle::intersect(Ray r) {
	Intersect::Intersect ret = *new Intersect::Intersect();
	float a = v1.getX() - v2.getX();
	float b = v1.getY() - v2.getY();
	float c = v1.getZ() - v2.getZ();
	float d = v1.getX() - v3.getX();
	float e = v1.getY() - v3.getY();
	float f = v1.getZ() - v3.getZ();
	float g = r.getDir().at(0);
	float h = r.getDir().at(1);
	float i = r.getDir().at(2);
	float j = v1.getX() - r.getEye().at(0);
	float k = v1.getY() - r.getEye().at(1);
	float l = v1.getZ() - r.getEye().at(2);
	float eiminushf = e*i - h*f;
	float gfminusdi = g*f - d*i;
	float dhminuseg = d*h - e*g;
	float akminusjb = a*k - j*b;
	float jcminusal = j*c - a*l;
	float blminuskc = b*l - k*c;
	float m = a*(eiminushf) + b*(gfminusdi) + c*(dhminuseg);
	float beta = (j*(eiminushf) + k*(gfminusdi) + l*(dhminuseg))/m;
	if (beta < 0) {return ret;}
	float gamma = (i*(akminusjb) + h*(jcminusal) + g*(blminuskc))/m;
	if (gamma < 0 || beta+gamma > 1) {return ret;}
	float t = (-1)*(f*(akminusjb) + e*(jcminusal) + d*(blminuskc))/m;
	std::vector<float> p;
	
	std::vector<float> vec1 = v1.toVec();
	std::vector<float> vec2 = v2.toVec();
	std::vector<float> vec3 = v3.toVec();
	std::vector<float> sub1 = vSub(&vec2, &vec1);
	std::vector<float> sub2 = vSub(&vec3, &vec1);
	std::vector<float> scaled1 = vScale(&beta, &sub1);
	std::vector<float> scaled2 = vScale(&gamma, &sub2);
	std::vector<float> added1 = vAdd(&vec1, &scaled1);
	p = vAdd(&added1, &scaled2);
	
	ret.setPoint(p);
	
	return ret;
}
Пример #10
0
Intersect Triangle::intersect(Ray r) {
    Intersect::Intersect ret = *new Intersect::Intersect();
    float a = v1.getX() - v2.getX();
    float b = v1.getY() - v2.getY();
    float c = v1.getZ() - v2.getZ();
    float d = v1.getX() - v3.getX();
    float e = v1.getY() - v3.getY();
    float f = v1.getZ() - v3.getZ();
    float g = r.getDir().at(0);
    float h = r.getDir().at(1);
    float i = r.getDir().at(2);
    float j = v1.getX() - r.getEye().at(0);
    float k = v1.getY() - r.getEye().at(1);
    float l = v1.getZ() - r.getEye().at(2);
    float eiminushf = e*i - h*f;
    float gfminusdi = g*f - d*i;
    float dhminuseg = d*h - e*g;
    float akminusjb = a*k - j*b;
    float jcminusal = j*c - a*l;
    float blminuskc = b*l - k*c;
    float m = a*(eiminushf) + b*(gfminusdi) + c*(dhminuseg);
    float beta = (j*(eiminushf) + k*(gfminusdi) + l*(dhminuseg))/m;
    if (beta < 0) {
        return ret;
    }
    float gamma = (i*(akminusjb) + h*(jcminusal) + g*(blminuskc))/m;
    if (gamma < 0 || beta+gamma > 1) {
        return ret;
    }
    float t = (-1)*(f*(akminusjb) + e*(jcminusal) + d*(blminuskc))/m;
    std::vector<float> p(3);
    std::vector<float> vec1 = v1.toVec();
    std::vector<float> vec2 = v2.toVec();
    std::vector<float> vec3 = v3.toVec();
    p[0] = vec1[0] + (vec2[0] - vec1[0])*beta + (vec3[0] - vec1[0])*gamma;
    p[1] = vec1[1] + (vec2[1] - vec1[1])*beta + (vec3[1] - vec1[1])*gamma;
    p[2] = vec1[2] + (vec2[2] - vec1[2])*beta + (vec3[2] - vec1[2])*gamma;
    ret.setPoint(vec1);

    return ret;
}
HitInfo Sphere::intersection(const Ray & ray){
	double a = Vector(ray.getDir()).dot(Vector(ray.getDir()));
	double b = 2*Vector(ray.getStart()).dot(ray.getDir());
	double c = Vector(ray.getStart()).dot(Vector(ray.getStart()))-1;

	double discr = pow(b,2) - 4*a*c;

	double t1 =(-b-sqrt(discr))/(2*a);
	double t2 =(-b+sqrt(discr))/(2*a);
	double t = t2;

	if (t1<t2){
		if(t1 >= 0){
			t = t1;
		}
	}

	Point intersect = ray.getPoint(t);

	return HitInfo(t, intersect, mtrl, Vector(intersect));
}
Пример #12
0
/** Cast transmitted ray
 ** @param ray incoming ray
 ** @param pt intersection point
 ** @param normal normal of pt
 ** @param ior2 index of refraction of the object
 ** @return transmitted ray
 **/
Ray transmit(Ray ray, Vec pt, Vec normal, float ior1, float ior2){
  Vec r = ray.getDir();
  float alpha = ior1 / ior2;
  float c1 = normal.dot(r) * -1;
  float c2 = sqrt(1 - pow(alpha,2) * (1 - pow(c1,2)));
  Vec v = r * alpha + normal * (c1 * alpha - c2);
  Ray t(pt, v, 0, 9999, TransmittedRay);
  if (debugMode) {
    printf("transmitted ray origin: "); t.getOrig().print();
    printf("transmitted ray direction: "); t.getDir().print();
  }
  return t;
}
Пример #13
0
bool Sphere::intersect(const Ray& ray, RaySurfIntersection& res)const{
    res.shp = NULL;

    //Transform ray to object space
    const Ray rOb = w2o(ray);

    const Vector o = Vector(rOb.getOrigin().x, rOb.getOrigin().y, rOb.getOrigin().z);
    const Vector d = rOb.getDir();
    const float A = d.dot(d);
    const float B = 2.0f * (d.dot(o));
    const float C = o.dot(o) - (r * r);


    struct MathUtils::QuadraticEqnRes<float> slv =
        MathUtils::solveQuadratic<float>(A, B, C);
    float tHitFinal = 0.0f; //After the below code this will eventually be set to
    //the first hit point in front of the camera
    if(slv.solCount == 0){
        return false;
    }else if(slv.solCount == 1){
        tHitFinal = slv.sol1;
        if(tHitFinal < 0.0f){
            //No solutions in front of camera
            return false;
        }
    }else{ //2 solutions
        //Find smallest t value that is > 0.0f
        if(slv.sol1 < 0.0f && slv.sol2 < 0.0f){
            //No solutions in front of camera
            return false;
        }else{
            //At least one hit in front of camera
            slv.sol1 = slv.sol1 < 0.0f ? Constants::MAX_FLOAT_VAL : slv.sol1;
            slv.sol2 = slv.sol2 < 0.0f ? Constants::MAX_FLOAT_VAL : slv.sol2;
            tHitFinal = std::min<float>(slv.sol1, slv.sol2);
        }
    }

    //Make sure hit is in front of camera
    Assert(tHitFinal >= 0.0f);

    res.tHit = tHitFinal;
    res.locWS = ray(res.tHit);
    Vector normalVecAtHit = res.locWS - o2w(Point(0.0f,0.0f,0.0f));
    res.n = normalVecAtHit.getNormalized();
    res.shp = this;
    return true;
}
Пример #14
0
CIsect Plane::intersect(const Ray& ray)
{
	float angle = dot(mNormal, ray.getDir());
	if (fabs(angle) < FLOAT_ZERO) 
	{
		return CIsect(false);
	}
	float t = (-(dot(ray.getOrg(), mNormal) + mD) / angle);
	if (t > 0.f)
	{
		CIsect res(true, t, this, getNormal(ray, t));
		res.Dst.push_back(t);
		res.InsideIntervals.push_back(Span(t, t));
		return res;
	}
	return CIsect(false);
}
Пример #15
0
void Collide::raySphereCollide(const Body * ray_, const Body * sphere_)
{
	Ray *ray = (Ray*)ray_;
	Sphere *sphere = (Sphere*)sphere_;
	Vector3 vec = ray->getStart() - sphere->getCenter();
	setCollide(true);
	setDistance(0.0f);
	float fB = vec.Dot(ray->getDir());
	float fC = vec.Dot(vec) - sphere->getRadius()*sphere->getRadius();
	if (fC > 0.0f && fB > 0.0f)
		setCollide(false);
	float fDisc = fB*fB - fC;
	if (fDisc < 0.0f)
		setCollide(false);

	// compute the response vectors
	Vector3 responseObject1 = ray_->getCenter()- sphere_->getCenter();
	Vector3 responseObject2 = sphere_->getCenter() - ray_->getCenter();
	setResponseObject1(responseObject1);
	setResponseObject2(responseObject2);
}
Пример #16
0
bool Tri::intersectP(Ray& ray) {
  t = (glm::dot(a, planeNormal) - glm::dot(ray.getPos(), planeNormal)) /
    glm::dot(ray.getDir(), planeNormal);
  if (t > 0) { return true; }
  else { return false; }
}
Пример #17
0
Color Scene::shade(Intersection isect, Ray r, int level) {
    if (!isect.hits()) {
	return bgColor;
    }
    real eps;
    if (r.in()) {
	eps = 0.00001;
    } else {
	eps = -0.00001;
    }
  
    Texture *txt = isect.object()->getTexture();
    Point isectPt = r.pointOn(isect.t());
  
    Color curColor(0.0,0.0,0.0);
    Color specular(0,0,0);
    Color diffuse(0,0,0);
    Color shadowAmt(1,1,1);
  
    for (LightList::iterator lt_iter = lights.begin();
	 lt_iter != lights.end();
	 ++lt_iter) {

	Vector specL((*lt_iter)->location()-isectPt);
	Vector specV(cam.getLocation()-isectPt);
	Vector specHj((specL+specV)*(1.0/((specL+specV).length())));

	Ray shade_ray = (*lt_iter)->getRayTo(r.pointOn(isect.t()+ eps));

	++shadow_rays_cast;
	Intersection tempI = rtrace(shade_ray, true, isect.object());
	if (tempI.hits()) {
	    if (level>0) {
		shadowAmt -= shade(tempI, shade_ray, level-1);
	    } else {
		shadowAmt = Color(0.0,0.0,0.0);
	    }
	}

	specular += (*lt_iter)->intensity()*std::pow(specHj.dot(isect.normal()), txt->n());
	diffuse += (*lt_iter)->intensity()*shade_ray.getDir().dot(isect.normal());
    }
    shadowAmt *= 1.0/real(lights.size());
  
    Color reflective(0.0,0.0,0.0,0.0);
    if ((level>0)
	&& (txt->kr().intensity()>0.01)) {
	++reflective_rays_cast;
	Ray tempRay(r.pointOn(isect.t()+eps),
		    r.getDir()
		    - 2.0
		    * (r.getDir().dot(isect.normal()))
		    * isect.normal());
	reflective = shade(rtrace(tempRay), tempRay, level-1);
    }
  
    Color refractive(0.0,0.0,0.0);
    if ((level>0)
	&& (txt->kt().intensity()>0.01)) {
	real eta;
	if (r.in()) {
	    eta = 1.0/txt->ior();
	} else {
	    eta = txt->ior();
	}
	real ci;
	if (r.in()) {
	    ci = (r.getDir().dot(-1.0*isect.normal()));
	} else {
	    ci = (r.getDir().dot(isect.normal()));
	}
	real costt = 1.0 - (eta*eta) * (1.0-ci*ci);
  
	if (costt<0.0) {
	    refractive = Color(0,0,0);
	} else {
	    ++refractive_rays_cast;
	    Ray tempRay(r.pointOn(isect.t()+eps),
			((eta*ci-std::sqrt(costt))*((r.in()?-1.0:1.0)*isect.normal())
			 - (eta*r.getDir())),
			!r.in());
	    refractive = shade(rtrace(tempRay, isect.object()), tempRay, level-1);

	}
    }

    curColor +=
	txt->ka()
	+ (txt->kd()*diffuse
	   + txt->ks()*specular
	   + txt->kr()*reflective
	   + txt->kt()*refractive)
	* shadowAmt;

    return curColor.clamp();
}
Пример #18
0
Intersection Scene::rtrace(Ray r, bool computeNorm, Object *curObj) {
    ++rays_cast;
    Intersection bestIsect(9e99, false);
    size_t xi, yi, zi;
    int signx, signy, signz;
    int exy,exz,ezy;
  
    int rdx = int(std::floor(r.getDir().normal().i()*x_max));
    int rdy = int(std::floor(r.getDir().normal().j()*y_max));
    int rdz = int(std::floor(r.getDir().normal().k()*z_max));
  
    int absRdx(std::abs(rdx));
    int absRdy(std::abs(rdy));
    int absRdz(std::abs(rdz));
  
    getIdxOfPoint(r.getOrigin().x(),
		  r.getOrigin().y(),
		  r.getOrigin().z(),
		  xi, yi, zi);

    exy = rdy-rdx;
    exz = rdz-rdx;
    ezy = rdy-rdz;

    signx=1;
    if (rdx<0.0)
	signx=-1;
  
    signy=1;
    if (rdy<0.0)
	signy=-1;
  
    signz=1;
    if (rdz < 0.0)
	signz=-1;
    while ((xi<width)
	   && (yi<height)
	   && (zi<depth)
	   && (xi>=0)
	   && (yi>=0)
	   && (zi>=0)) {
	bestIsect = theGrid[xi][yi][zi]->intersect(r,
						   computeNorm,
						   &intersection_tests,
						   &intersections);
	if (bestIsect.hits()
	    && (bestIsect.object()!=curObj)
	    && bestIsect.getGridEntry()==theGrid[xi][yi][zi]) {
	    return bestIsect;
	}
	if (exy<0) {
	    // Not y adjacent
	    if (exz <0) {
		// X adjacent
		xi  +=  signx;
		exy += absRdy;
		exz += absRdz;
	    } else {
		// Z adjacent
		zi  +=  signz;
		exz -= absRdx;
		ezy += absRdy;  // Changed from ezy
	    }
	} else {
	    // Possibly y adjacent
	    if (ezy < 0) {
		// Z adjacent
		zi  +=  signz;
		exz -= absRdx;
		ezy += absRdy;
	    } else {
		// Y adjacent
		yi  +=  signy;
		exy -= absRdx;
		ezy -= absRdz;
	    }
	}
    }
    return bestIsect;
}
Пример #19
0
/** Ray Tracer
 ** @param ray the ray to be traced
 ** @param depth recursion depth
 ** @return color value
 **/
Vec trace(Ray ray, int depth){
  if (debugMode) {
    printf("\nrecursion = %d\n", depth);
    printf("ray origin = "); ray.getOrig().print();
    printf("ray direction = "); ray.getDir().print();
  }
  if (depth == 0) return black; // return background color
  
  Vec color, local, reflected, transmitted;
  Vec pt, normal;
  float tClosest = ray.getTmax(); // set dis to a maximum value
  Shape *ObjPtr = NULL; // set the Obj pointer to null
  
  // look for intersection point for each object in the scene
  bool inside = false;
  for (ShapeIter its = scene.shapes.begin(); its != scene.shapes.end(); its++) {
    if ((*its) == ray.ObjPtr) continue;
    float t;
    
    if ((*its)->getType() == sphere) {
      Sphere *shape = dynamic_cast<Sphere*>(*its);
      if (shape->intersect(ray, t)) {
        if (t < tClosest && t > ray.getTmin()) {
          inside = (shape->intersect(ray, t) == -1) ? true : false;
          tClosest = t; // update tClosest
          ObjPtr = (*its); // set ObjPtr to point to the object
        }
      }
    } else if((*its)->getType() == polyhedron){
      Polyhedron *shape = dynamic_cast<Polyhedron*>(*its);
      if (shape->intersect(ray, t)) {
        if (t < tClosest && t > ray.getTmin()) {
          tClosest = t; 
          ObjPtr = (*its);
        }
      }
    } else if((*its)->getType() == triangleMesh){
      TriangleMesh *shape = dynamic_cast<TriangleMesh*>(*its);
      if (shape->intersect(ray, t)) {
        if (t < tClosest && t > ray.getTmin()) {
          tClosest = t;
          ObjPtr = (*its); 
        }
      }
    }
  }
  
  
  if (ObjPtr != NULL) {
    SurFinish appearance = ObjPtr->getSurFin();
    float Kr = appearance.reflective; // reflectivity
    float Kt = appearance.transmission; // transmitivity
    float ior_obj = appearance.ior; // index of refraction
    
    pt = ray.calcDest(tClosest); // set the pos variable pt to the nearest intersection point
    normal = ObjPtr->calcNorm(pt); // normal of intersection point
    if (normal.dot(ray.getDir()) > 0) normal = normal * (-1);
    if(inside) normal = normal * (-1);
    local.setVec(0.0, 0.0, 0.0); // set local shading to black 
    
    // for each light source in the scene
    for (LightIter itl = scene.lights.begin(); itl != scene.lights.end(); itl++){
      Light *LightPtr = (*itl); // pointer to the light source
      
      // calculate local shading according to Phong model
      local = local + phongModel(pt, normal, LightPtr, ObjPtr, ray) / scene.numL;
      
      // Recursively cast reflected and refracted rays
      if (Kr > 0) { // specular reflective
        Ray refl = reflect(ray, pt, normal);
        refl.ObjPtr = ObjPtr;
        reflected = reflected + trace(refl, depth-1)/scene.numL;
      }
      if (Kt > 0 && ior_obj != 0) { // translucent
        Ray refr = transmit(ray, pt, normal, ior_air, ior_obj);
        refr.ObjPtr = ObjPtr;
        transmitted = transmitted + trace(refr, depth-1)/scene.numL;
      }
    }
    
    // update light color
    color.setVec(local + reflected * Kr + transmitted * Kt);
  }
  // if no intersection
  else {
    color.setVec(background); // set color to background color
  }
  
  if (debugMode == 1) {
    printf("\nPrinting information for depth = %d\n", depth);
    Vec orig = ray.getOrig();
    Vec dir = ray.getDir();
    printf("RAY:\n");
    printf("origin = %f %f %f\n", orig.x, orig.y, orig.z);
    printf("direction = %f %f %f\n", dir.x, dir.y, dir.z);
    printf("INTERSECTION:\n");
    printf("intersection point = %f %f %f\n", pt.x, pt.y, pt.z);
    printf("normal = %f %f %f\n", normal.x, normal.y, normal.z);
    printf("LIGHT VISIBILITY:\n");
    printf("local shading = %f %f %f\n", local.x, local.y, local.z);
    printf("reflected shading = %f %f %f\n", reflected.x, reflected.y, reflected.z);
    printf("transmitted shading = %f %f %f\n", transmitted.x, transmitted.y, transmitted.z);
    printf("PIXEL COLOR:\n");
    printf("color = %f %f %f\n", color.x, color.y, color.z);
    printf("\n");
  }
  
  return color;
}
Пример #20
0
Spectrum IntegratorHelpers::radianceDirect(const Scene* scene, const Ray& ray,
    const RaySurfIntersection& hit, const IntegratorHelpers::SpectralStrategy& ss)
{
    //Memory for output spectrum
    //TODO: Remove all dynamic memory allocations from rendering inner loop
    //...for now this is still in here for east of implementation
    float* buf = new float[ss.numSpectralSamples];
    for(int i = 0; i < ss.numSpectralSamples; i++){
        buf[i] = 0.0f;
    }

    //Return spectrum
    Spectrum retColor(buf, ss.nmMin, ss.nmMax, ss.nmStep, ss.numSpectralSamples);

    //Create relavent params
    const Vector omega_o(-ray.getDir());
    const Vector vecN(hit.n.x, hit.n.y, hit.n.z);
    const AccelStructure* geom = scene->getSceneGeom(); //Scene acceleration structure
    const bool isEmitter = hit.shp->isEmitter();
    const Point hitLocWS(hit.locWS);

    //Determine the maximum number of light samples we will make
    //and allocate this memory OUTSIDE of the light loop
    int NLightSampsMax = -1;
    for(size_t i = 0; i < scene->getNumLights(); i++){
        NLightSampsMax = std::max<int>(
            NLightSampsMax,
            scene->getLight(i)->getRecNumVisibilitySamples());
    }
    Point* samps = new Point[NLightSampsMax];

    //Process each light individually
    for(size_t i = 0; i < scene->getNumLights(); i++){
        Light* l = scene->getLight(i);

        //Skip sampling the light itself if the geometry is an emitter
        if(isEmitter && hit.shp->getEmitter() == l){
            continue;
        }

        //Sample the light source potentially many times
        const int N = l->getRecNumVisibilitySamples();
        l->getSamples(samps, N);


        //Loop over all light samples
        const float invNumSamps = 1.0f / float(N);
        for(int j = 0; j < N; j++){

            //Check if we can see the light
            VisibilityTester visTest(hitLocWS, samps[j], l->getGeom(),
                geom, DFLT_RAY_MOVE_EPSILON);
            //visTest.r is a ray to the light from hitLocWS

            //Get the incident radiance from the light at the hit location
            Spectrum L = l->sampleIncidentRadiance(hitLocWS, vecN, samps[j]);
            //TODO: "continue" here if the spectrum is black...is this any faster?


            //If we saw the light, add its contribution
            bool sawLight = visTest.visible(NULL);
            if(sawLight){
                //Vector to light
                const Vector omega_i(visTest.r.getDir());

                //Geomety term (solid angle)
                const Vector Nvec = hit.n;
                const float G = GeomUtils::absDotProd(omega_i, Nvec);
                //Technically, the above G is not correct! TODO
                //const Vector v = (samps[j] - hitLocWS);
                //const float r = v.magnitude();
                //const float G = GeomUtils::absDotProd(omega_i, Nvec) / (r*r);

                //Transform vectors into local BRDF frame
                /*
                Vector w_i_brdfCS = BRDFCoordHelpers::worldCSToBrdfCS(omega_i,
                   Nvec, hit.tangent, Nvec.cross(hit.tangent));
                Vector w_o_brdfCS = BRDFCoordHelpers::worldCSToBrdfCS(omega_o,
                   Nvec, hit.tangent, Nvec.cross(hit.tangent));
                */

                //Evaluate BRDF term at each wavelength
                float nm = ss.nmMin;
                BRDF* brdf = hit.shp->getBRDF();
                for(int i = 0; i < ss.numSpectralSamples; i++){
                    buf[i] = brdf->f(omega_i, omega_o, nm);
                    //buf[i] = brdf->f(w_i_brdfCS, w_o_brdfCS, nm);
                    nm += ss.nmStep;
                }

                //Create a "spectrum" of BRDF values
                Spectrum brdfSpec(buf, ss.nmMin, ss.nmMax, ss.nmStep,
                    ss.numSpectralSamples);

                //Light term
                retColor = retColor + (L * G * invNumSamps * brdfSpec);
            }
        }
    }

    //All done!
    delete[] samps; samps = NULL;
    delete[] buf; buf = NULL;
    return retColor;
}
RGB SubsurfacePathtracer::trace(Ray p_ray, Vector3d cameraPos, int p_depth) {

	RGB radiance(0,0,0);
	RGB localRadiance(0,0,0);
	RayIntersection nearestRayInt;
	p_depth++;
	
	bool intersected = false;

	if(scene->kdTree == NULL) {
		intersected = p_ray.nearestIntersection(scene->getObjects(), scene->getObjectCount(), &nearestRayInt);
	} else {
		intersected = scene->kdTree->nearestIntersection(&p_ray, &nearestRayInt);
	}

	if(intersected) {
		if(!(nearestRayInt.object->getShader()->isLight() && p_ray.getDiffuse())) {
			//local ilumination:
			Vector3d viewVec = cameraPos - nearestRayInt.point;
			viewVec.normalize();
			localRadiance = nearestRayInt.object->getShader()->getDiffuseRadiance(nearestRayInt.object, nearestRayInt.point, nearestRayInt.normal, nearestRayInt.uv, viewVec, scene);

			radiance = localRadiance;

			if(nearestRayInt.object->getShader()->hasSubsurface()) {
				radiance = radiance + subsurface(&nearestRayInt, &p_ray);
				//return subsurface(&nearestRayInt, &p_ray);
			}

			int outVecsCount = 0;
			RGB indirectRadiance;

			if(p_depth == 1) {
				for(int i = 0; i < 5; i++) {
					if(p_depth < maxDepth) {
						Ray outRays[10];
						RGB values[10];
						outVecsCount = nearestRayInt.object->getShader()->getBRDFSampledRays(nearestRayInt.object, nearestRayInt.point, nearestRayInt.normal, nearestRayInt.uv, viewVec, p_ray.getDir(), outRays, values);
						
						for(int s = 0; s < outVecsCount; s++) {
							Ray ray = outRays[s];
							indirectRadiance = indirectRadiance + (trace(ray, cameraPos, p_depth) * values[s]) ;
						}
					}

					indirectRadiance;
				}

				indirectRadiance = indirectRadiance / 5;
			} else {
				if(p_depth < maxDepth) {
					Ray outRays[10];
					RGB values[10];
					outVecsCount = nearestRayInt.object->getShader()->getBRDFSampledRays(nearestRayInt.object, nearestRayInt.point, nearestRayInt.normal, nearestRayInt.uv, viewVec, p_ray.getDir(), outRays, values);
					
					for(int s = 0; s < outVecsCount; s++) {
						Ray ray = outRays[s];
						indirectRadiance = indirectRadiance + (trace(ray, cameraPos, p_depth) * values[s]) ;
					}
				}	
			}

			if(outVecsCount > 0) {
				radiance =  radiance + indirectRadiance;
			}

		}
	} else if(scene->getBackground() != NULL) {
		radiance = scene->getBackground()->getRadianceAt(p_ray.getPoint(), p_ray.getPointAt(FAR_AWAY));
	}

	return radiance;
}
Пример #22
0
float Object::bound_box(Ray ray) const
{
	float t, thit = HUGEREAL;
	float xmin, xmax, ymin, ymax, zmin, zmax;
	Vector Q;
	Vector i(1,0,0), j(0,1,0), k(0,0,1);
	Vector base = ray.getBase();
	Vector dir = ray.getDir();
	
	xmin = this->vmin.x;
	xmax = this->vmax.x;
	ymin = this->vmin.y;
	ymax = this->vmax.y;
	zmin = this->vmin.z;
	zmax = this->vmax.z;

	t = ray.intersect_plane(i, this->vmax);
	if(t > 0.001)
	{
		Q = base + dir.scale(t);

		if( (ymin <= Q.y) && (Q.y <= ymax) && (zmin <= Q.z) && (Q.z <= zmax) )
		{
			thit = t;
			return thit;
		}
	}
	t = ray.intersect_plane(i.scale(-1), this->vmin);
	if(t > 0.001)
	{
		Q = base + dir.scale(t);
		
		if( (ymin <= Q.y) && (Q.y <= ymax) && (zmin <= Q.z) && (Q.z <= zmax) )
		{
			thit = t;
			return thit;
		}
	}
	t = ray.intersect_plane(j, this->vmax);
	if(t > 0.001)
	{
		Q = base + dir.scale(t);
				
		if( (xmin <= Q.x) && (Q.x <= xmax) && (zmin <= Q.z) && (Q.z <= zmax) )
		{
			thit = t;
			return thit;
		}
	}
	t = ray.intersect_plane(j.scale(-1), this->vmin);
	if(t > 0.001)
	{
		Q = base + dir.scale(t);
		
		if( (xmin <= Q.x) && (Q.x <= xmax) && (zmin <= Q.z) && (Q.z <= zmax) )
		{
			thit = t;
			return thit;
		}
	}
	t = ray.intersect_plane(k, this->vmax);
	if(t > 0.001)
	{
		Q = base + dir.scale(t);
		
		if( (xmin <= Q.x) && (Q.x <= xmax) && (ymin <= Q.y) && (Q.y <= ymax) )
		{
			thit = t;
			return thit;
		}
	}
	t = ray.intersect_plane(k.scale(-1), this->vmin);
	if(t > 0.001)
	{
		Q = base + dir.scale(t);
		
		if( (xmin <= Q.x) && (Q.x <= xmax) && (ymin <= Q.y) && (Q.y <= ymax) )
		{
			thit = t;
			return thit;
		}
	}
	return thit;
}
Пример #23
0
CIsect Cylinder::intersect(const Ray& ray)
{
  const Vec3D& origin    = ray.getOrg();
  const Vec3D& direction = ray.getDir();

	const Vec3D& CO = origin - mBottom;
	
	const Vec3D& u = direction - mAxis * (dot(direction, mAxis));
	const Vec3D& v = CO - mAxis * (dot(CO, mAxis));

	CIsect res = CIsect(true);
	// Let a, b and c be coefficients of some square equation
	const float a = dot(u, u);
	float root		= 0.f;
	float closest = -1.f;
	float rayExit = -1.f;
	if (fabs(a) > FLOAT_ZERO)
	{
		const float b = 2 * dot(u, v);
		const float c = dot(v, v) - mRadius2;

		float D = b * b - 4 * a * c;

		// Complete miss
		if (D < 0.f) 
		{
			return CIsect(false);
		}

		D = sqrtf(D);

		// Calculate roots and take closest
		float denom = 1 / (2 * a);

		root = (-b - D) * denom;
		if (root >= 0.f)
		{
			Vec3D toBottom = ray.apply(root) - mBottom;
			Vec3D toTop		= ray.apply(root) - mTop;
			if (dot(mAxis, toBottom) > 0.f && dot(mAxis, toTop) < 0.f)
			{
				res.Dst.push_back(root);
				closest = root;
			}
		}
		root = (-b + D) * denom;
		if (root > 0.f)
		{
			// Awful copy paste :(
			Vec3D toBottom = ray.apply(root) - mBottom;
			Vec3D toTop		= ray.apply(root) - mTop;
			if (dot(mAxis, toBottom) > 0.f && dot(mAxis, toTop) < 0.f)
			{
				res.Dst.push_back(root);
				if (closest < 0.f)
				{
					root = closest;
				}
				else if (root < closest)
				{
					rayExit = closest;
					closest = root;
				}
				else
				{
					rayExit = root;
				}
			}
		}
	}
	
	// dot(va, (q - p1)) = 0   t = (dot(va, p1) - dot(va, p)) / dot(va, v)

	// Find intersection with caps
	// Bottom one
	float axisToDir = dot(mAxis, direction);

	if (fabs(axisToDir) < FLOAT_ZERO)
	{
		if (closest > 0.f)
		{
			res.Distance = closest;
			res.Object   = this;
			res.Normal	 = getNormal(ray, closest);
			if (rayExit < 0.f) 
			{
				res.InsideIntervals.push_back(Span(0.f, closest));
				res.Dst.insert(res.Dst.begin(), 0.f);
			}
			else
			{
				res.InsideIntervals.push_back(Span(closest, rayExit));
			}
			return res;
		}

		return CIsect(false);
	}

	float axisToOrg		= dot(mAxis, origin);
	//root = (dot(mAxis, mBottom) - axisToOrg) / axisToDir;
	float CODotAxis = dot(CO, mAxis);
	root = -CODotAxis / axisToDir;
	if (root > 0.f)
	{
		Vec3D toBottom = ray.apply(root) - mBottom;
		if (dot(toBottom, toBottom) < mRadius2)
		{
			res.Dst.push_back(root);
			// Awful copy paste :(
			if (closest < 0.f)
			{
				closest = root;
			}
			else if (root < closest)
			{
				rayExit = closest;
				closest = root;
			}
			else
			{
				rayExit = root;
			}
		}
	}
	// Top one
	//root = (dot(mAxis, mTop) - axisToOrg) / axisToDir;
	float CTDotAxis = dot(origin - mTop, -mAxis);
	root = CTDotAxis / axisToDir;
	if (root > 0.f)
	{
		// Awful copy paste :(
		Vec3D toTop = ray.apply(root) - mTop;
		if (dot(toTop, toTop) < mRadius2)
		{
			res.Dst.push_back(root);
			if (closest < 0.f)
			{
				closest = root;
			}
			else if (root < closest)
			{
				rayExit = closest;
				closest = root;
			}
			else
			{
				rayExit = root;
			}
		}
	}
	
	if (closest >= 0.f)
	{
		res.Distance = closest;
		res.Object   = this;
		res.Normal	 = getNormal(ray, closest);
		if (rayExit < 0.f) 
		{
			res.InsideIntervals.push_back(Span(0.f, closest));
			res.Dst.insert(res.Dst.begin(), 0.f);
		}
		else
		{
			res.InsideIntervals.push_back(Span(closest, rayExit));
		}
		return res;
	}
  return CIsect(false);
}
Пример #24
0
bool Tracer::scatterSpecular(const IntersectDescr& node, Ray& ray) const
{
	ray = Ray( node.point_, ray.getDir().reflect( node.normal_ ) );
	return true;
}
Пример #25
0
float Object::Shadow_box(Ray ray) const	// Bounding box function for shadows
{
	float t, thit = 1.0;
	float xmin, xmax, ymin, ymax, zmin, zmax;
	Vector Q;
	Vector i(1,0,0), j(0,1,0), k(0,0,1);
	Vector base = ray.getBase();
	Vector dir = ray.getDir();
	
	xmin = this->vmin.x;
	xmax = this->vmax.x;
	ymin = this->vmin.y;
	ymax = this->vmax.y;
	zmin = this->vmin.z;
	zmax = this->vmax.z;

	t = ray.intersect_plane(i, this->vmax);
	if( (t > 0.0) && (t < 1.0) )
	{
		Q = base + dir.scale(t);

		if( (ymin <= Q.y) && (Q.y <= ymax) && (zmin <= Q.z) && (Q.z <= zmax) )
		{
			thit = t;
			return thit;
		}
	}
	t = ray.intersect_plane(i.scale(-1), this->vmin);
	if( (t > 0.0) && (t < 1.0) )
	{
		Q = base + dir.scale(t);
		
		if( (ymin <= Q.y) && (Q.y <= ymax) && (zmin <= Q.z) && (Q.z <= zmax) )
		{
			thit = t;
			return thit;
		}
	}
	t = ray.intersect_plane(j, this->vmax);
	if( (t > 0.0) && (t < 1.0) )
	{
		Q = base + dir.scale(t);
				
		if( (xmin <= Q.x) && (Q.x <= xmax) && (zmin <= Q.z) && (Q.z <= zmax) )
		{
			thit = t;
			return thit;
		}
	}
	t = ray.intersect_plane(j.scale(-1), this->vmin);
	if( (t > 0.0) && (t < 1.0) )
	{
		Q = base + dir.scale(t);
		
		if( (xmin <= Q.x) && (Q.x <= xmax) && (zmin <= Q.z) && (Q.z <= zmax) )
		{
			thit = t;
			return thit;
		}
	}
	t = ray.intersect_plane(k, this->vmax);
	if( (t > 0.0) && (t < 1.0) )
	{
		Q = base + dir.scale(t);
		
		if( (xmin <= Q.x) && (Q.x <= xmax) && (ymin <= Q.y) && (Q.y <= ymax) )
		{
			thit = t;
			return thit;
		}
	}
	t = ray.intersect_plane(k.scale(-1), this->vmin);
	if( (t > 0.0) && (t < 1.0) )
	{
		Q = base + dir.scale(t);
		
		if( (xmin <= Q.x) && (Q.x <= xmax) && (ymin <= Q.y) && (Q.y <= ymax) )
		{
			thit = t;
			return thit;
		}
	}
	return thit;
}