Пример #1
0
bool UVSphere::shadowHit(const Ray& r, precision tMin, precision tMax, precision time) const{
    Vector3 temp = r.origin() - center;
    
    double a = dot(r.direction(), r.direction());
    double b = 2 * dot(r.direction(), temp);
    double c = dot(temp, temp) - radius * radius;
    
    double discriminant = b * b - 4 * a * c;
    
    //First check to see if the ray intersects the sphere
    if(discriminant > 0){
        discriminant = sqrt(discriminant);
        double t = (- b - discriminant) / (2 * a);
        
        //Now check for a valid interval
        if(t < tMin)
            t = (- b + discriminant) / (2 * a);
        if(t < tMin || t > tMax)
            return false;
        
        //We have a valid hit
        return true;
    }
    return false;
}
Пример #2
0
Option<Vec2> sb::Intersection::get(const Ray& a, const Polygon& b) {
	Option<Vec2> pt = nullptr;
	Option<bool> inside = nullptr;
	float t = std::numeric_limits<float>::max();
	auto eCount = b.edgeCount();
	for (ptrdiff_t i = 0; i < eCount; i++) {
		const auto ed = b.edge(i);
		auto r = Intersection::get(a, ed);
		if (!r)
			continue;
		if (aeq(r.value(), ed.pointA())) {
			if (!inside.hasValue())
				inside = test(b, a.m_point);

			if (!inside.value() && !(-a.direction()).isBetween(b.normal(i), b.normal(i - 1)))
				continue;
		}
		else if (aeq(r.value(), ed.pointB())) {
			if (!inside.hasValue())
				inside = test(b, a.m_point);

			if (!inside.value() && !(-a.direction()).isBetween(b.normal(i), b.normal(i + 1)))
				continue;
		}
		auto u = a.computeT(r.value());
		if (u < t) {
			t = u;
			pt = r;
		}
	}
	return pt;
}
Пример #3
0
void App::playSculpture(const Ray& playRay) {
  int maxDistance = 0;
  int startIndex = g_sampleWindowIndex;
  for (auto piece : m_sonicSculpturePieces) {
    const shared_ptr<AudioSample>& sample = piece->getAudioSampleFromRay(playRay);
    if (sample->buffer.size() > 0) {
        maxDistance = max(maxDistance, (int)ceil(sample->buffer.size() / 512.0f));
        Synthesizer::global->queueSound(sample);
        m_lastInterestingEventTime = System::time();
    }
  }
  if (maxDistance > 0) {
    PlayPlane pp;
    pp.direction = playRay.direction();
    pp.origin = playRay.origin();
    pp.beginWindowIndex = startIndex;
    pp.endWindowIndex = startIndex + maxDistance;

    Vector3 zAxis = -playRay.direction();
	Vector3 xAxis;
	if (abs(zAxis.dot(Vector3::unitY())) < 0.9f) {
	  xAxis = zAxis.unitCross(Vector3::unitY());
	} else {
	  xAxis = zAxis.unitCross(Vector3::unitX());
	}
	Vector3 yAxis = zAxis.cross(xAxis);

	pp.frame = CFrame(Matrix3::fromColumns(xAxis, yAxis, zAxis), pp.origin);


    m_playPlanes.append(pp);
  }
}
Пример #4
0
bool Metal::scatter(const Ray& r_in, const HitRecord& record, vec3& attenuation, Ray& scattered) const
{
	vec3 reflected = reflect( glm::normalize(r_in.direction()), record.normal );
	scattered = Ray(record.point, reflected + roughness * randomInUnitSphere());
	attenuation = Color3(m_color);
	return (glm::dot(scattered.direction(), record.normal) > 0);
}
Пример #5
0
bool Metal::scatter(const Ray& r_in, const HitRecord& record, vec3& attenuation, Ray& scattered) const
{
	vec3 reflected = reflect( glm::normalize(r_in.direction()), record.normal );
	scattered = Ray(record.point, reflected + roughness * random_in_unit_sphere());
	attenuation = albedo;
	return (dot(scattered.direction(), record.normal) > 0);
}
Пример #6
0
Option<Vec2> Intersection::get(const Ray& a, const Circle& b) {
	const auto f = a.point() - b.center();
	float _a = dot(a.direction(), a.direction());
	float _b = 2 * dot(f, a.direction());
	float _c = dot(f, f) - b.radius() * b.radius();
	float d = _b * _b - 4 * _a * _c;
	if (d <= 0) //if d == 0, this means that the ray is tangent to the circle... we don't wanna this Intersection...
		return nullptr;
	else {
		d = sqrtf(d);
		float t1 = (-_b - d) / (2 * _a);
		float t2 = (-_b + d) / (2 * _a);
		if (t1 >= 0) {
			if (t2 >= 0) {
				if (t1 < t2)
					return a.sampleAlongRay(t1);
				else
					return a.sampleAlongRay(t2);
			}
			else {
				return a.sampleAlongRay(t1);
			}
		}
		else {
			if (t2 >= 0)
				return a.sampleAlongRay(t2);
			else
				return nullptr;
		}
	}
}
void RayTracer::traceOnePixel(int x, int y, int threadID) {

    //used for constructing viewport
    Vector2 tmp(m_settings.width, m_settings.height);

    Ray primaryRay;

    // If one ray per pixel: (kinda debugging mode with blue color for places with no surfel hit
    if (m_settings.raysPerPixel == 1){
        //Get the primary ray from the pixel x,y
        primaryRay = m_camera->worldRay(x + 0.5f, y + 0.5f, Rect2D(tmp));
        
        //Get the first surfel hit.
        //Can't call L_i unfortunately because we want the blue background for debugging
        const shared_ptr<Surfel>& s = RayTracer::castRay(primaryRay, finf(), 0);

        //If there is a surfel hit, get the direct illumination value and apply to the pixel
        if (s){
            //Call L_scatteredDirect to get direct illumination. Invert primaryRay to get the direction for incident light
            m_image->set(Point2int32(x,y), L_o(s, -primaryRay.direction(), m_settings.recursiveBounces, *(m_rnd[threadID])));
        } else{
            //Set the pixels with no surfel hit. Include this line so we could make it a specific color for debug purposes.
            m_image->set(Point2int32(x,y), Color3(0,0,1));
        }
    } else {
        Radiance3 L(0,0,0);
        //If more than one ray, randomly generate required number of rays within the pixel
        for (int i = 0; i < m_settings.raysPerPixel; ++i){
            primaryRay = m_camera->worldRay(x + m_rnd[threadID]->uniform(), y + m_rnd[threadID]->uniform(), Rect2D(tmp));
            L += L_i(primaryRay.origin(), primaryRay.direction(), m_settings.recursiveBounces, *(m_rnd[threadID]));
        }
        m_image->set(Point2int32(x,y), L/m_settings.raysPerPixel);
    }
}
Пример #8
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;
}
Пример #9
0
bool UVSphere::intersect(const Ray& r, float tmin, float tmax, float time, HitRecord& record)const{
  Vec temp = r.origin() - center;
  float a = r.direction().dot(r.direction());
  float b = 2 * r.direction().dot(temp);
  float c = temp.dot(temp) - radius * radius;

  float discriminant = b*b - 4*a*c;
  if(discriminant > 0){
    discriminant = sqrt(discriminant);
    float t = (-b -discriminant) /(2*a);
    if(t < tmin) t = (-b + discriminant) / (2*a);
    if(t < tmin || t > tmax) return false;
    
    record.t = t;
    record.hit_p = r.origin() + r.direction() * t;
    record.reflect = reflectionCoef;
    record.transparency = refractionCoef;
    Vec n = record.normal = normalize(r.origin() + r.direction()*t - center);
    
    //calculate UV coordinates
    float theta = acos(n.y);
    float phi = atan2(n.z, n.x);
    if(phi < 0) phi += M_PI * 2;
    record.uv = Vec(phi/(2* M_PI), (M_PI - theta)/M_PI, 0);
    record.hit_tex = tex;
    return true;
  }
  return false;
}
Пример #10
0
Color Scene::traceNoDepthMod(Ray &ray, bool &hitSomething, Color &Oi) const
{
    if (ray.traceDepth == maxTraceDetph)
    {
        hitSomething = false;
        return Color(all_zero());
    }
    ray.traceDepth++;

    const float prevMaxT = ray.maxT;

    IntersectionInfo info;
    const Geometry *nearestObj = bvhRoot->findClosest(ray, info);

    if (!nearestObj)
    {
        hitSomething = false;
        return Color(all_zero());
    }

    hitSomething = true;

    // Object doesn't have shader, make it appear even for blind people!
    if (!nearestObj->hasShader())
    {
        Oi = Color(sse::all_one);
        return Color(1, 0, 1);
    }

    CompiledShader shader(nearestObj->getShader(), true);
    shader.setCurrentDepth(ray.traceDepth);
    shader.setRTVarValueByIndex(CompiledShader::Cs, info.Cs);
    shader.setRTVarValueByIndex(CompiledShader::Os, info.Os);
    shader.setRTVarValueByIndex(CompiledShader::P, Vector3(info.P));
    shader.setRTVarValueByIndex(CompiledShader::N, info.N);
    shader.setRTVarValueByIndex(CompiledShader::Ng, info.Ng);
    shader.setRTVarValueByIndex(CompiledShader::s, info.s);
    shader.setRTVarValueByIndex(CompiledShader::t, info.t);
    shader.setRTVarValueByIndex(CompiledShader::I, Vector3((cam.WorldToCamN * ray.direction()).get128()));
    shader.exec();

    Color Ci, thisOi;
    shader.getOutput(Ci, thisOi);
    Oi += thisOi;

    if (isOpaque(Oi))
        return Ci;

    ray.origin = info.P + (ray.direction() * 0.001f);
    ray.maxT = prevMaxT - ray.maxT;

    bool nextHit;
    const Color nextColor = traceNoDepthMod(ray, nextHit, Oi);

    if (!nextHit)
        return Ci;

    return Ci + mulPerElem((Vector3(1) - thisOi), nextColor);
}
Пример #11
0
	Intersection<Plane> Plane::find_intersection(const Ray& r) const
	{
		if (_span == Span::XY)
			return find_intersection_for_components(r.origin().z, r.direction().z);
		if (_span == Span::XZ)
			return find_intersection_for_components(r.origin().y, r.direction().y);
		return find_intersection_for_components(r.origin().x, r.direction().x);
	}
Пример #12
0
bool BVH::intersect(Ray &ray, IntersectionPtr isect)
{
    if (nodes.empty())
        return false;

    bool hit = false;
    Vector directionDivider;
    directionDivider << 1.0f/ray.direction(0), 1.0f/ray.direction(1), 1.0f/ray.direction(2);
    bool directionIsNegative[3] = {directionDivider(0) < 0,
                                   directionDivider(1) < 0,
                                   directionDivider(2) < 0};

    // follow the ray through the tree's nodes to find intersections
    unsigned int toVisitOffset = 0;
    unsigned int nodeNumber = 0;
    unsigned int toVisit[64];
    while(true)
    {
        const LinearNodePtr node = nodes[nodeNumber];
        // check ray against the node
        if (intersectSlabs(node->bbox, ray, directionDivider, directionIsNegative))
        {
            if (node->numberPrimitives > 0)
            {
                // proceed to intersect ray with primitives in leaf
                for (int i = 0; i < node->numberPrimitives; ++i) {
                    if (objects[node->primOffset+i]->intersect(ray, isect))
                        hit = true;
                }
                if (toVisitOffset == 0)
                    break;
                nodeNumber = toVisit[--toVisitOffset];
            }
            else
            {
                // put distant node on stack, advance to next node
                if (directionIsNegative[node->axis])
                {
                    toVisit[toVisitOffset++] = nodeNumber + 1;
                    nodeNumber = node->secondChildOffset;
                }
                else
                {
                    toVisit[toVisitOffset++] = node->secondChildOffset;
                    nodeNumber = nodeNumber + 1;
                }
            }
        }
        else
        {
            if (toVisitOffset == 0)
                break;
            nodeNumber = toVisit[--toVisitOffset];
        }
    }

    return hit;
}
Пример #13
0
bool Cone::intersect(const Ray &ray, double &t)
{
    Ray localRay = ray * m_worldToObject;

    double dx = localRay.direction().x();
    double dy = localRay.direction().y();
    double dz = localRay.direction().z();
    double ox = localRay.origin().x();
    double oy = localRay.origin().y();
    double oz = localRay.origin().z();

    double a = dx * dx - dy * dy + dz * dz;
    double b = 2.0 * (dx * ox - dy * oy + dy + dz * oz);
    double c = ox * ox - oy * oy + 2 * oy + oz * oz - 1.0;

    double t1, t2, t3;

    // Calculate bottom disc t
    t3 = -oy / dy;
    double discX, discZ;
    discX = ox + dx * t3;
    discZ = oz + dz * t3;
    if (discX * discX + discZ * discZ > 1.0)
        t3 = -1.0;  // Didn't hit the disc

    if (MathUtils::solveQuadratic(a, b, c, t1, t2)) {
        // Set cone tees to negative if the hit point y isn't between 0 and 1
        double hy = oy + dy * t1;
        if (!(hy >= 0.0 && hy <= 1.0))
            t1 = -1.0;

        hy = oy + dy * t2;
        if (!(hy >= 0.0 && hy <= 1.0))
            t2 = -1.0;

        bool hit = false; t = std::numeric_limits<double>::max();
        if (t1 > MathUtils::dEpsilon) {
            hit = true;
            t = t1;
        }
        if (t2 < t && t2 > MathUtils::dEpsilon) {
            hit = true;
            t = t2;
        }
        if (t3 < t && t3 > MathUtils::dEpsilon) {
            hit = true;
            t = t3;
        }

        return hit;
    }

    // Can't hit bottom disc without hitting the infinite cone too
    return false;
}
Пример #14
0
bool World::intersect(Ray & r, double & bestT, vec3 &outn, MaterialInfo &outm) {

    bestT = numeric_limits<double>::infinity();

    if (_DEBUG_INTERSECT1
            && abs(r.direction()[0] - 0.146734796) < 0.05
            && abs(r.direction()[1] + 0.146734796) < 0.05
            && abs(r.direction()[2] + 0.978231971) < 0.05)
        int i = 0; //debug statement, stops at a ray aimed at the center of one of the spheres in threespheres.scd
    if (_DEBUG_INTERSECT2
            && abs(r.direction()[0] + 0.114776942) < 0.02
            && abs(r.direction()[1] - 0.0619082097) < 0.02
            && abs(r.direction()[2] + 0.991460351) < 0.02)
        int i = 0; // debug statement, stops at a ray aimed for the left eye of the bunny in ellipsoids.scd


    if (_ASSIGNMENT <= 5 || _FINAL_PROJ) {
        // iterate through spheres to see if any of them are intersected
        for (vector<Sphere>::iterator sphere = _spheres.begin(); sphere != _spheres.end(); sphere++) {
            double intersect = sphere->intersect(r);
            if (intersect < bestT) {
                //cout << "intersect found" << endl;
                bestT = intersect;
                //cout << intersect << " ";
                vec4 pos = r.getPos(intersect);
                //cout << pos[0] << "," << pos[1] << "," << pos[2] << " ";
                outn = vec3(sphere->calculateNormal(pos), VW);
                //cout << outn[0] << "," << outn[1] << "," << outn[2] << endl;
                outm = sphere->getMaterial();
                //AS4 stuff
                //if (sphere == _spheres.begin()) {
                //	outm.k[MAT_KSM] *= ksmMod;
                //	outm.k[MAT_KSP] *= kspMod;
                //	if (outm.k[MAT_KSP] < 1.0) outm.k[MAT_KSP] = 1.0;
                //}
            }
        }

        for (vector<Cube>::iterator cube = _cubes.begin(); cube != _cubes.end(); cube++) {
            double intersect = cube->intersect(r);
            if (intersect < bestT) {
                bestT = intersect;
                vec4 pos = r.getPos(intersect);
                outn = vec3(cube->calculateNormal(pos), VW);
                outm = cube->getMaterial();
                outm.color = cube->calculateColor(pos);
            }
        }

        return bestT < numeric_limits<double>::infinity();
    }
    else
        return _bb->intersect(r, bestT, outn, outm);
}
Пример #15
0
Ray Raytracer::make_reflection_ray(const Vector3d &normal,
                                 const Ray &ray,
                                 const Point3d &intersection)
{
    Ray reflection(intersection,
                   normalize(
                       vector_subtract(ray.direction(),
                           scalar_multiply(normal,
                               2 * dot_product(ray.direction(), normal)))));
     return reflection;
}
bool MaterialOneSideSpecular::OutputRay( const Ray& incident, DifferentialGeometry* dg, RandomDeviate& rand, Ray* outputRay ) const
{
	if( dg->shapeFrontSide && !isFront.getValue() )	return ( false );
	if( !dg->shapeFrontSide && isFront.getValue() )	return ( false );


	double randomNumber = rand.RandomDouble();
	if ( randomNumber >= reflectivity.getValue()  ) return false;//return 0;

	//Compute reflected ray (local coordinates )
	outputRay->origin = dg->point;

	NormalVector normalVector;
	double sSlope = sigmaSlope.getValue() / 1000;
	if( sSlope > 0.0 )
	{
		NormalVector errorNormal;
		if ( distribution.getValue() == 0 )
		{
			double phi = gc::TwoPi * rand.RandomDouble();
			double theta = sSlope * rand.RandomDouble();

			errorNormal.x = sin( theta ) * sin( phi ) ;
			errorNormal.y = cos( theta );
			errorNormal.z = sin( theta ) * cos( phi );
		 }
		 else if (distribution.getValue() == 1 )
		 {
			 errorNormal.x = sSlope * tgf::AlternateBoxMuller( rand );
			 errorNormal.y = 1.0;
			 errorNormal.z = sSlope * tgf::AlternateBoxMuller( rand );

		 }
		Vector3D r = dg->normal;
		Vector3D s = Normalize( dg->dpdu );
		Vector3D t = Normalize( dg->dpdv );
		Transform trasform( s.x, s.y, s.z, 0.0,
								r.x, r.y, r.z, 0.0,
								t.x, t.y, t.z, 0.0,
								0.0, 0.0, 0.0, 1.0);

		NormalVector normalDirection = trasform.GetInverse()( errorNormal );
		normalVector = Normalize( normalDirection );
	}
	else
	{
		normalVector = dg->normal;
	}

	double cosTheta = DotProduct( normalVector, incident.direction() );
	outputRay->setDirection( Normalize( incident.direction() - 2.0 * normalVector * cosTheta ) );
	return true;

}
Пример #17
0
/**
 *  slab method: http://www.siggraph.org/education/materials/HyperGraph/raytrace/rtinter3.htm   
 *	http://www.cs.utah.edu/~awilliam/box/box.pdf
 */
bool cgray::rt::AABB::intersect(const Ray & ray, IntersectInfo & info)
{
	// r.dir is unit direction vector of ray
	Vector3f dir_frac(0,0,0);

	if (-M_EPSILON < ray.direction()[0] && ray.direction()[0] < M_EPSILON) {
		if (min_[0] > ray.origin()[0] || ray.origin()[0] > max_[0]) {
			return false;
		}
	}

	if (-M_EPSILON < ray.direction()[1] && ray.direction()[1] < M_EPSILON) {
		if (min_[1] > ray.origin()[1] || ray.origin()[1] > max_[1]) {
			return false;
		}
	}

	if (-M_EPSILON < ray.direction()[2] && ray.direction()[2] < M_EPSILON) {
		if (min_[2] > ray.origin()[2] || ray.origin()[2] > max_[2]) {
			return false;
		}
	}

	dir_frac[0] = 1.0f / ray.direction()[0];
	dir_frac[1] = 1.0f / ray.direction()[1];
	dir_frac[2] = 1.0f / ray.direction()[2];
	// lb is the corner of AABB with minimal coordinates - left bottom, rt is maximal corner
	// r.org is origin of ray
	float t1 = (min_[0] - ray.origin()[0])*dir_frac[0];
	float t2 = (max_[0] - ray.origin()[0])*dir_frac[0];
	float t3 = (min_[1] - ray.origin()[1])*dir_frac[1];
	float t4 = (max_[1] - ray.origin()[1])*dir_frac[1];
	float t5 = (min_[2] - ray.origin()[2])*dir_frac[2];
	float t6 = (max_[2] - ray.origin()[2])*dir_frac[2];

	float tmin = std::max(std::max(std::min(t1, t2), std::min(t3, t4)), std::min(t5, t6));
	float tmax = std::min(std::min(std::max(t1, t2), std::max(t3, t4)), std::max(t5, t6));

	// if tmax < 0, ray (line) is intersecting AABB, but whole AABB is behing us
	if (tmax < 0) {
		return false;
	}

	// if tmin > tmax, ray doesn't intersect AABB
	if (tmin > tmax) {
		return false;
	}

	// set intersection info
	info.hit_point = ray.origin() + ray.direction() * tmin;
	info.hit_shape = std::make_shared<AABB>(*this);
	info.is_hit = true;
	info.dist = tmin;
	info.normal = getNormal(info.hit_point);
	info.ray = ray;

	return true;
}
Пример #18
0
// returns true if it has collisions inside aabb
    bool KDTree::intersect(KDTreeNode *child, const Ray &ray, KDTreeHitInfo& hit, vec3 startPoint) {
        bool collision = false;
        if (child->isLeaf()) {
            for (auto& node : child->objects) {
                if (node.intersectRay(ray, hit)){
                    vec3 collisionPos = hit.collisionPoint;
                    collision = child->aabb.contains(collisionPos);
                }
            }
        } else {
            float directionDelta = ray.direction()[child->splittingAxis];

            if (directionDelta < 0 && ray.origin()[child->splittingAxis] < child->splittingPlane) {
                // only consider left child
                collision = intersect(child->leftChild,  ray, hit, startPoint);
            } else if (directionDelta > 0 && ray.origin()[child->splittingAxis] > child->splittingPlane) {
                // only consider right child
                collision = intersect(child->rightChild, ray, hit, startPoint);
            } else {
                // collision with splitting plane
                if (directionDelta > 0) {
                    // if direction is from min to max (left to right)
                    collision = intersect(child->leftChild, ray, hit, startPoint);
                    if (!collision) {
                        float fNear, fFar;
                        int aNear, aFar;
                        if (child->rightChild->aabb.intersect(ray, fNear, fFar,aNear, aFar)) {
                            vec3 splitPlaneIntersect = ray.origin() + ray.direction() * fNear;
                            Ray newRay{splitPlaneIntersect, ray.direction()};
                            collision = intersect(child->rightChild, newRay, hit, startPoint);
                        }
                    }
                } else {
                    // if direction is from min to max (left to right)
                    collision = intersect(child->rightChild, ray, hit, startPoint);
                    if (!collision) {
                        float fNear, fFar;
                        int aNear, aFar;
                        if (child->leftChild->aabb.intersect(ray, fNear, fFar,aNear, aFar)) {
                            vec3 splitPlaneIntersect = ray.origin() + ray.direction() * fNear;
                            Ray newRay{splitPlaneIntersect, ray.direction()};
                            collision = intersect(child->leftChild, newRay, hit, startPoint);
                        }
                    }
                }
            }
        }

        return collision;
    }
Пример #19
0
	bool Triangle::intersect(const Ray& ray, float& distance, float baryCoord[3]) const {
		static const float EPS = 1e-5f;

		// See RTR2 ch. 13.7 for the algorithm.

		const Vector3& e1 = edge01();
		const Vector3& e2 = edge02();
		const Vector3 p(ray.direction().cross(e2));
		const float a = e1.dot(p);

		if (abs(a) < EPS) {
			// Determinant is ill-conditioned; abort early
			return false;
		}

		const float f = 1.0f / a;
		const Vector3 s(ray.origin() - vertex(0));
		const float u = f * s.dot(p);

		if ((u < 0.0f) || (u > 1.0f)) {
			// We hit the plane of the m_geometry, but outside the m_geometry
			return false;
		}

		const Vector3 q(s.cross(e1));
		const float v = f * ray.direction().dot(q);

		if ((v < 0.0f) || ((u + v) > 1.0f)) {
			// We hit the plane of the triangle, but outside the triangle
			return false;
		}

		const float t = f * e2.dot(q);

		if ((t > 0.0f) && (t < distance)) {
			// This is a new hit, closer than the previous one
			distance = t;

			baryCoord[0] = 1.0 - u - v;
			baryCoord[1] = u;
			baryCoord[2] = v;

			return true;
		}
		else {
			// This hit is after the previous hit, so ignore it
			return false;
		}
	}
Пример #20
0
bool Cylinder::intersectCap(const Ray &localRay, double &t)
{
    if (localRay.direction().y() < 0.0)
        t = (0.5 * m_length - localRay.origin().y()) / localRay.direction().y();
    else if (localRay.direction().y() > 0.0)
        t = (-0.5 * m_length - localRay.origin().y()) / localRay.direction().y();
    else
        return false;

    QVector4D p = localRay.along(t);
    if (p.x() * p.x() + p.z() * p.z() < m_rSq)
        return true;

    return false;
}
Пример #21
0
Файл: Sphere.cpp Проект: 9gix/cg
bool Sphere::hit( const Ray &r, double tmin, double tmax, SurfaceHitRecord &rec ) const 
{
	//***********************************************
    //*********** WRITE YOUR CODE HERE **************
    //***********************************************

    Vector3d rayOrigin = r.origin() - center; // origin with respect to the sphere
    double a = 1;
    double b = 2 * dot(r.direction(), rayOrigin);
    double c = dot(rayOrigin, rayOrigin) - pow(radius, 2);
    double discriminant = pow(b, 2) - 4 * a * c;
    if (discriminant < 0) {
        return false;
    }

    double t1 = (-b + sqrt(discriminant)) / (2 * a);
    double t2 = (-b - sqrt(discriminant)) / (2 * a);
    double t0 = min(t1, t2);

    if (t0 < tmin || t0 > tmax) {
        return false;
    }

    rec.mat_ptr = matp;
    rec.p = r.pointAtParam(t0);
    rec.normal = (rec.p - center) / (rec.p - center).length();
    rec.t = t0;
    return true;
}
Пример #22
0
bool SceneNode::intersect(const Ray& ray, Intersection& i) const
{
  // Transform the ray from WCS->MCS for this node
  Ray r(m_invtrans * ray.origin(), m_invtrans * ray.direction());

  bool intersects = false;
  for(auto child : m_children)
  {
    Intersection j;
    if(child->intersect(r, j))
    {
      // We need to see if this intersection point is closer than the previous intersection point
      // If it is than replace the previous intersection
      if(std::isinf(i.q[0]) || std::isinf(i.q[1]) || std::isinf(i.q[2]) || (j.q-r.origin()).length() < (i.q-r.origin()).length()) i = j;
      intersects = true;
    }
  }

  // If intersection occurs than transform the intersection point and the normal from MCS->WCS
  // We have to convert the intersection point from MCS->WCS and the normal from MCS->WCS
  // Normals must be multiplied by the transpose of the inverse to throw away scaling (no translations either, but the normal is 
  // a vector and vectors can't be translated) but preserve rotation
  if(intersects)
  {
    i.q = m_trans * i.q;
    i.n = transNorm(m_invtrans, i.n);
  }
  
  return intersects;
}
Пример #23
0
Color3 Raytracer::shadeDirectBSDF(const SurfaceSample& intersector, const Ray& ray) const
{	
	Color3 lightContribution(0,0,0);
	for (int i = 0; i < _currentScene->lighting()->lightArray.length(); ++i)
	{
		GLight& light = _currentScene->lighting()->lightArray[i];
		const Point3& X = intersector.shadingLocation;
		const Point3& n = intersector.shadingNormal;
		const Vector3& diff = light.position.xyz() - X;
		const Vector3 w_i = diff.direction();
		const float distance = diff.length();
		const Vector3 w_eye = -ray.direction();
		const Power3& Phi = light.color.rgb();

		if (!isInSpotlight(light, w_i))
		{
			continue;
		}

		if (isInShadow(intersector, w_i, distance))
		{
			continue;
		}

		// power area
		const Color3& E_i = w_i.dot(n) * Phi / (4 * pif() * (distance*distance));

		const SuperBSDF::Ref bsdf = intersector.material->bsdf();
		const Color3& bsdfColor = bsdf->evaluate(intersector.shadingNormal, intersector.texCoord, w_i, w_eye).rgb();

		lightContribution += bsdfColor * E_i + intersector.emit;
	}

	return lightContribution;
}
Пример #24
0
Color3 Raytracer::shadePixel(const Tri::Intersector& intersector, const Ray& ray, int backwardBouncesLeft) const
{
	Color3 pixelColor;
	Vector3 position, normal;
	Vector2 texCoord;
	intersector.getResult(position, normal, texCoord);
	SurfaceSample surfaceSample(intersector);

	if (_settings._useSuperBSDF)
	{
		if(_settings._useDirectShading)
		{
			pixelColor = shadeDirectBSDF(surfaceSample, ray);
		}
		
		pixelColor += shadeSpecularBSDF(surfaceSample, -ray.direction(), backwardBouncesLeft);
		
		if (_settings._usePhotonMap)
		{
			pixelColor += shadeIndirectIllumination(surfaceSample);
		}
						
	}
	else
	{
		pixelColor = myShadePixel(intersector, ray, backwardBouncesLeft);
	}

	return pixelColor;
}
Пример #25
0
 bool Sphere::hit(Ray& ray, HitInfo* hitInfo)
 {
     if (!m_boundingBox.doesHit(ray)) {
         return false;
     }
     
     Vector3 dist = m_center - ray.origin();
     float b = ray.direction().dot(dist);
     float discriminant = m_radiusSq - dist.normSq() + b * b;
     if (discriminant < 0.0) {
         return false;
     }
     
     // two possible intersections
     float t = kNoHit;
     float t0 = b - sqrt(discriminant);
     float t1 = b + sqrt(discriminant);
     if (t0 > 0.0001) {
         t = t0;
     } else if (t1 > 0.0001) {
         t = t1;
     }
     
     Vector3 hitPosition = ray.pointAtDistance(t);
     Vector3 hitNormal = (hitPosition - m_center) * m_radiusInv;
     hitInfo->setDistance(t);
     hitInfo->setNormal(hitNormal);
     hitInfo->setMaterial(m_material);
     hitInfo->setPosition(hitPosition);
     hitInfo->setSurface(this);
     hitInfo->setRay(&ray);
     
     return true;
 }
Пример #26
0
std::tuple<bool, Ray> a4_reflect_perturbed(const Ray& reflected, const Vector3D& normal, double glossiness, const std::function<double()>& uniform)
{
  Vector3D r = reflected.direction();
  Vector3D na = -r;
  Vector3D U, V;

  // Get the basis vectors for the square of size <glossiness>x<glossiness>
  if(na[2] > na[0] && na[2] > na[1]) U = Vector3D(-na[1], na[0], 0.0);
  else if(na[1] > na[0]) U = Vector3D(-na[2], 0.0, na[0]);
  else U = Vector3D(0.0, -na[2], na[1]);
  U.normalized();

  V = na.cross(U).normalized();

  // Randomly generate a 2D point on the square
  double u = -(glossiness * 0.5) + uniform() * glossiness;
  double v = -(glossiness * 0.5) + uniform() * glossiness;

  // Use the 2D point and the basis vectors for the square to perturb the reflection ray to point to a location on the square
  Point3D rp = Point3D(r[0], r[1], r[2]) + u * U + v * V;

  // Set the new perturbed direction vector for the ray
  r = Vector3D(rp[0], rp[1], rp[2]);

  // Check if the perturbed ray is below the surface
  return std::tuple<bool, Ray>(normal.dot(r) < 0, Ray(reflected.origin(), r)); 
}
Пример #27
0
IntersectionPtrList Sphere::intersect( const Ray& ray ) const
{
	// Calculate if there is an intersection
	const Imath::V3f rayStart = ray.start();

	const float d = rayStart.x - m_centre.x;
	const float e = rayStart.y - m_centre.y;
	const float f = rayStart.z - m_centre.z;

	const Imath::V3f rayDir = ray.direction();
	const float a = 1;
	const float b = 2 * ( rayDir.x * d + rayDir.y * e + rayDir.z * f );
	const float c = ( d*d + e*e + f*f ) - m_radius*m_radius;

	const float determinant = b*b - 4 * a * c;

	if ( determinant < 0 )
	{
		return IntersectionPtrList();
	}

	// a is non-zero so no checks required
	const float intersectionDistancePlus = ( -b + sqrt( determinant ) ) / ( 2 * a );
	const float intersectionDistanceMinus = ( -b - sqrt( determinant ) ) / ( 2 * a );

	IntersectionPtrList intersections;

	// Minus distance should be closer then plus so put it in first
	intersections.push_back( new SphereIntersection( *this, ray, intersectionDistanceMinus ) );
	intersections.push_back( new SphereIntersection( *this, ray, intersectionDistancePlus ) ); 
	
	return intersections;
}
Пример #28
0
QVector4D Cylinder::surfaceNormal(const QVector4D &p, const Ray &ray)
{
    QVector4D lp = m_worldToObject * p;
    QMatrix4x4 a = m_worldToObject.transposed();
    a.setRow(3, QVector4D(0.0, 0.0, 0.0, 1.0));


    if (m_hasCaps && fabs(fabs(lp.y()) - m_length * 0.5) < MathUtils::dEpsilon) {
        // Return cap normal
        QVector4D n;
        if (lp.y() < 0.0)
            n = QVector4D(0.0, -1.0, 0.0, 0.0);
        else
            n = QVector4D(0.0, 1.0, 0.0, 0.0);
        return (a * n).normalized();
    } else {
        // calculate cylinder normal
        QVector4D o = QVector4D(0.0, lp.y(), 0.0, 1.0);
        QVector4D n = lp - o;
        n = a * n;

        QVector4D rd = -ray.direction();
        if (QVector4D::dotProduct(n, rd) < 0)
            return -n.normalized();
        else
            return n.normalized();
    }
}
Пример #29
0
real Renderable::transformRayLambdaWorldToModel(const Ray &ray, const real lambda) const
{
  this->updateTransforms();
  Vec3 model_direction = mTransformInv.transformVector(ray.direction());

  return lambda * model_direction.norm();
}
Пример #30
0
bool Cube::FindIntersection(const Ray& ray, double* t, Point3* point, Vector3* normal) const {
  const Point3& origin = ray.origin();
  const Vector3& direction = ray.direction();

  *t = std::numeric_limits<double>::max();

  for (int i = 0; i < 3; ++i) {
    if (direction[i] == 0)  // Ray is parallel to plane.
      continue;

    for (int j = -1; j <= 1; j += 2) {
      if (direction[i] * j > 0)  // Ray hits the back of the plane.
        continue;

      double s = (j - origin[i]) / direction[i];
      if (s >= kEpsilon && s < *t) {
        int k = (i + 1) % 3;
        double y = origin[k] + direction[k] * s;

        int l = (i + 2) % 3;
        double z = origin[l] + direction[l] * s;

        if (y >= -1 && y <= 1 && z >= -1 && z <= 1) {
          *t = s;
          *point = origin + direction * s;
          *normal = Vector3();
          (*normal)[i] = j;
        }
      }
    }
  }

  return *t != std::numeric_limits<double>::max();
}