Exemple #1
0
        GeometryRayTestResult Intersects(const AxisAlignedBox& Box, const Ray& Cast)
        {
            // Code in this function is based on the equivalent in Ogre
            Vector3 CastDir = Cast.GetNormal();
            Vector3 AbsoluteDir = CastDir;
            AbsoluteDir.X = MathTools::Abs( AbsoluteDir.X );
            AbsoluteDir.Y = MathTools::Abs( AbsoluteDir.Y );
            AbsoluteDir.Z = MathTools::Abs( AbsoluteDir.Z );

            // A small fixed sized constant time sorting algorithm for sorting the length of each axis.
            Whole MaxAxis = 0, MidAxis = 1, MinAxis = 2;
            if( AbsoluteDir[0] < AbsoluteDir[2] ) {
                MaxAxis = 2;
                MinAxis = 1;
            }else if( AbsoluteDir[1] < AbsoluteDir[MinAxis] ) {
                MidAxis = MinAxis;
                MinAxis = 1;
            }else if( AbsoluteDir[1] > AbsoluteDir[MaxAxis] ) {
                MidAxis = MaxAxis;
                MaxAxis = 1;
            }

            if(IsInside(Box,Cast.Origin))
            {
                Vector3 Intersects;
                Intersects[MinAxis] = 0;
                Intersects[MidAxis] = 0;
                Intersects[MaxAxis] = 1;
                /*Plane Side(Intersects,)
                if(CastDir[MaxAxis]>0)
                {

                }else{

                }
                return GeometryRayTestResult(true,Ray(,Vector3));*/
            }

            SegmentPosPair Distances(0,std::numeric_limits<Real>::infinity());

            ::CalculateAxis(MaxAxis,Cast,Box,Distances);
            if( AbsoluteDir[MidAxis] < std::numeric_limits<Real>::epsilon() ) {
                if( Cast.GetOrigin()[MidAxis] < Box.MinExt[MidAxis] || Cast.GetOrigin()[MidAxis] > Box.MaxExt[MidAxis] ||
                    Cast.GetOrigin()[MinAxis] < Box.MinExt[MinAxis] || Cast.GetOrigin()[MinAxis] > Box.MaxExt[MinAxis] )
                {
                    return GeometryRayTestResult(false,Ray());
                }
            }else{
                ::CalculateAxis(MidAxis,Cast,Box,Distances);
                if( AbsoluteDir[MinAxis] < std::numeric_limits<Real>::epsilon() ) {
                    if( Cast.GetOrigin()[MinAxis] < Box.MinExt[MinAxis] || Cast.GetOrigin()[MinAxis] > Box.MaxExt[MinAxis] ) {
                        return GeometryRayTestResult(false,Ray());
                    }
                }else{
                    ::CalculateAxis(MinAxis,Cast,Box,Distances);
                }
            }

            Ray Ret( Cast.GetOrigin() + (CastDir * Distances.first), Cast.GetOrigin() + (CastDir * Distances.second) );
            return GeometryRayTestResult(true,Ret);
        }
Exemple #2
0
bool parseRay(Ray &ray, TiXmlElement* config)
{
  ray.clear();
  ray.type = VisualSensor::RAY;

  TiXmlElement *horizontal = config->FirstChildElement("horizontal");
  if (horizontal)
  {
    const char* samples_char = horizontal->Attribute("samples");
    if (samples_char)
    {
      try
      {
        ray.horizontal_samples = boost::lexical_cast<unsigned int>(samples_char);
      }
      catch (boost::bad_lexical_cast &e)
      {
        logError("Ray horizontal samples [%s] is not a valid float: %s", samples_char, e.what());
        return false;
      }
    }

    const char* resolution_char = horizontal->Attribute("resolution");
    if (resolution_char)
    {
      try
      {
        ray.horizontal_resolution = boost::lexical_cast<double>(resolution_char);
      }
      catch (boost::bad_lexical_cast &e)
      {
        logError("Ray horizontal resolution [%s] is not a valid float: %s", resolution_char, e.what());
        return false;
      }
    }   
    
    const char* min_angle_char = horizontal->Attribute("min_angle");
    if (min_angle_char)
    {
      try
      {
        ray.horizontal_min_angle = boost::lexical_cast<double>(min_angle_char);
      }
      catch (boost::bad_lexical_cast &e)
      {
        logError("Ray horizontal min_angle [%s] is not a valid float: %s", min_angle_char, e.what());
        return false;
      }
    }

    const char* max_angle_char = horizontal->Attribute("max_angle");
    if (max_angle_char)
    {
      try
      {
        ray.horizontal_max_angle = boost::lexical_cast<double>(max_angle_char);
      }
      catch (boost::bad_lexical_cast &e)
      {
        logError("Ray horizontal max_angle [%s] is not a valid float: %s", max_angle_char, e.what());
        return false;
      }
    }
  }
  
  TiXmlElement *vertical = config->FirstChildElement("vertical");
  if (vertical)
  {
    const char* samples_char = vertical->Attribute("samples");
    if (samples_char)
    {
      try
      {
        ray.vertical_samples = boost::lexical_cast<unsigned int>(samples_char);
      }
      catch (boost::bad_lexical_cast &e)
      {
        logError("Ray vertical samples [%s] is not a valid float: %s", samples_char, e.what());
        return false;
      }
    }

    const char* resolution_char = vertical->Attribute("resolution");
    if (resolution_char)
    {
      try
      {
        ray.vertical_resolution = boost::lexical_cast<double>(resolution_char);
      }
      catch (boost::bad_lexical_cast &e)
      {
        logError("Ray vertical resolution [%s] is not a valid float: %s", resolution_char, e.what());
        return false;
      }
    }   
    
    const char* min_angle_char = vertical->Attribute("min_angle");
    if (min_angle_char)
    {
      try
      {
        ray.vertical_min_angle = boost::lexical_cast<double>(min_angle_char);
      }
      catch (boost::bad_lexical_cast &e)
      {
        logError("Ray vertical min_angle [%s] is not a valid float: %s", min_angle_char, e.what());
        return false;
      }
    }

    const char* max_angle_char = vertical->Attribute("max_angle");
    if (max_angle_char)
    {
      try
      {
        ray.vertical_max_angle = boost::lexical_cast<double>(max_angle_char);
      }
      catch (boost::bad_lexical_cast &e)
      {
        logError("Ray vertical max_angle [%s] is not a valid float: %s", max_angle_char, e.what());
        return false;
      }
    }
  }
  return false;
}
Exemple #3
0
    bool Sphere::hit(const Ray &ws_ray, float &thit,
                      std::shared_ptr<DifferentialGeometry> &dg) const {
      float phi;
      Point phit;

      //UNCOMMENT FOR BROKEN BB
      if(!mImpl->bb.hit(ws_ray))
        return false;

      // Transform the ray into object space
      Transform transform = worldToObjectSpace();
      Ray os_ray = transform(ws_ray);



      // Do ray-sphere intersection in object space
      // Compute quadratic sphere coefficients

      float A = os_ray.dir().x() * os_ray.dir().x() +
                os_ray.dir().y() * os_ray.dir().y() +
                os_ray.dir().z() * os_ray.dir().z();
      float B = 2.0 * (os_ray.dir().x() * os_ray.origin().x() +
                     os_ray.dir().y() * os_ray.origin().y() +
                     os_ray.dir().z() * os_ray.origin().z());
      float C = os_ray.origin().x() * os_ray.origin().x() +
                os_ray.origin().y() * os_ray.origin().y() +
                os_ray.origin().z() * os_ray.origin().z() -
                mImpl->radius * mImpl->radius;


      // Solve quadratic equation for t values
      float t0, t1;
      if (!mImpl->Quadratic(A,B,C, &t0, &t1)) return false;
      // compute intersection distance along ray
      if (t0 > os_ray.maxt() || t1 < os_ray.mint())
        return false;

      thit = t0;
      if (t0 < os_ray.mint()) {
        thit = t1;
        if (thit > os_ray.maxt()) return false;
      }


      // Compute sphere hit position and phi
      phit = os_ray(thit);

      if (phit.x() == 0.f && phit.y() == 0.f) phit.x(1e-5f * mImpl->radius);

      phi = atan2f(phit.y(), phit.x());

      if (phi < 0.) phi += 2.f*M_PI;

      // Test against clipping parameters
      if ((mImpl->zmin > -mImpl->radius && phit.z() < mImpl->zmin) ||
        (mImpl->zmax < mImpl->radius && phit.z() > mImpl->zmax) ||
         phi > mImpl->phiMax) {
           if (thit == t1) return false;
           thit = t1;

           if ((mImpl->zmin > -mImpl->radius && phit.z() < mImpl->zmin) ||
             (mImpl->zmax < mImpl->radius && phit.z() > mImpl->zmax) ||
             phi > mImpl->phiMax)
             return false;
         }

         // find parametric representation of sphere
         float u = phi/mImpl->phiMax;

         float theta = acosf(Clamp(phit.z()/mImpl->radius, -1.f, 1.f));

         float v = (theta - mImpl->thetaMin) / (mImpl->thetaMax - mImpl->thetaMin);
         float zradius = sqrtf(phit.x() * phit.x() + phit.y() * phit.y());
         float invzradius = 1.f / zradius;
         float cosphi = phit.x() * invzradius;
         float sinphi = phit.y() * invzradius;
         Vector dpdu(-mImpl->phiMax * phit.y(), mImpl->phiMax * phit.x(), 0);
         Vector dpdv = (mImpl->thetaMax - mImpl->thetaMin) *
                Vector(phit.z() * cosphi, phit.z() * sinphi,
                      -mImpl->radius * sinf(theta));

        Vector d2Pduu = -mImpl->phiMax * mImpl->phiMax * Vector(phit.x(), phit.y(), 0.0f);
        Vector d2Pduv = (mImpl->thetaMax - mImpl->thetaMin) * phit.z() * mImpl->phiMax * Vector(-sinphi, cosphi, 0.0f);
        Vector d2Pdvv = -(mImpl->thetaMax - mImpl->thetaMin) * (mImpl->thetaMax - mImpl->thetaMin) * Vector(phit.x(), phit.y(), phit.z());

        float E = dpdu.dot(dpdu);
        float F = dpdu.dot(dpdv);
        float G = dpdv.dot(dpdv);
        Vector N = dpdu.cross(dpdv).normalized();
        float e = N.dot(d2Pduu);
        float f = N.dot(d2Pduv);
        float g = N.dot(d2Pdvv);

        float invEGF2 = 1.f/(E * G - F * F);
        Normal dndu = Normal((f * F - e * G) * invEGF2 * dpdu +
                            (e * F - f * E) * invEGF2 * dpdv);
        Normal dndv = Normal((g * F - f * G) * invEGF2 * dpdu +
                            (f*F - g * E) * invEGF2 * dpdv);




      // if the ray intersects the sphere return true
      std::shared_ptr<DifferentialGeometry> dg_temp(new DifferentialGeometry(mImpl->o2w(os_ray(thit)),
                                mImpl->o2w(dpdu),
                                mImpl->o2w(dpdv),
                                mImpl->o2w(dndu),
                                mImpl->o2w(dndv),
                                u, v, this));
      dg_temp->dir = ws_ray.dir();
      dg = dg_temp;

       return true;

    }
    void DefaultZone::_findNodes( const Ray &t, 
							      PCZSceneNodeList &list, 
                                  PortalList &visitedPortals,
						 	      bool includeVisitors,
							      bool recurseThruPortals,
							      PCZSceneNode *exclude )
    {
		// if this zone has an enclosure, check against the enclosure AABB first
		if (mEnclosureNode)
		{
			std::pair<bool, Real> nsect = t.intersects(mEnclosureNode->_getWorldAABB());
			if (!nsect.first)
			{
				// AABB of zone does not intersect t, just return.
				return;
			}
		}

		// check nodes at home in this zone
	    PCZSceneNodeList::iterator it = mHomeNodeList.begin();
	    while ( it != mHomeNodeList.end() )
	    {
			PCZSceneNode * pczsn = *it;
			if ( pczsn != exclude )
			{
				// make sure node is not already in the list (might have been added in another
				// zone it was visiting)
				PCZSceneNodeList::iterator it2 = list.find(pczsn);
				if (it2 == list.end())
				{
					std::pair<bool, Real> nsect = t.intersects( pczsn -> _getWorldAABB() );
					if ( nsect.first )
					{
						list.insert( pczsn );
					}
				}
			}
		    ++it;
	    }

		if (includeVisitors)
		{
			// check visitor nodes
			PCZSceneNodeList::iterator iter = mVisitorNodeList.begin();
			while ( iter != mVisitorNodeList.end() )
			{
				PCZSceneNode * pczsn = *iter;
				if ( pczsn != exclude )
				{
					// make sure node is not already in the list (might have been added in another
					// zone it was visiting)
					PCZSceneNodeList::iterator it2 = list.find(pczsn);
					if (it2 == list.end())
					{
						std::pair<bool, Real> nsect = t.intersects( pczsn -> _getWorldAABB() );
						if ( nsect.first )
						{
							list.insert( pczsn );
						}
					}
				}
				++iter;
			}
		}

		// if asked to, recurse through portals
		if (recurseThruPortals)
		{
			PortalList::iterator pit = mPortals.begin();
			while ( pit != mPortals.end() )
			{
				Portal * portal = *pit;
				// check portal versus bounding box
				if (portal->intersects(t))
				{
					// make sure portal hasn't already been recursed through
					PortalList::iterator pit2 = std::find(visitedPortals.begin(), visitedPortals.end(), portal);
					if (pit2 == visitedPortals.end())
					{
						// save portal to the visitedPortals list
						visitedPortals.push_front(portal);
						// recurse into the connected zone 
						portal->getTargetZone()->_findNodes(t, 
															list, 
															visitedPortals,
															includeVisitors, 
															recurseThruPortals, 
															exclude);
					}
				}
				pit++;
			}
		}

	}
Exemple #5
0
	//---------------------------------------------------------------------()
	void Camera::getCameraToViewportBoxVolume(Real screenLeft, 
		Real screenTop, Real screenRight, Real screenBottom, 
		PlaneBoundedVolume* outVolume, bool includeFarPlane)
	{
		outVolume->planes.clear();

		if (mProjType == PT_PERSPECTIVE)
		{

			// Use the corner rays to generate planes
			Ray ul = getCameraToViewportRay(screenLeft, screenTop);
			Ray ur = getCameraToViewportRay(screenRight, screenTop);
			Ray bl = getCameraToViewportRay(screenLeft, screenBottom);
			Ray br = getCameraToViewportRay(screenRight, screenBottom);


			Vector3 normal;
			// top plane
			normal = ul.getDirection().crossProduct(ur.getDirection());
			normal.normalise();
			outVolume->planes.push_back(
				Plane(normal, getDerivedPosition()));

			// right plane
			normal = ur.getDirection().crossProduct(br.getDirection());
			normal.normalise();
			outVolume->planes.push_back(
				Plane(normal, getDerivedPosition()));

			// bottom plane
			normal = br.getDirection().crossProduct(bl.getDirection());
			normal.normalise();
			outVolume->planes.push_back(
				Plane(normal, getDerivedPosition()));

			// left plane
			normal = bl.getDirection().crossProduct(ul.getDirection());
			normal.normalise();
			outVolume->planes.push_back(
				Plane(normal, getDerivedPosition()));

		}
		else
		{
			// ortho planes are parallel to frustum planes

			Ray ul = getCameraToViewportRay(screenLeft, screenTop);
			Ray br = getCameraToViewportRay(screenRight, screenBottom);

			updateFrustumPlanes();
			outVolume->planes.push_back(
				Plane(mFrustumPlanes[FRUSTUM_PLANE_TOP].normal, ul.getOrigin()));
			outVolume->planes.push_back(
				Plane(mFrustumPlanes[FRUSTUM_PLANE_RIGHT].normal, br.getOrigin()));
			outVolume->planes.push_back(
				Plane(mFrustumPlanes[FRUSTUM_PLANE_BOTTOM].normal, br.getOrigin()));
			outVolume->planes.push_back(
				Plane(mFrustumPlanes[FRUSTUM_PLANE_LEFT].normal, ul.getOrigin()));
			

		}

		// near & far plane applicable to both projection types
		outVolume->planes.push_back(getFrustumPlane(FRUSTUM_PLANE_NEAR));
		if (includeFarPlane)
			outVolume->planes.push_back(getFrustumPlane(FRUSTUM_PLANE_FAR));
	}
Exemple #6
0
  Vec3f PhongShader::shade(Ray& ray)
  {
    if (!scene) return Vec3f();

    vector<Light*>::iterator lightIt;
    Vec3f color;
    Point3f iPoint = ray.getIntersectionPoint();
    Vec3f N = ray.normal.normalized();

    for (lightIt = scene->lights.begin(); lightIt != scene->lights.end(); ++lightIt)
    {
      Light* light = *lightIt;
      if (!light) { color += Vec3f(0.5,0.5,0.5); continue; }

      float invlightDist = 1.0f / (light->pos() - iPoint).length();
      invlightDist *= invlightDist * light->intensity();

      Vec3f L = ( light->pos()- iPoint).normalized();
      color += ambient % light->ambient() * invlightDist;

      float angle = N * L;

      if (angle > 0.0f)
      {	
        Vec3f diff = light->diffuse() % diffuse * angle * invlightDist;
        Vec3f E = ray.org.vec3f().normalized();
        L = -L;
        float dotLN = N * L;
        Vec3f R = L - (2.0 * dotLN * N);

        float spec = pow(max( R * E , 0.0f ), shininess );
        diff += light->specular() % specular * spec * invlightDist;

        if (light->shadows() > 0.0f)
        {
          Point3f rndPos(light->pos().x-(RND-0.5)*light->radius(),
              light->pos().y-(RND-0.5)*light->radius(),
              light->pos().z-(RND-0.5)*light->radius());

          Ray shadowRay(rndPos,iPoint-rndPos);
          shadowRay.tmin = 0.01;
          shadowRay.tmax = 0.99;

          if (scene->traceShadowRay(shadowRay,(SceneObject*)ray.obj))
            diff *=  (1.0 - light->shadows()*(1.0-refract)*(1.0-reflect));
        }	

        color += diff;
      }
    }

    ray.color = color;

    if (ray.bounce < scene->maxBounce)
    {
      if (reflect > 0.0f)
      {
        Ray rayRefl = ray.reflect();
        color += color*(1.0f - reflect) + scene->traceRay(rayRefl,(SceneObject*)ray.obj) * reflect;
      }
      if (refract > 0.0f)
      {
        Ray rayRefr = ray.refract(IOR);
        color += color*(1.0f - refract) + scene->traceRay(rayRefr,(SceneObject*)ray.obj) * refract;
      }
    }

    return color;	
  }
Exemple #7
0
	std::pair<bool, float> Capsule::intersects(const Ray& ray) const
	{
		const Vector3& org = ray.getOrigin();
		const Vector3& dir = ray.getDirection();

		Vector3 segDir = mSegment.getEnd() - mSegment.getStart();
		float segExtent = segDir.normalize() * 0.5f;
		Vector3 segCenter = mSegment.getStart() + segDir * segExtent;

		Vector3 basis[3];
		basis[0] = segDir;
		basis[0].orthogonalComplement(basis[1], basis[2]);

		float rSqr = mRadius * mRadius;

		Vector3 diff = org - segCenter;
		Vector3 P(basis[1].dot(diff), basis[2].dot(diff), basis[0].dot(diff));

		// Get the z-value, in capsule coordinates, of the incoming line's
		// unit-length direction.
		float dz = basis[0].dot(dir);
		if (std::abs(dz) == 1.0f)
		{
			// The line is parallel to the capsule axis.  Determine whether the
			// line intersects the capsule hemispheres.
			float radialSqrDist = rSqr - P[0] * P[0] - P[1] * P[1];
			if (radialSqrDist < 0.0f)
			{
				// The line is outside the cylinder of the capsule, so there is no
				// intersection.
				return std::make_pair(false, 0.0f);
			}

			// The line intersects the hemispherical caps.
			float zOffset = std::sqrt(radialSqrDist) + segExtent;
			if (dz > 0.0f)
				return std::make_pair(true, -P[2] - zOffset);
			else
				return std::make_pair(true, P[2] - zOffset);
		}

		// Convert the incoming line unit-length direction to capsule coordinates.
		Vector3 D(basis[1].dot(dir), basis[2].dot(dir), dz);

		// Test intersection of line with infinite cylinder 
		float a0 = P[0] * P[0] + P[1] * P[1] - rSqr;
		float a1 = P[0] * D[0] + P[1] * D[1];
		float a2 = D[0] * D[0] + D[1] * D[1];
		float discr = a1*a1 - a0*a2;

		if (discr < 0.0f)
		{
			// The line does not intersect the infinite cylinder.
			return std::make_pair(false, 0.0f);
		}

		float root, inv, tValue, zValue;
		float nearestT = std::numeric_limits<float>::max();
		bool foundOneIntersection = false;

		if (discr > 0.0f)
		{
			// The line intersects the infinite cylinder in two places.
			root = std::sqrt(discr);
			inv = 1.0f / a2;

			tValue = (-a1 - root)*inv;
			zValue = P[2] + tValue*D[2];
			if (std::abs(zValue) <= segExtent)
			{
				nearestT = tValue;
				foundOneIntersection = true;
			}

			tValue = (-a1 + root)*inv;
			zValue = P[2] + tValue*D[2];
			if (std::abs(zValue) <= segExtent)
			{
				if (foundOneIntersection)
					return std::make_pair(true, nearestT);
				else
				{
					nearestT = tValue;
					foundOneIntersection = true;
				}
			}
		}
		else
		{
			// The line is tangent to the infinite cylinder but intersects the
			// cylinder in a single point.
			tValue = -a1 / a2;
			zValue = P[2] + tValue*D[2];
			if (std::abs(zValue) <= segExtent)
				return std::make_pair(true, tValue);
		}

		// Test intersection with bottom hemisphere.
		float PZpE = P[2] + segExtent;
		a1 += PZpE*D[2];
		a0 += PZpE*PZpE;
		discr = a1*a1 - a0;
		if (discr > 0)
		{
			root = sqrt(discr);
			tValue = -a1 - root;
			zValue = P[2] + tValue*D[2];
			if (zValue <= -segExtent)
			{
				if (foundOneIntersection)
					return std::make_pair(true, nearestT < tValue ? nearestT : tValue);
				else
				{
					nearestT = tValue;
					foundOneIntersection = true;
				}
			}

			tValue = -a1 + root;
			zValue = P[2] + tValue*D[2];
			if (zValue <= -segExtent)
			{
				if (foundOneIntersection)
					return std::make_pair(true, nearestT < tValue ? nearestT : tValue);
				else
				{
					nearestT = tValue;
					foundOneIntersection = true;
				}
			}
		}
		else if (discr == 0.0f)
		{
			tValue = -a1;
			zValue = P[2] + tValue*D[2];
			if (zValue <= -segExtent)
			{
				if (foundOneIntersection)
					return std::make_pair(true, nearestT < tValue ? nearestT : tValue);
				else
				{
					nearestT = tValue;
					foundOneIntersection = true;
				}
			}
		}

		// Test intersection with top hemisphere
		a1 -= 2.0f*segExtent*D[2];
		a0 -= 4.0f*segExtent*P[2];
		discr = a1*a1 - a0;
		if (discr > 0.0f)
		{
			root = sqrt(discr);
			tValue = -a1 - root;
			zValue = P[2] + tValue*D[2];
			if (zValue >= segExtent)
			{
				if (foundOneIntersection)
					return std::make_pair(true, nearestT < tValue ? nearestT : tValue);
				else
				{
					nearestT = tValue;
					foundOneIntersection = true;
				}
			}

			tValue = -a1 + root;
			zValue = P[2] + tValue*D[2];
			if (zValue >= segExtent)
			{
				if (foundOneIntersection)
					return std::make_pair(true, nearestT < tValue ? nearestT : tValue);
				else
				{
					nearestT = tValue;
					foundOneIntersection = true;
				}
			}
		}
		else if (discr == 0.0f)
		{
			tValue = -a1;
			zValue = P[2] + tValue*D[2];
			if (zValue >= segExtent)
			{
				if (foundOneIntersection)
					return std::make_pair(true, nearestT < tValue ? nearestT : tValue);
				else
				{
					nearestT = tValue;
					foundOneIntersection = true;
				}
			}
		}

		if (foundOneIntersection)
			return std::make_pair(true, nearestT);

		return std::make_pair(false, 0.0f);
	}
Exemple #8
0
void init(void)
{
	float seconds = glutGet(GLUT_ELAPSED_TIME);

	 Objects obj;

	 float raysPerPixel = 9.0f;
	 int rays = int(raysPerPixel);

	float X =2;
	float Y =2;
	float Z =0;
	float cornellDepth = 5.0f;
	
	 //CornellBox Walls
	 obj.createNewPlane(glm::vec3(-X,-Y,Z),glm::vec3(X,-Y,Z),glm::vec3(X,Y,Z),glm::vec3(-X,Y,Z));
	 obj.createNewPlane(glm::vec3(-X,-Y,Z+cornellDepth),glm::vec3(-X,-Y,Z),glm::vec3(-X,Y,Z),glm::vec3(-X,Y,Z+cornellDepth));
	 obj.createNewPlane(glm::vec3(-X,-Y,Z+cornellDepth),glm::vec3(X,-Y,Z+cornellDepth),glm::vec3(X,-Y,Z),glm::vec3(-X,-Y,Z));
	 obj.createNewPlane(glm::vec3(X,-Y,Z),glm::vec3(X,-Y,Z+cornellDepth),glm::vec3(X,Y,Z+cornellDepth),glm::vec3(X,Y,Z));
	 obj.createNewPlane(glm::vec3(-X,Y,Z),glm::vec3(X,Y,Z),glm::vec3(X,Y,Z+cornellDepth),glm::vec3(-X,Y,Z+cornellDepth));
	 //And their Colors
	 obj.shapes[0]->material.color = GREEN;
	 obj.shapes[1]->material.color = MAGENTA;
	 obj.shapes[2]->material.color = YELLOW;
	 obj.shapes[3]->material.color = BLUE;
	 obj.shapes[4]->material.color = RED;
	 
	 //Box made up of 6 planes
	 float boxY = 0.525;
	 obj.createNewPlane(glm::vec3(-1.587,-2.0,1.819),glm::vec3(-0.361,-2.000,2.120),glm::vec3(-0.361,0.525,2.120),glm::vec3(-1.587,0.525,1.819));
	 obj.createNewPlane(glm::vec3(-0.361,-2.0,2.120),glm::vec3(-0.060,-2.000,0.894),glm::vec3(-0.060,0.525,0.894),glm::vec3(-0.361,0.525,2.120));
	 obj.createNewPlane(glm::vec3(-0.060,-2.0,0.894),glm::vec3(-1.286,-2.000,0.593),glm::vec3(-1.286,0.525,0.593),glm::vec3(-0.060,0.525,0.894));
	 obj.createNewPlane(glm::vec3(-1.286,-2.0,0.593),glm::vec3(-1.587,-2.000,1.819),glm::vec3(-1.587,0.525,1.819),glm::vec3(-1.286,0.525,0.593));
	 //top
	 obj.createNewPlane(glm::vec3(-1.587,0.525,1.819),glm::vec3(-0.361,0.525,2.120),glm::vec3(-0.060,0.525,0.894),glm::vec3(-1.286,0.525,0.593));
	 float SphereRadius = 0.80;
	 obj.createNewSphere(glm::mat4(0.0),glm::vec3(0.7,-2.0+SphereRadius,Z+3.0),SphereRadius);

	 obj.shapes[5]->material.color = BLUE;
	 obj.shapes[6]->material.color = RED;
	 obj.shapes[7]->material.color = YELLOW;
	 obj.shapes[8]->material.color = MAGENTA;
	 obj.shapes[9]->material.color = CYAN;

	 obj.shapes[10]->material.isDiffuse = false;
	 obj.shapes[10]->material.isRefractive = true;
	obj.shapes[10]->material.refractiveIndex = 1.5f; //Originally 1.33f
	 obj.shapes[10]->material.color = YELLOW;

	  obj.createNewPlane(glm::vec3(-X*20,-Y*20,Z+7.7),glm::vec3(-X*20,Y*20,Z+7.7),glm::vec3(X*20,Y*20,Z+7.7),glm::vec3(X*20,-Y*20,Z+7.7));

	  obj.shapes[11]->material.color = CYAN;

	 obj.shapes[5]->material.isDiffuse = false;
	 obj.shapes[6]->material.isDiffuse = false;
	 obj.shapes[7]->material.isDiffuse = false;
	 obj.shapes[8]->material.isDiffuse = false;
	 obj.shapes[9]->material.isDiffuse = false;



	 obj.createNewSphere(glm::mat4(0.0),glm::vec3(-1.0,-2.0+0.6,Z+3.0),0.6);
	 obj.shapes[12]->material.isDiffuse = false;


	//======== Main RayTracing Loop ========
		glm::vec3 renderColor,pixelColor = BLACK;
		glm::vec3 lightSource =glm::vec3(0,1.75,2);

		float yFov = 0.5*renderHeight / (camera.position.z*sin(FieldOfView/2.0));
		float xFov = 0.5*renderWidth / (camera.position.z*sin(FieldOfView*(renderWidth/renderHeight)/2.0));

		float maxT = -10.0;
			float minT = 9999999.9;


		float SSx [9];
			
		SSx[0] = -1.0/3.0;
		SSx[1] = 0.0;
		SSx[2] = 1.0/3.0;
		SSx[3] = -1.0/3.0;
		SSx[4] = 0.0;
		SSx[5] = 1.0/3.0;
		SSx[6] = -1.0/3.0;
		SSx[7] = 0.0;
		SSx[8] = 1.0/3.0;


		float SSy [9];

		SSy[0] = 1.0/3.0;
		SSy[1] = 1.0/3.0;
		SSy[2] = 1.0/3.0;
		SSy[3] = 0.0;
		SSy[4] = 0.0;
		SSy[5] = 0.0;
		SSy[6] = -1.0/3.0;
		SSy[7] = -1.0/3.0;
		SSy[8] = -1.0/3.0;
		
		srand((unsigned)time(NULL));
		float shadow = 1.0;

		for (int x=0; x<renderWidth; x++) 
		{	
			for (int y=0; y<renderHeight; y++) 
			{
				shadow = 1.0;
				renderColor = glm::vec3(0);


				
				for (int i=0; i<rays; i++) 
				{
					SSx[i] += 0.01*((((float)rand() / (float)RAND_MAX)/3.75) -1.0/7.5);
					SSy[i] += 0.01*((((float)rand() / (float)RAND_MAX)/3.75) -1.0/7.5);
				}
				
				for (int c=0; c<rays; c++) 
				{
					pixelColor = glm::vec3(0);
					glm::vec3 rayDirection = glm::vec3((x+SSx[c]-renderWidth/2.0)/yFov,(y+SSy[c]-renderHeight/2.0)/yFov,pixelPlane) - camera.position;

					rayDirection = glm::normalize(rayDirection);


					bool insideObject = false;
					bool hitWall = false;
					int rayDepth = 1;
					float t = 999999.0;
					float tMin = 999999.0;
					int objectID = -1;
					float lastRefIndex = 1.3333;
					int maxDepth = 12;


					Ray ray = Ray();
					ray.createRay(camera.position,rayDirection,1.0f,100.0f,maxDepth, false);
					ray.trace(obj,maxDepth);
					renderColor += ray.color;
					
				}
				

				renderColor.r = glm::min(renderColor.r/raysPerPixel,1.0f);
				renderColor.g = glm::min(renderColor.g/raysPerPixel,1.0f);
				renderColor.b = glm::min(renderColor.b/raysPerPixel,1.0f);

				pixels[3*(y*renderWidth+x)] = 255*renderColor.r;
				pixels[3*(y*renderWidth+x)+1] = 255*renderColor.g;
				pixels[3*(y*renderWidth+x)+2] = 255*renderColor.b;

				
			}
			std::cout << "progress: " << x << " / " << renderWidth << " done" << std::endl;
		}


		float ms = (glutGet(GLUT_ELAPSED_TIME) - seconds);

		std::cout << "RenderTime: " << ms << " milliseconds" << std::endl;
		//  (0,480)----------------- (640,480)
		//         |               |
		//         |   The Screen  |
		//         |               |
		//         |               |
		//    (0,0)----------------- (640,0)


	printf("OpenGL Version:%s\n",glGetString(GL_VERSION));
	printf("GLSL Version  :%s\n\n",glGetString(GL_SHADING_LANGUAGE_VERSION));

		glGenTextures( 1, &imageTexture );
	glBindTexture( GL_TEXTURE_2D, imageTexture);

		
}
Exemple #9
0
Color trace(const Scene& scene, Ray ray, int depth)
{
    const Color background(0,0,0);
    const int maxDepth = 3;
    if (depth >= maxDepth)
        return background;

    Color color(0,0,0);
    double distance = 0;
    const Primitive* prim = NULL;
    int intersectionType = 0;

    findNearsetIntersection(scene, ray, &prim, &distance, &intersectionType);

    if (prim != NULL)
    {
        if (prim->IsIlluminative())
        {
            return prim->GetMaterial().GetColor();
        }

        const Vector3 intersectionPoint = ray.GetPoint(distance);
        const Vector3 n = prim->GetNormal(intersectionPoint);

        if (prim->GetMaterial().GetDiffuse() > 0)
        {
            for (Scene::ConstIterator it = scene.Begin(); it != scene.End(); it++)
            {
                const double intensive = getIntensity((*it), intersectionPoint, n, scene);

                if (intensive != .0)
                {
                    Vector3 x = (prim->GetMaterial().GetColor());
                    Vector3 y = ((*it)->GetMaterial().GetColor());

                    color = color + (intensive * prim->GetMaterial().GetDiffuse()) * x * y;
                }
            }
        }

        //refraction
        {
            const Vector3 x = ray.GetDirection();
            const Vector3 y = intersectionType * (-n);

            double n;
            if (intersectionType == IntersectOutside)
                n = 1.0 / prim->GetMaterial().GetRefractionRate();
            else
                n = prim->GetMaterial().GetRefractionRate();

            const double sin_1 = sqrt(1 - Dot(x,y));
            const double sin_2 = n * sin_1;

            if (sin_2 < 1)
            {
                const double cos_2 = sqrt(1 - sin_2);
                Vector3 xPerpendicular = x - Dot(x,y)*y;
                Vector3 z = cos_2 * y + sin_2 * xPerpendicular;
                z.Normalize();

                if (prim->GetMaterial().GetRefraction() > 0)
                {
                    if (intersectionType == IntersectInside)
                    {
                        color = color +
                            prim->GetMaterial().GetRefraction() *
                            exp(-prim->GetMaterial().GetAbsorptionRate()*distance) *
                            trace(scene, Ray(intersectionPoint, z), depth + 1);
                    }
                    else
                        color = color +
                            prim->GetMaterial().GetRefraction() * trace(scene, Ray(intersectionPoint, z), depth + 1);
                }
            }
        }

        //reflection
        if (prim->GetMaterial().GetReflection() > 0)
        {
            const Vector3 a = ray.GetDirection();
            Vector3 newA = a - 2 * (Dot(a,n)) * n;
            color = color + prim->GetMaterial().GetReflection() * trace(scene, Ray(intersectionPoint, newA), depth + 1);
        }
    }
    return color;
}
bool BoundingBox::intersects(const Ray& ray) const {
	if (mNull)
		return false;

	switch (ray.getClassification())
	{
	case Ray::MMM:
		// side(R,HD) < 0 or side(R,FB) > 0 or side(R,EF) > 0 or side(R,DC) < 0 or side(R,CB) < 0 or side(R,HE) > 0 to miss

		if ((ray.x() < mXMin) || (ray.y() < mYMin) || (ray.z() < mZMin) ||
			(ray.R0() + ray.i() * mYMin - ray.j() * mXMax < 0) ||
			(ray.R0() + ray.i() * mYMax - ray.j() * mXMin > 0) ||
			(ray.R1() + ray.i() * mZMax - ray.k() * mXMin > 0) ||
			(ray.R1() + ray.i() * mZMin - ray.k() * mXMax < 0) ||
			(ray.R3() - ray.k() * mYMax + ray.j() * mZMin < 0) ||
			(ray.R3() - ray.k() * mYMin + ray.j() * mZMax > 0))
			return false;

		return true;

	case Ray::MMP:
		// side(R,HD) < 0 or side(R,FB) > 0 or side(R,HG) > 0 or side(R,AB) < 0 or side(R,DA) < 0 or side(R,GF) > 0 to miss

		if ((ray.x() < mXMin) || (ray.y() < mYMin) || (ray.z() > mZMax) ||
			(ray.R0() + ray.i() * mYMin - ray.j() * mXMax < 0) ||
			(ray.R0() + ray.i() * mYMax - ray.j() * mXMin > 0) ||
			(ray.R1() + ray.i() * mZMax - ray.k() * mXMax > 0) ||
			(ray.R1() + ray.i() * mZMin - ray.k() * mXMin < 0) ||
			(ray.R3() - ray.k() * mYMin + ray.j() * mZMin < 0) ||
			(ray.R3() - ray.k() * mYMax + ray.j() * mZMax > 0))
			return false;

		return true;

	case Ray::MPM:
		// side(R,EA) < 0 or side(R,GC) > 0 or side(R,EF) > 0 or side(R,DC) < 0 or side(R,GF) < 0 or side(R,DA) > 0 to miss

		if ((ray.x() < mXMin) || (ray.y() > mYMax) || (ray.z() < mZMin) ||
			(ray.R0() + ray.i() * mYMin - ray.j() * mXMin < 0) ||
			(ray.R0() + ray.i() * mYMax - ray.j() * mXMax > 0) ||
			(ray.R1() + ray.i() * mZMax - ray.k() * mXMin > 0) ||
			(ray.R1() + ray.i() * mZMin - ray.k() * mXMax < 0) ||
			(ray.R3() - ray.k() * mYMax + ray.j() * mZMax < 0) ||
			(ray.R3() - ray.k() * mYMin + ray.j() * mZMin > 0))
			return false;

		return true;

	case Ray::MPP:
		// side(R,EA) < 0 or side(R,GC) > 0 or side(R,HG) > 0 or side(R,AB) < 0 or side(R,HE) < 0 or side(R,CB) > 0 to miss

		if ((ray.x() < mXMin) || (ray.y() > mYMax) || (ray.z() > mZMax) ||
			(ray.R0() + ray.i() * mYMin - ray.j() * mXMin < 0) ||
			(ray.R0() + ray.i() * mYMax - ray.j() * mXMax > 0) ||
			(ray.R1() + ray.i() * mZMax - ray.k() * mXMax > 0) ||
			(ray.R1() + ray.i() * mZMin - ray.k() * mXMin < 0) ||
			(ray.R3() - ray.k() * mYMin + ray.j() * mZMax < 0) ||
			(ray.R3() - ray.k() * mYMax + ray.j() * mZMin > 0))
			return false;

		return true;

	case Ray::PMM:
		// side(R,GC) < 0 or side(R,EA) > 0 or side(R,AB) > 0 or side(R,HG) < 0 or side(R,CB) < 0 or side(R,HE) > 0 to miss

		if ((ray.x() > mXMax) || (ray.y() < mYMin) || (ray.z() < mZMin) ||
			(ray.R0() + ray.i() * mYMax - ray.j() * mXMax < 0) ||
			(ray.R0() + ray.i() * mYMin - ray.j() * mXMin > 0) ||
			(ray.R1() + ray.i() * mZMin - ray.k() * mXMin > 0) ||
			(ray.R1() + ray.i() * mZMax - ray.k() * mXMax < 0) ||
			(ray.R3() - ray.k() * mYMax + ray.j() * mZMin < 0) ||
			(ray.R3() - ray.k() * mYMin + ray.j() * mZMax > 0))
			return false;

		return true;

	case Ray::PMP:
		// side(R,GC) < 0 or side(R,EA) > 0 or side(R,DC) > 0 or side(R,EF) < 0 or side(R,DA) < 0 or side(R,GF) > 0 to miss

		if ((ray.x() > mXMax) || (ray.y() < mYMin) || (ray.z() > mZMax) ||
			(ray.R0() + ray.i() * mYMax - ray.j() * mXMax < 0) ||
			(ray.R0() + ray.i() * mYMin - ray.j() * mXMin > 0) ||
			(ray.R1() + ray.i() * mZMin - ray.k() * mXMax > 0) ||
			(ray.R1() + ray.i() * mZMax - ray.k() * mXMin < 0) ||
			(ray.R3() - ray.k() * mYMin + ray.j() * mZMin < 0) ||
			(ray.R3() - ray.k() * mYMax + ray.j() * mZMax > 0))
			return false;

		return true;

	case Ray::PPM:
		// side(R,FB) < 0 or side(R,HD) > 0 or side(R,AB) > 0 or side(R,HG) < 0 or side(R,GF) < 0 or side(R,DA) > 0 to miss

		if ((ray.x() > mXMax) || (ray.y() > mYMax) || (ray.z() < mZMin) ||
			(ray.R0() + ray.i() * mYMax - ray.j() * mXMin < 0) ||
			(ray.R0() + ray.i() * mYMin - ray.j() * mXMax > 0) ||
			(ray.R1() + ray.i() * mZMin - ray.k() * mXMin > 0) ||
			(ray.R1() + ray.i() * mZMax - ray.k() * mXMax < 0) ||
			(ray.R3() - ray.k() * mYMax + ray.j() * mZMax < 0) ||
			(ray.R3() - ray.k() * mYMin + ray.j() * mZMin > 0))
			return false;

		return true;

	case Ray::PPP:
		// side(R,FB) < 0 or side(R,HD) > 0 or side(R,DC) > 0 or side(R,EF) < 0 or side(R,HE) < 0 or side(R,CB) > 0 to miss

		if ((ray.x() > mXMax) || (ray.y() > mYMax) || (ray.z() > mZMax) ||
			(ray.R0() + ray.i() * mYMax - ray.j() * mXMin < 0) ||
			(ray.R0() + ray.i() * mYMin - ray.j() * mXMax > 0) ||
			(ray.R1() + ray.i() * mZMin - ray.k() * mXMax > 0) ||
			(ray.R1() + ray.i() * mZMax - ray.k() * mXMin < 0) ||
			(ray.R3() - ray.k() * mYMin + ray.j() * mZMax < 0) ||
			(ray.R3() - ray.k() * mYMax + ray.j() * mZMin > 0))
			return false;

		return true;
	}

	return false;
}
/*
 * Calculates the output ray \a outputRay for the \a incident ray for the intersection parameters \a dg.
 *
 * Returns FALSE if there is not output ray.
 */
bool MaterialAngleDependentSpecular::OutputRay( const Ray& incident, DifferentialGeometry* dg, RandomDeviate& rand, Ray* outputRay  ) const
{
    double reflectivity = 0.0;

    NormalVector dgNormal;
    if( dg->shapeFrontSide )
    {
        if( !reflectivityFront.getValue() )	return ( false );
        dgNormal = dg->normal;

        // Product
        double incidenceAngle  = acos( DotProduct( -incident.direction(), dgNormal ) );
        reflectivity = OutputPropertyValue( m_frontReflectivityIncidenceAngle,  m_frontReflectivityValue, incidenceAngle );
    }
    else
    {
        if( !reflectivityBack.getValue() )	return ( false );

        dgNormal = - dg->normal;
        double incidenceAngle  = acos( DotProduct( -incident.direction(), dgNormal) );
        reflectivity = OutputPropertyValue( m_backReflectivityIncidenceAngle,  m_backReflectivityValue, incidenceAngle );

    }

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

    //Compute reflected ray (local coordinates )
    //Ray* reflected = new Ray();
    //reflected.origin = dg->point;
    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 = dgNormal;
        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 = dgNormal;
    }

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

}
Exemple #12
0
pair<int, float> Grid::trace(const Ray &ray, float tmin, float tmax, int ignored_id, int flags) const {
	float3 p1 = ray.at(tmin), p2 = ray.at(tmax);
	int2 pos = worldToGrid((int2)p1.xz()), end = worldToGrid((int2)p2.xz());
	
	//TODO: verify for rays going out of grid space
	if(!isInsideGrid(pos) || !isInsideGrid(end))
		return make_pair(-1, constant::inf);

	// Algorithm idea from: RTCD by Christer Ericson
	int dx = end.x > pos.x? 1 : end.x < pos.x? -1 : 0;
	int dz = end.y > pos.y? 1 : end.y < pos.y? -1 : 0;

	float cell_size = (float)node_size;
	float inv_cell_size = 1.0f / cell_size;
	float lenx = fabs(p2.x - p1.x);
	float lenz = fabs(p2.z - p1.z);

	float minx = float(node_size) * floorf(p1.x * inv_cell_size), maxx = minx + cell_size;
	float minz = float(node_size) * floorf(p1.z * inv_cell_size), maxz = minz + cell_size;
	float tx = (p1.x > p2.x? p1.x - minx : maxx - p1.x) / lenx;
	float tz = (p1.z > p2.z? p1.z - minz : maxz - p1.z) / lenz;

	float deltax = cell_size / lenx;
	float deltaz = cell_size / lenz;

	int out = -1;
	float out_dist = tmax + constant::epsilon;

	while(true) {
		int node_id = nodeAt(pos);
		const Node &node = m_nodes[node_id];

		if(flagTest(node.obj_flags, flags) && intersection(ray, node.bbox) < out_dist) {
			const Object *objects[node.size];
			int count = extractObjects(node_id, objects, ignored_id, flags);

			for(int n = 0; n < count; n++) {
				float dist = intersection(ray, objects[n]->bbox);
				if(dist < out_dist) {
					out_dist = dist;
					out = objects[n] - &m_objects[0];
				}
			}	
			
			if(node.is_dirty)
				updateNode(node_id);
		}

		if(tx <= tz || dz == 0) {
			if(pos.x == end.x)
				break;
			tx += deltax;
			pos.x += dx;
		}
		else {
			if(pos.y == end.y)
				break;
			tz += deltaz;
			pos.y += dz;
		}
		float ray_pos = tmin + max((tx - deltax) * lenx, (tz - deltaz) * lenz);
		if(ray_pos >= out_dist)
			break;
	}

	return make_pair(out, out_dist);
}
Exemple #13
0
bool AABB::Intersects( const Ray& r ) const
{
	return r.Intersects( *this );
}
Exemple #14
0
void StaticModelGroup::ProcessRayQuery(const RayOctreeQuery& query, PODVector<RayQueryResult>& results)
{
    // If no bones or no bone-level testing, use the Drawable test
    RayQueryLevel level = query.level_;
    if (level < RAY_AABB)
    {
        Drawable::ProcessRayQuery(query, results);
        return;
    }

    // Check ray hit distance to AABB before proceeding with more accurate tests
    // GetWorldBoundingBox() updates the world transforms
    if (query.ray_.HitDistance(GetWorldBoundingBox()) >= query.maxDistance_)
        return;
    
    for (unsigned i = 0; i < numWorldTransforms_; ++i)
    {
        // Initial test using AABB
        float distance = query.ray_.HitDistance(boundingBox_.Transformed(worldTransforms_[i]));
        Vector3 normal = -query.ray_.direction_;
        
        // Then proceed to OBB and triangle-level tests if necessary
        if (level >= RAY_OBB && distance < query.maxDistance_)
        {
            Matrix3x4 inverse = worldTransforms_[i].Inverse();
            Ray localRay = query.ray_.Transformed(inverse);
            distance = localRay.HitDistance(boundingBox_);
            
            if (level == RAY_TRIANGLE && distance < query.maxDistance_)
            {
                distance = M_INFINITY;
                
                for (unsigned j = 0; j < batches_.Size(); ++j)
                {
                    Geometry* geometry = batches_[j].geometry_;
                    if (geometry)
                    {
                        Vector3 geometryNormal;
                        float geometryDistance = geometry->GetHitDistance(localRay, &geometryNormal);
                        if (geometryDistance < query.maxDistance_ && geometryDistance < distance)
                        {
                            distance = geometryDistance;
                            normal = (worldTransforms_[i] * Vector4(geometryNormal, 0.0f)).Normalized();
                        }
                    }
                }
            }
        }
        
        if (distance < query.maxDistance_)
        {
            RayQueryResult result;
            result.position_ = query.ray_.origin_ + distance * query.ray_.direction_;
            result.normal_ = normal;
            result.distance_ = distance;
            result.drawable_ = this;
            result.node_ = node_;
            result.subObject_ = i;
            results.Push(result);
        }
    }
}
Ray Renderable::transformRayWorldToModel(const Ray &ray) const
{
  return ray.transformed(mTransformInv);
}
Exemple #16
0
	/**
	  * Computes normal for an intersection point on a sphere
	  */
	const glm::vec3 computeNormal(const Ray& r, const float& t) {
		glm::vec3 n = glm::normalize(((r.getOrigin() + t * r.getDirection()) - p) / this->r);
		return n;
	}
double Renderable::transformRayLambdaWorldToModel(const Ray &ray, const double lambda) const
{
  Vec3d model_direction = mTransformInv.as3x3()*ray.direction();

  return lambda * model_direction.length();
}
Exemple #18
0
 void operator()(const Ray& ray, const Triangle& tri, float& distance) {
     float d = ray.intersectionTime(tri);
     if (d > 0 && d < distance) {
         distance = d;
     }
 }
Exemple #19
0
//------------------------------------------------------------------------
bool KdTreeNode::intersect(const Ray& ray, float min, float max, float* pDistance, const Sphere** ppSphere) const
{
	ASSERT(pDistance != nullptr && ppSphere != nullptr);

	// Case 1: leaf has been reached
	if (isLeaf())
	{
		if (m_Spheres->size() == 0)
		{
			return false;
		}

		*pDistance = std::numeric_limits<float>::max();
		bool success = false;

		for (auto it = m_Spheres->begin(); it != m_Spheres->end(); it++)
		{
			const Sphere& s = **it;
			float d;

			if (s.intersect(ray, &d))
			{
				if (d < *pDistance && d < max)
				{
					success = true;
					*pDistance = d;
					*ppSphere = &s;
				}
			}
		}

		return success;
	}
	
	float dirAxis = ray.getDirection().get(m_Axis);
	float tSplit = ray.planeIntersectionDistance(m_SplitDistance, m_Axis);

	KdTreeNode* minNode; // Node the closest  to the ray origin
	KdTreeNode* maxNode; // Node the furthest to the ray origin
	if (dirAxis > 0)
	{
		minNode = getA();
		maxNode = getB();
	}
	else
	{
		minNode = getB();
		maxNode = getA();
	}

	// Case 2: ray is parallel to split plane
	if (dirAxis == 0)
	{
		float originPlane = ray.getOrigin().get(m_Axis);

		if (originPlane < m_SplitDistance)
		{
			return getA()->intersect(ray, min, max, pDistance, ppSphere);
		}
		if (m_SplitDistance < originPlane)
		{
			return getB()->intersect(ray, min, max, pDistance, ppSphere);
		}

		return false;
	}

	// Case 3: ray only crosses min node
	if (max < tSplit)
	{
		return minNode->intersect(ray, min, max, pDistance, ppSphere);
	}

	// Case 4: ray only crosses max node
	if (tSplit < min)
	{
		return maxNode->intersect(ray, min, max, pDistance, ppSphere);
	}

	// Case 5: ray crosses both nodes
	if (minNode->intersect(ray, min, tSplit, pDistance, ppSphere))
	{
		return true;
	}

	return maxNode->intersect(ray, tSplit, max, pDistance, ppSphere);
}
Exemple #20
0
void testRayIntersect() {
    KDTree<Triangle> tree;

    Array<int> index;
    Array<Point3> vertex;
    printf(" (load model, ");
    fflush(stdout);
    
    ArticulatedModel::Ref model = ArticulatedModel::fromFile(System::findDataFile("cow.ifs"));
    extractTriangles(model, vertex, index);
    
    for (int i = 0; i < index.size(); i += 3) {
        int i0 = index[i];
        int i1 = index[i + 1];
        int i2 = index[i + 2];
        tree.insert(Triangle(vertex[i0], vertex[i1], vertex[i2]));
    }
    printf("balance tree, ");
    fflush(stdout);
    tree.balance();

    Vector3 origin = Vector3(0, 5, 0);
    IntersectCallback intersectCallback;
    printf("raytrace, ");
    fflush(stdout);
    for (int i = 0; i < 4000; ++i) {
        // Cast towards a random point near the cow surface
        Vector3 target = vertex.randomElement() + Vector3::random() * 0.0001f;
        Ray ray = Ray::fromOriginAndDirection(origin, (target - origin).direction());

        // Exhaustively test against each triangle
        float exhaustiveDistance = inf();
        {
            const KDTree<Triangle>::Iterator& end = tree.end();
            KDTree<Triangle>::Iterator it = tree.begin();

            while (it != end) {
                const Triangle& tri = *it;
                float d = ray.intersectionTime(tri);
                if (d > 0 && d < exhaustiveDistance) {
                    exhaustiveDistance = d;
                }
                ++it;
            }
        }

        // Test using the ray iterator
        float treeDistance = inf();
        tree.intersectRay(ray, intersectCallback, treeDistance, true);

        float treeDistance2 = inf();
        tree.intersectRay(ray, intersectCallback, treeDistance2, false);

        debugAssertM(fuzzyEq(treeDistance, exhaustiveDistance),
                     format("KDTree::intersectRay found a point at %f, "
                            "exhaustive ray intersection found %f.",
                            treeDistance, exhaustiveDistance));

        debugAssertM(fuzzyEq(treeDistance2, exhaustiveDistance),
                     format("KDTree::intersectRay found a point at %f, "
                            "exhaustive ray intersection found %f.",
                            treeDistance2, exhaustiveDistance));
    }
    printf("done) ");
}
	Ray HeterogeneousVolume::scatter(Ray &inRay) const{
		Ray outRay;
		outRay.isDeltaDirection = false;

		bool go_in_vol = inRay.intersectObj == this && inRay.insideObj != this;
		bool be_in_vol = inRay.insideObj == this;

		// CASE1: Go in volume.
		if(go_in_vol){
			vec3f position = inRay.origin + inRay.direction*inRay.intersectDist;
			vec3f normal = inRay.intersectObj->getWorldNormal(inRay.intersectTriangleID, position);

			outRay.origin = position;
			outRay.direction = inRay.direction;

			vec3f reflDir = -normal.dot(inRay.direction)*normal*2 + inRay.direction;
			reflDir.normalize();
			float theta = acos(inRay.direction.dot(normal));

			AbstractObject* currentInsideObject = inRay.insideObj;
			AbstractObject* outSideObject = (AbstractObject*)this;

			float current_n = currentInsideObject ? currentInsideObject->getIOR() : 1;
			float next_n = outSideObject ? outSideObject->getIOR() : 1;
			float sin_phi = current_n / next_n * sin(theta);

			outRay.intersectObj = NULL;
			outRay.radiance = vec3f(1, 1, 1);
			outRay.directionProb = 1;
			outRay.contactObj = (AbstractObject*)this;
			outRay.contactTriangleID = inRay.intersectTriangleID;

			if(sin_phi > 1){
				outRay.direction = reflDir;
				outRay.insideObj = inRay.insideObj;
				outRay.directionProb = 1;
				outRay.isDeltaDirection = true;
				outRay.photonType = Ray::NOUSE;
			}
			else{
				float phi = asin(sin_phi);
				if(theta > PI/2)	phi = PI - phi;
				vec3f axis = normal.cross(inRay.direction);
				axis.normalize();
				outRay.direction = vec3f(RotateMatrix(axis, phi) * vec4f(normal, 0));
				outRay.direction.normalize();

				float cos_theta = abs(cos(theta));
				float cos_phi = abs(cos(phi));
				float esr = powf(abs(current_n*cos_theta-next_n*cos_phi)/(current_n*cos_theta+next_n*cos_phi),2);
				float epr = powf(abs(next_n*cos_theta-current_n*cos_phi)/(next_n*cos_theta+current_n*cos_phi),2);
				float er = (esr+epr)/2;
				float p = er;

				if(rng->genFloat() < p)
				{
					outRay.direction = reflDir;
					outRay.radiance *= er / outRay.cosineTerm();
					outRay.directionProb = p;
					outRay.insideObj = inRay.insideObj;
					outRay.isDeltaDirection = true;
					outRay.photonType = Ray::NOUSE;
				}
				else
				{
					outRay.radiance *= (1-er) / outRay.cosineTerm();
					outRay.directionProb = 1-p;
					outRay.contactObj = outRay.insideObj = (AbstractObject*)this;
					outRay.isDeltaDirection = true;
					outRay.photonType = Ray::HITVOL;
				}
				outRay.direction.normalize();
			}
			return outRay;
		}

		float p_medium, P_surface, sampleDist;

		bool samplingState = sampleDistance(inRay, sampleDist, p_medium, P_surface);

		bool out_of_vol = samplingState == false;//sampleDist >= inRay.intersectDist;

		// CASE2: Be in volume.
		if(be_in_vol && !out_of_vol){
			outRay.origin = inRay.origin + inRay.direction * sampleDist;
			outRay.radiance = bsdf->sampleBSDF(inRay.direction, outRay.direction, vec3f(), *rng, &outRay.directionProb);
			outRay.insideObj = (AbstractObject*)this;
			outRay.contactTriangleID = inRay.intersectTriangleID;
			float albedo = isSubsurface ? getAlbedo(outRay.origin) : getAlbedo();
			float rander = rng->genFloat();	
			if(rander < albedo){
				outRay.contactObj = NULL;
				outRay.directionProb *= albedo;
				outRay.originProb = p_medium;//  pMedium(inRay, sampleDist);// 
				outRay.isDeltaDirection = false;
				outRay.radiance *= isSubsurface ? lookUpSubSurfaceVolumeData(outRay.origin, SCATTERING) : scatteringCoeff * lookUpDensity(outRay.origin);
				outRay.photonType = Ray::INVOL;
			}
			else{
				// terminate
				outRay.direction = vec3f(0, 0, 0); 
				outRay.radiance = vec3f(0, 0, 0);  
				outRay.directionProb = 1; 
				outRay.originProb = p_medium;//pMedium(inRay, sampleDist);//
				outRay.insideObj = NULL;
				outRay.contactObj = NULL;
				outRay.isDeltaDirection = false;
				outRay.photonType = Ray::INVOL; //Ray::NOUSE;//
			}
			return outRay;
		}

		// CASE3: Go out of volume.
		if(be_in_vol && out_of_vol){
			outRay = inRay;
			outRay.direction = inRay.direction;
			outRay.origin = inRay.origin + inRay.intersectDist * inRay.direction;
			outRay.contactObj = inRay.intersectObj;
			outRay.contactTriangleID = inRay.intersectTriangleID;
			outRay.insideObj = (AbstractObject*)this;
			outRay.directionProb = 1; 
			outRay.radiance = vec3f(1,1,1);
			bool going_out = (inRay.intersectObj == this);
			if(going_out){
				vec3f normal = inRay.intersectObj->getWorldNormal(inRay.intersectTriangleID, outRay.origin);
				vec3f reflDir = -normal.dot(inRay.direction)*normal*2 + inRay.direction;
				reflDir.normalize();
				float theta = acos(inRay.direction.dot(normal));

				AbstractObject* currentInsideObject = (AbstractObject*)this;
				AbstractObject* outSideObject = scene->findInsideObject(outRay, (AbstractObject*)this);

				float current_n = currentInsideObject ? currentInsideObject->getIOR() : 1;
				float next_n = outSideObject ? outSideObject->getIOR() : 1;
				float sin_phi = current_n / next_n * sin(theta);

				outRay.intersectObj = NULL;
				if(sin_phi > 1){
					outRay.direction = reflDir;
					outRay.insideObj = inRay.insideObj;
					outRay.contactObj = (AbstractObject*)this;
					outRay.originProb = P_surface;// PSurface(inRay, inRay.intersectDist);//
					outRay.photonType = Ray::NOUSE;
					outRay.isDeltaDirection = true;
				}
				else{
					float phi = asin(sin_phi);
					if(theta > PI/2)	phi = PI - phi;
					vec3f axis = normal.cross(inRay.direction);
					axis.normalize();
					outRay.direction = vec3f(RotateMatrix(axis, phi) * vec4f(normal, 0));
					outRay.direction.normalize();

					float cos_theta = abs(cos(theta));
					float cos_phi = abs(cos(phi));
					float esr = powf(abs(current_n*cos_theta-next_n*cos_phi)/(current_n*cos_theta+next_n*cos_phi),2);
					float epr = powf(abs(next_n*cos_theta-current_n*cos_phi)/(next_n*cos_theta+current_n*cos_phi),2);
					float er = (esr+epr)/2;
					float p = er;

					if(rng->genFloat() < p)
					{
						outRay.direction = reflDir;
						outRay.radiance *= er / outRay.cosineTerm();
						outRay.directionProb = p;
						outRay.originProb = P_surface;// PSurface(inRay, inRay.intersectDist);//
						outRay.insideObj = inRay.insideObj;
						outRay.isDeltaDirection = true;
						outRay.photonType = Ray::NOUSE;
					}
					else
					{
						outRay.radiance *= (1-er) / outRay.cosineTerm();
						outRay.directionProb = (1-p);
						outRay.originProb = P_surface;//PSurface(inRay, inRay.intersectDist);// 
						outRay.insideObj = outSideObject;
						outRay.isDeltaDirection = true;
						outRay.photonType = Ray::NOUSE;
					}
					outRay.direction.normalize();
				}	
			}
			else{
				outRay.contactObj = NULL;
				outRay.intersectDist = 0;
				outRay = inRay.intersectObj->scatter(outRay);
				outRay.originProb *= P_surface;//PSurface(inRay, inRay.intersectDist);// 
				outRay.photonType = inRay.intersectObj->isVolume() ? Ray::NOUSE : Ray::OUTVOL;
			}
			return outRay;
		}
		return outRay;
	}
Exemple #22
0
float Line::Distance(const Ray &other, float &d, float &d2) const
{
    vec c = ClosestPoint(other, d, d2);
    return c.Distance(other.GetPoint(d2));
}
Exemple #23
0
// Moeller-Trumbore
bool Triangle::hit(const Ray& ray, const Ray_Tracer* rt,
                    float t_min, float t_max, Ray_Hit& rh, bool shadow) const {

    // Absolute Triangle Vertex Positions
    V3& v0 = m->verts[inds[0]];
    V3& v1 = m->verts[inds[1]];
    V3& v2 = m->verts[inds[2]];

    // Two edges of triangle
    V3 e0, e1;
    e0 = v1 - v0;
    e1 = v2 - v0; 

    V3 p = ray.s.cross(e1);
    float deter = e0.dot(p);

    if (deter  > -EPSILON && deter < EPSILON)
        return false; 

    V3 t = ray.o - v0;
    
    // Store the inverse to reduce divisions
    float inv_deter = 1.0 / deter;
    float u = t.dot(p) * inv_deter;

    if (u < 0.0 || u > 1.0)
        return false;

    V3 q = t.cross(e0);
    float v = ray.s.dot(q) * inv_deter;

    if (v < 0.0 || u + v > 1.0)
        return false;

    float t_inter = e1.dot(q) * inv_deter;

    if (t_inter < t_min || t_inter > t_max) {
        //std::cout << "Cull: " << t_inter << '\t' <<t_min<< '\t' <<t_max<<  std::endl;
        return false;
    }

    rh.t = t_inter;
    rh.col = 0.2*m->mat.col;
    rh.shape = m;

    if (shadow || ray.depth >= rt->depth_limit)
        return true;

/*
    if (is_light) {     
        rh.col = Color(1.0, 1.0, 1.0);
        return true;
    }
*/

    V3 int_loc = ray.at(t_inter);
    // Shadow
    for (Shape* light : rt->lights) {

        // BIG ASSUMPTION THAT ALL LIGHTS ARE SPHERES
        Sphere* sph = static_cast<Sphere*>(light);

        // Make ray from intersection to light
        V3 int_to_light = sph->c - int_loc; 
        float dist_to_light = int_to_light.norm();
        int_to_light.normalize();
        Ray shadow_ray(int_loc + EPSILON*int_to_light, int_to_light, ray.depth + 1);
        Ray_Hit shadow_hit;
        if (rt->kd->hit_helper(true, rt->kd->root, shadow_ray, rt,
                EPSILON, dist_to_light, shadow_hit, true, 0)) {
            if (!shadow_hit.shape->is_light) {
                continue;
            }
        }

        float inner = int_to_light.dot(normal);
        if (inner > 0.0) {
            rh.col += sph->mat.col *inner* m->mat.diff * m->mat.col;
        }
    }

    // Reflection 
    V3 refl_dir = ray.s - 2.0f * (normal.dot(ray.s)) * normal;
    Ray refl_ray(int_loc + EPSILON*refl_dir, refl_dir, ray.depth + 1);
    Ray_Hit refl_hit;
    if (rt->kd->hit_helper(true, rt->kd->root, refl_ray, rt,
            EPSILON, FLT_MAX, refl_hit, false, 0)) {
    //if (rt->trace(refl_ray, EPSILON, FLT_MAX, refl_hit, false)) {
        rh.col += m->mat.refl*refl_hit.col * refl_hit.shape->mat.col;
    }

    return true;  
}
Exemple #24
0
bool Cylindre::intersect(const Ray& ray, Hit& hit) const
{

	/*bool top = topdisque()->intersect(ray,hit);
	bool bottom = bottomdisque()->intersect(ray,hit);
	return top || bottom;
*/
	// Determination de l'intersection

	// J'appelle I le point intersection s'il existe, O le point d'origine du rayon, D sa direction, R1 et R1 les rayons du cylindre, h sa hauteur
	// C l'origine du repere basé à la base du cylindre

	// on place le ray dans le répère associé au cylindre
	Ray ray_associe_cylindre(frame().coordinatesOf(ray.start()), frame().transformOf(ray.direction()));
	
	Vec I;
	Vec O = ray_associe_cylindre.start();
	const Vec& D = ray_associe_cylindre.direction();
	float R1,R2;

	
	R1 = bottomradius_;
	R2 = topradius_;
	

	float h = height_;

#ifdef DEBUG_INTERSEC
	std::cout << "TENTATIVE d'intersection du rayon :\n" << ray << "avec le cylindre\n" << *this << std::endl;
#endif
	
#ifdef DEBUG_INTERSEC
	std::cout << "rayon dans l'espace du cylindre : \n" << ray_associe_cylindre << std::endl;
#endif


// on vérifie que le ray pointe vers le cylindre
	if ( (frame().position() - ray.start())*ray.direction() < 0){
		
#ifdef DEBUG_INTERSEC
		std::cout << "PAS D'INTERSECTION : direction pointant en arrière" << std::endl;
#endif
		return false;
	}




	// On se place dans les coordonnées du cylindre pour tous les calculs et on a les équations suivantes :
	// Ix = Ox + tDx
	// Iy = Oy + tDy
	// Iz = Oz + tDz
	// Ix² + Iy² = (Iz/h*(R2-R1)+R1)² <=> Ix² + Iy² = Iz²/h²*(R2-R1)²   +  R1² +  2*(R2-R1)*R1*Iz/h

	// on remplace Ix, Iy et Iz dans la 4e equation pour obtenir une equation du 2nd degré en t
	// (Dx² + Dy² - Dz²*(R2-R1)²/h²)*t² + (2OxDx + 	2OyDy - (2OzDz)/h²*(R2-R1)² - 2Dz*(R2-R1)/h)*t + (Ox²+Oy²-Oz²/h²*(R2-R1)²-R1²-2*(R2-R1)*Oz/h = 0

	float a, b ,c;
	if (R1>R2){
		a = D.x*D.x + D.y*D.y -D.z*D.z*(R2-R1)*(R2-R1)/(h*h);
		b = 2*O.x*D.x+2*O.y*D.y - (2*O.z*D.z)*(R2-R1)*(R2-R1)/(h*h) - 2*D.z*R1*(R2-R1)/h;
		c = O.x*O.x+O.y*O.y-O.z*O.z*(R2-R1)*(R2-R1)/(h*h)-2*R1*(R2-R1)*O.z/h -R1*R1;
	}else
	{
		a = D.x*D.x + D.y*D.y -D.z*D.z*(R2-R1)*(R2-R1)/(h*h);
		b = 2*O.x*D.x+2*O.y*D.y - (2*O.z*D.z)*(R2-R1)*(R2-R1)/(h*h) - 2*D.z*R1*(R2-R1)/h;
		c = O.x*O.x+O.y*O.y-O.z*O.z*(R2-R1)*(R2-R1)/(h*h)-2*R1*(R2-R1)*O.z/h -R1*R1;
	
	}
	float delta = b*b-4*a*c;

#ifdef DEBUG_INTERSEC
		cout << "a : " << a << endl << "b : " << b << endl << "c :" << c << endl << "delta : " << delta << endl;
#endif

	

	if (delta < 0)
	{
#ifdef DEBUG_INTERSEC
		cout << "delta est négatif, il n'y a pas de solution" << endl;
#endif
		// pas de solution, il faut vérifier maintenant si on intersecte les disques supérieur ou inférieur
		bool inter_topdisque = topdisque_->intersect(ray,hit);
		bool inter_bottomdisque = bottomdisque_->intersect(ray,hit);
		return (inter_topdisque || inter_bottomdisque);
	}

	
	if (delta > 0)
	{
#ifdef DEBUG_INTERSEC
		cout << "delta est positif, il y a deux solutions" << endl;
#endif
		// deux solutions, le rayon entre et sort par la robe du cylindre
		float t;
		if (a == 0)
		{
			t = -c/b;
		}
		else{
			t = (-b-sqrt(delta))/(2*a);
		}	

		if ( t < 0 ){
#ifdef DEBUG_INTERSEC
			cout << "t < 0 " << endl;
			cout << "PAS D'INTERSECTION avec la robe du cylindre" << endl;
#endif
			return false;
		}
		
		// on calcule le point d'intersection	
		I.x = O.x + t*D.x;
		I.y = O.y + t*D.y;
		I.z = O.z + t*D.z;

#ifdef DEBUG_INTERSEC
		cout <<"I : " << I << endl;
#endif
	

		if (I.z < 0 || I.z > h)
		{
#ifdef DEBUG_INTERSEC
		cout << "t vaut : " << t << endl << "I.z vaut : " << I.z << endl;
		//cout << "PAS D'INTERSECTION avec la robe du cylindre" << endl;
#endif
		bool top = topdisque()->intersect(ray,hit);
		bool bottom = bottomdisque()->intersect(ray,hit);
		return top || bottom;
		}
		

		// on calcule la normale en ce point, dans les coordonnées du cylindre toujours

		float theta = 0;
		Vec normale;
		normale.x = I.x;
		normale.y = I.y;
		normale.z = 0;

		if (normale.norm() == 0)
		{
			cout << "la norme de la normale est nulle" << endl;
		}
	
		if (R1>=R2){
			theta = atan((R1-R2)/h);
			normale = normale * (1/normale.norm())*cos(theta);
			normale = normale + Vec(0,0,sin(theta));
		}
		else
		{
			theta = atan(h/(R2-R1));
			normale = normale * (1/normale.norm())*sin(theta);
			normale = normale - Vec(0,0,cos(theta));
		}
	
		if ( hit.time() > t){
			hit.setTime(t);
			Vec locale = frame().inverseTransformOf(I);
			hit.setIntersection(locale);
			hit.setNormal(frame().inverseTransformOf(normale));
			hit.setMaterial(material());
			computeUV(hit);
#ifdef DEBUG_INTERSEC
			displayIntersectionDebug(ray,hit,O,I,t);
#endif
			topdisque()->intersect(ray,hit);
			bottomdisque()->intersect(ray,hit);
			return true;
		}else{
			return false;
		}

	}
	
	if (delta ==0)
	{
#ifdef DEBUG_INTERSEC
		cout << "delta est nul, il y a une solution" << endl;
#endif
		// une solution, regarder si on intersecte les disques et comparer les time obtenu pour trouver le plus petit
		float t;
		if (a==0)
		{
			t = -c/b;
		} 
		else 
		{
			t=(-b/(2*a));
		}
		

		if (t<0)
		{
			//l'objet est derrière moi
#ifdef DEBUG_INTERSEC
			cout << "On est à l'intérieur de l'objet" << endl; 
#endif
			return false;
		}
		// on calcule le point d'intersection	
		I.x = O.x + t*D.x;
		I.y = O.y + t*D.y;
		I.z = O.z + t*D.z;

		// on calcule la normale en ce point, dans les coordonnées du cylindre toujours

		float theta;
		Vec normale;
		theta = atan((R1-R2)/h);
		normale.x = I.x;
		normale.y = I.y;
		normale.z = 0;

		if (normale.norm() == 0)
		{
			cout << "la norme de la normale est nulle" << endl;
		}

		normale = normale * (1/normale.norm())*cos(theta);

		normale = normale + Vec(0,0,sin(theta));

		if ( hit.time() > t){
			hit.setTime(t);
			hit.setIntersection(frame().inverseCoordinatesOf(I));
			hit.setNormal(frame().inverseCoordinatesOf(normale));
			hit.setMaterial(material());
			computeUV(hit);
#ifdef DEBUG_INTERSEC
			displayIntersectionDebug(ray,hit,O,I,t);
#endif
			topdisque()->intersect(ray,hit);
			bottomdisque()->intersect(ray,hit);
			return true;
		}else{
			return false;
		}

		
	}	  	

#ifdef DEBUG
	cerr << "Erreur lors du calcul de l'intersection d'un objet avec un rayon" << endl;
#endif
	return false;

}
  /// Computes the intersection of a ray and an infinite plane defined by three vertices
  RAYTRACER_EXPORTS static bool Helper1(const Ray& ray, const Vec3d &a, const Vec3d &b,
                        const Vec3d &c, Vec3d& uvw, double & lambda)
  {

  // Barycentric approach according to lecture slides
  // Ray: x=o+t*d
  // Barycentric Triangle: x=a*u+b*v+c*w
  // Solve: o+t*d = u*a+v*b+w*c

  // This is an inhomogeneous linear system
  // (ax bx cx -dx) (u) = ox 
  // (ay by cy -dy) (v) = oy
  // (az bz cz -dz) (w) = oz
  // (1  1  1   0 ) (t) = 1

  // or in short: A*x = o
  // Then, solution is given by A^-1 * o = x
  // with x = (u,v,w,t)^T
  /*
  const Vec3& o = ray.origin();
  const Vec3& d = ray.direction();
  Mat4 A;
  A(0,0)=a[0];A(0,1)=b[0];A(0,2)=c[0];A(0,3)=-d[0];
  A(1,0)=a[1];A(1,1)=b[1];A(1,2)=c[1];A(1,3)=-d[1];
  A(2,0)=a[2];A(2,1)=b[2];A(2,2)=c[2];A(2,3)=-d[2];
  A(3,0)=1   ;A(3,1)=1   ;A(3,2)=1   ;A(3,3)=0;

  A.invert();
  Vec4 x=A*Vec4(o,1);

  uvw[0] = x[0];
  uvw[1] = x[1];
  uvw[2] = x[2];
  lambda = x[3];

  return true;
  */

  /////////////////////////////////////////////////////////////////////////////
  /////////////////////////////////////////////////////////////////////////////
  /////////////////////////////////////////////////////////////////////////////

  //Approach by Moeller and Trumbore
  //see Fast, Minimum Storage RayTriangle Intersection
  // Ray: x=o+t*d
  // Barycentric Triangle: x=u*a+v*b+w*c
  // w=1-u-v
  // Therefore
  // x=u*a+v*b+(1-u-v)*c
  // Solve: o+t*d = u*a+v*b+(1-u-v)*c
  // Rearrange, then
  // (ax-cx bx-cx -dx) (u) = (ox-dx)
  // (ay-cy by-cy -dy) (v) = (oy-dy)
  // (az-cz bz-cz -dz) (t) = (oz-dz)
  // or in short: A*x = b
  // Then, solution is given by A^-1 * b = x
  // with x = (u,v,t)^T

  // This system can be solved using Cramer's rule
  // x_i = det(A_i) / det(A)
  // where the i-th column is replaced with b in the Matrix A_i
  //
  // e1 = a-c
  // e2 = b-c
  // tt = o-d

  // then
  // (        ) (u)  
  // (e1 e2 -d) (v) =  tt
  // (        ) (t)

  // with
  // (u)                    ( det(tt,e2,-d) )
  // (v) = 1/det(e1,e2,-d)* ( det(e1,tt,-d) )
  // (t)                    ( det(e1,e2,tt) )

  //use triple scalar product
  // det(a,b,c) = a * (b x c) = b * (c x a) = c*(a x b)  , and
  // a * (b x c) = -a * (c x b)

  // then
  // (u)                    ( tt * (e2 x -d) )
  // (v) = e1*(e2 x -d)     ( e1 * (tt x -d) )
  // (t)                    ( e1 * (e2 x tt) )

  //rearrange terms for u,t
  // (u)                    ( tt * (e2 x -d) )
  // (v) = e1*(e2 x -d)     ( -d * (e1 x tt) )
  // (t)                    (-e2 * (e1 x tt) )
  // reuse expensive terms
  // pp = e2 x -d
  // qq = e1 x tt
  // then
  // (u)                    ( tt * pp )
  // (v) = e1*pp            ( -d * qq )
  // (t)                    (-e2 * qq )

    const Vec3d& o = ray.origin();
    const Vec3d& d = ray.direction();
    Vec3d e1 = a-c;
    Vec3d e2 = b-c;
    Vec3d tt = o-c;
    Vec3d pp = cross(e2,-d);
    Vec3d qq = cross(e1,tt);

    double detA = dot(e1,pp);

    if(fabs(detA) < Math::safetyEps())
      return false;

    uvw[0] = (dot( tt,pp))/detA;
    uvw[1] = (dot( -d,qq))/detA;
    uvw[2] = 1-uvw[0]-uvw[1];
    lambda = (dot(-e2,qq))/detA;

    return true;

  }
Exemple #26
0
//--------------------------------------------------------------------------------------------------
/// Intersect the drawable geo with the ray and return the closest intersection point and the face hit
///
/// Returns true if anything was hit.
//--------------------------------------------------------------------------------------------------
bool DrawableGeo::rayIntersect(const Ray& ray, Vec3d* intersectionPoint, uint* faceHit) const
{
    CVF_ASSERT(intersectionPoint);

    bool anyHits = false;
    double minDistSquared = 1.0e300;

    cref<Vec3fArray> vertexArr = m_vertexBundle->vertexArray();

    size_t numPrimitiveSets = m_primitiveSets.size();
    size_t iPrimSet;
    int accumulatedFaceCount = 0;

    for (iPrimSet = 0; iPrimSet < numPrimitiveSets; iPrimSet++)
    {
        const PrimitiveSet* primSet = m_primitiveSets.at(iPrimSet);
        CVF_TIGHT_ASSERT(primSet);

        UIntArray conn;
        int numPrimFaces = static_cast<int>(primSet->faceCount());

#pragma omp parallel for private (conn)
        for (int i = 0; i < numPrimFaces; i++)
        {
            bool hitThisFace = false;
            Vec3d localIntersect;

            primSet->getFaceIndices(static_cast<size_t>(i), &conn);
            int numconn = static_cast<int>(conn.size());
            CVF_TIGHT_ASSERT(numconn <= 3);
            if (numconn == 3)
            {
                hitThisFace = ray.triangleIntersect(Vec3d(vertexArr->get(conn[0])), 
                                                    Vec3d(vertexArr->get(conn[1])), 
                                                    Vec3d(vertexArr->get(conn[2])), 
                                                    &localIntersect);
            }

            if (hitThisFace)
            {
                double distSquared = (ray.origin() - localIntersect).lengthSquared();
                #pragma omp critical
		{
                    if (distSquared < minDistSquared)
                    {
                        *intersectionPoint = localIntersect;
                        minDistSquared = distSquared;

                        if (faceHit)
                        {
                            *faceHit = i + accumulatedFaceCount;
                        }
                    }
                    anyHits = true;
		}
            }
        } // End omp parallel for
        accumulatedFaceCount += numPrimFaces;
    }

    return anyHits;
}
Exemple #27
0
Intersection Cube::GetIntersection(Ray r)
{
    //Transform the ray
    Ray r_loc = r.GetTransformedCopy(transform.invT());
    Intersection result;

    float t_n = -1000000.f;
    float t_f = 1000000.f;
    for(int i = 0; i < 3; i++){
        //Ray parallel to slab check
        if(r_loc.direction[i] == 0){
            if(r_loc.origin[i] < -0.5f || r_loc.origin[i] > 0.5f){
                return result;
            }
        }
        //If not parallel, do slab intersect check
        float t0 = (-0.5f - r_loc.origin[i])/r_loc.direction[i];
        float t1 = (0.5f - r_loc.origin[i])/r_loc.direction[i];
        if(t0 > t1){
            float temp = t1;
            t1 = t0;
            t0 = temp;
        }
        if(t0 > t_n){
            t_n = t0;
        }
        if(t1 < t_f){
            t_f = t1;
        }
    }
    float t_final = -1;
    if(t_n < t_f)
    {
        if(t_n >= 0)
        {
            t_final = t_n;
        }
        else if(t_f >= 0)
        {
            t_final = t_f;
        }
    }
    if(t_final >= 0)
    {
        //Lastly, transform the point found in object space by T
        glm::vec4 P = glm::vec4(r_loc.origin + t_final*r_loc.direction, 1);
        glm::vec4 N( glm::normalize( GetCubeNormal( P ) ) );
        result.point = glm::vec3(transform.T() * P);
        result.normal = glm::normalize(glm::vec3(transform.invTransT() * N));
        result.object_hit = this;
        result.t = glm::distance(result.point, r.origin);
        result.texture_color = Material::GetImageColorInterp(GetUVCoordinates(glm::vec3(P)), material->texture);
        //TODO: Store the tangent and bitangent

        glm::vec4 T( 0.f ), B( 0.f );

        if( N[ 0 ] < -.9f ){
            T = glm::vec4( 0.f, -1.f, 0.f, 0.f );
        }else if( N[ 0 ] > .9f ){
            T = glm::vec4( 0.f, 1.f, 0.f, 0.f );
        }else if( N[ 1 ] < -.9f ){
            T = glm::vec4( 0.f, 0.f, -1.f, 0.f );
        }else if( N[ 1 ] > .9f ){
            T = glm::vec4( 0.f, 0.f, 1.f, 0.f );
        }else if( N[ 2 ] < -.9f ){
            T = glm::vec4( -1.f, 0.f, 0.f, 0.f );
        }else{
            T = glm::vec4( 1.f, 0.f, 0.f, 0.f );
        }

        B = glm::vec4( glm::cross( glm::vec3( N ), glm::vec3( T ) ), 0.f );

        result.tangent = glm::normalize( glm::vec3( transform.T() * T ) );
        result.bitangent = glm::normalize( glm::vec3( transform.T() * B ) );

        return result;
    }
    else{
        return result;
    }
}
bool Box::intersect( const Ray& r, Hit& h, float tmin ) const
{
	float maxToCam = (r.getOrigin() - this->m_max).length();
	float minToCam = (r.getOrigin() - this->m_min).length();

	Vec3f direction = r.getDirection();
	Vec3f origin = r.getOrigin();

	// Keep the direction values sane, we don't want to divide by zero
	if (direction.x == 0.0f)
		direction.x += EPSILON;
	if (direction.y == 0.0f)
		direction.y += EPSILON;
	if (direction.z == 0.0f)
		direction.z += EPSILON;

	float min, max, ymin, ymax, zmin, zmax;

	// Calculate the maximum and minimum on the x-axis
	float divx = 1.0f/direction.x;
	if (divx >= 0) {
		min = (this->m_min.x - origin.x) * divx;
		max = (this->m_max.x - origin.x) * divx;
	}
	else {
		min = (this->m_max.x - origin.x) * divx;
		max = (this->m_min.x - origin.x) * divx;
	}

	// Calculate the maximum and minimum on the y-axis
	float divy = 1.0f/direction.y;
	if (divy >= 0) {
		ymin = (this->m_min.y - origin.y) * divy;
		ymax = (this->m_max.y - origin.y) * divy;
	}
	else {
		ymin = (this->m_max.y - origin.y) * divy;
		ymax = (this->m_min.y - origin.y) * divy;
	}

	if ( (min > ymax) || (ymin > max) )
		return false;

	// Make sure the tmin and tmax hold the most binding values
	if (ymin > min)
		min = ymin;
	if (ymax < max)
		max = ymax;

	// Calculate the maximum and minimum on the z-axis
	float divz = 1.0f/direction.z;
	if (divz >= 0) {
		zmin = (this->m_min.z - origin.z) * divz;
		zmax = (this->m_max.z - origin.z) * divz;
	}
	else {
		zmin = (this->m_max.z - origin.z) * divz;
		zmax = (this->m_min.z - origin.z) * divz;
	}

	if ( (min > zmax) || (zmin > max ) )
		return false;
	
	// Make sure the tmin and tmax hold the most binding values
	if (zmin > min)
		min = zmin;
	if (zmax < max)
		max = zmax;

	if ( (min < h.getT() && (max > tmin)) ) {
		// Calculate the normal and set the values
		Vec3f point = r.pointAtParameter(min);
		Vec3f normal;

		if (FW::abs(point.x - this->m_min.x) < EPSILON)
			normal = Vec3f(-1.0f, 0.0f, 0.0f);
		else if (FW::abs(point.x - this->m_max.x) < EPSILON)
			normal = Vec3f(1.0f, 0.0f, 0.0f);
		else if (FW::abs(point.y - this->m_min.y) < EPSILON)
			normal = Vec3f(0.0f, -1.0f, 0.0f);
		else if (FW::abs(point.y - this->m_max.y) < EPSILON)
			normal = Vec3f(0.0f, 1.0f, 0.0f);
		else if (FW::abs(point.z - this->m_min.z) < EPSILON)
			normal = Vec3f(0.0f, 0.0f, -1.0f);
		else if (FW::abs(point.z - this->m_max.z) < EPSILON)
			normal = Vec3f(0.0f, 0.0f, 1.0f);
		else
			std::cerr << "ERROR: Could not calculate the normal in box intersect." << std::endl;

		h.set(min, this->m_material, normal);
		return true;
	}

	return false;
} 
Exemple #29
0
Ray Renderable::transformRayWorldToModel(const Ray &ray) const
{
  this->updateTransforms();
  return ray.transformed(mTransformInv);
}
Exemple #30
0
int lua_Ray_setOrigin(lua_State* state)
{
    // Get the number of parameters.
    int paramCount = lua_gettop(state);

    // Attempt to match the parameters to a valid binding.
    switch (paramCount)
    {
        case 2:
        {
            do
            {
                if ((lua_type(state, 1) == LUA_TUSERDATA) &&
                    (lua_type(state, 2) == LUA_TUSERDATA || lua_type(state, 2) == LUA_TNIL))
                {
                    // Get parameter 1 off the stack.
                    bool param1Valid;
                    gameplay::ScriptUtil::LuaArray<Vector3> param1 = gameplay::ScriptUtil::getObjectPointer<Vector3>(2, "Vector3", true, &param1Valid);
                    if (!param1Valid)
                        break;

                    Ray* instance = getInstance(state);
                    instance->setOrigin(*param1);
                    
                    return 0;
                }
            } while (0);

            lua_pushstring(state, "lua_Ray_setOrigin - Failed to match the given parameters to a valid function signature.");
            lua_error(state);
            break;
        }
        case 4:
        {
            do
            {
                if ((lua_type(state, 1) == LUA_TUSERDATA) &&
                    lua_type(state, 2) == LUA_TNUMBER &&
                    lua_type(state, 3) == LUA_TNUMBER &&
                    lua_type(state, 4) == LUA_TNUMBER)
                {
                    // Get parameter 1 off the stack.
                    float param1 = (float)luaL_checknumber(state, 2);

                    // Get parameter 2 off the stack.
                    float param2 = (float)luaL_checknumber(state, 3);

                    // Get parameter 3 off the stack.
                    float param3 = (float)luaL_checknumber(state, 4);

                    Ray* instance = getInstance(state);
                    instance->setOrigin(param1, param2, param3);
                    
                    return 0;
                }
            } while (0);

            lua_pushstring(state, "lua_Ray_setOrigin - Failed to match the given parameters to a valid function signature.");
            lua_error(state);
            break;
        }
        default:
        {
            lua_pushstring(state, "Invalid number of parameters (expected 2 or 4).");
            lua_error(state);
            break;
        }
    }
    return 0;
}