示例#1
0
Real
raySphereIntersectionTime(Ray3 const & ray, Vector3 const & center, Real radius)
{
  Vector3 pmc = ray.getOrigin() - center;

  double s[3];
  s[2] = ray.getDirection().squaredLength();
  s[1] = 2 * pmc.dot(ray.getDirection());
  s[0] = pmc.squaredLength() - radius * radius;

  double roots[2];
  int num_roots = Math::solveQuadratic(s[0], s[1], s[2], roots);

  double min_root = -1;
  for (int i = 0; i < num_roots; ++i)
    if (roots[i] >= 0 && (min_root < 0 || roots[i] < min_root))
      min_root = roots[i];

#if 0
  if (min_root >= 0)
    qDebug() << "min_root =" << min_root;
#endif

  return (Real)min_root;
}
	IResult Intersects(const Ray3& ray, const Transformation& objT) const{
		if (!mBV)
			return IResult(false, FLT_MAX);
		Ray3 localRay = objT.ApplyInverse(ray);
		Ray3::IResult ret = localRay.Intersects(mBV.get());
		return ret;
	}
//----------------------------------------------------------------------------
bool Mgc::FindIntersection (const Ray3& rkRay, const Triangle3& rkTriangle,
    Vector3& rkPoint)
{
    Real fRayP;
    if ( SqrDistance(rkRay,rkTriangle,&fRayP) <= gs_fEpsilon )
    {
        rkPoint = rkRay.Origin() + fRayP*rkRay.Direction();
        return true;
    }
    return false;
}
	void GatherPointLightData(const BoundingVolume* aabb, const Transformation& transform, POINT_LIGHT_CONSTANTS* plConst)
	{
		struct GatheredData
		{
			GatheredData(Real distSQ, unsigned idx)
				:mDistanceSQ(distSQ), mIndex(idx)
			{

			}
			Real mDistanceSQ;
			unsigned mIndex;
		};
		static std::vector<GatheredData> gathered;
		gathered.reserve(50);

		unsigned i = 0;
		for (auto it = mPointLights.begin(); it != mPointLights.end(); /**/)
		{		
			IteratingWeakContainer(mPointLights, it, p);
			if (!p->GetEnabled())
				continue;
			Ray3 ray(p->GetPosition(), transform.GetTranslation() - p->GetPosition());
			Ray3 localRay = transform.ApplyInverse(ray);
			auto iresult = localRay.Intersects(aabb);
			Real distSQ = Squared(iresult.second);
			Real range = p->GetRange();
			if (distSQ < (range*range))
			{
				gathered.push_back(GatheredData(distSQ, i));
			}
			++i;
		}

		std::sort(gathered.begin(), gathered.end(), [](const GatheredData& a, const GatheredData& b){
			return a.mDistanceSQ < b.mDistanceSQ;
		}
		);

		plConst->gPointLightColor[0].w = 0;
		int count = std::min(3, (int)gathered.size());
		unsigned validNumber = 0;
		for (int i = 0; i < count; i++)
		{
			PointLightPtr p = mPointLights[gathered[i].mIndex].lock();
			if (p){
				plConst->gPointLightPos[validNumber] = Vec4(p->GetPosition(), p->GetRange());
				plConst->gPointLightColor[validNumber] = Vec4(p->GetColorPowered(), (Real)count);
				++validNumber;
			}
		}

		gathered.clear();
	}
 void SpikeGuideRenderer::addSpike(const Ray3& ray, const FloatType length, const FloatType maxLength) {
     const float mix = static_cast<float>(maxLength / length / 2.0);
     
     m_spikeVertices.push_back(SpikeVertex(ray.origin, m_color));
     m_spikeVertices.push_back(SpikeVertex(ray.pointAtDistance(length),
                               Color(m_color, m_color.a() * mix)));
 }
示例#6
0
Color rayTraceRecursive(Object &scene, Ray3& ray, int maxReflect, DirectionalLight light)
{
	IntersectResult result = scene.intersect(ray);

	//cout<<result.getGeometry()->material->getReflectiveness()<<endl;
	if(result.getGeometry())
	{
		Color color = Color::black;
		Vec3 lightSample = light.sample(scene, result.getPosition());
		//cout<<lightSample.getx()<< " " << lightSample.gety() << " "<<lightSample.getz()<<endl;
		float reflectiveness = result.getGeometry()->material->getReflectiveness(); 	// just the float to int. it is rediculous
		color = result.getGeometry()->material->sample(ray,result.getPosition(),result.getNormal());
		color = color.multiply(1-reflectiveness);

		//	cout << reflectiveness <<endl;
		if(reflectiveness>0 && maxReflect > 0)
		{
			//			cout << reflectiveness <<endl;
			Vec3 r = result.getNormal().multiply(-2*result.getNormal().dot(ray.getDirection())).add(ray.getDirection());
			ray = Ray3(result.getPosition(),r);
			Color reflectedColor = rayTraceRecursive(scene, ray, maxReflect-1,  light);
			color = color.add(reflectedColor.multiply(reflectiveness));
			if(fabs(lightSample.getx())> 1e-4 || fabs(lightSample.gety())> 1e-4 || fabs(lightSample.getz()>1e-4))
			{
			}else{
				color = color.modulate(Color(0.3,0.3,0.3));
			}
		}
		//cout<<"abc"<<endl;
		return color;
	}else{
		return Color::black;
	}
}
//----------------------------------------------------------------------------
bool Mgc::TestIntersection (const Ray3& rkRay, const Box3& rkBox)
{
    Real fWdU[3], fAWdU[3], fDdU[3], fADdU[3], fAWxDdU[3], fRhs;

    Vector3 kDiff = rkRay.Origin() - rkBox.Center();

    fWdU[0] = rkRay.Direction().Dot(rkBox.Axis(0));
    fAWdU[0] = Math::FAbs(fWdU[0]);
    fDdU[0] = kDiff.Dot(rkBox.Axis(0));
    fADdU[0] = Math::FAbs(fDdU[0]);
    if ( fADdU[0] > rkBox.Extent(0) && fDdU[0]*fWdU[0] >= 0.0f )
        return false;

    fWdU[1] = rkRay.Direction().Dot(rkBox.Axis(1));
    fAWdU[1] = Math::FAbs(fWdU[1]);
    fDdU[1] = kDiff.Dot(rkBox.Axis(1));
    fADdU[1] = Math::FAbs(fDdU[1]);
    if ( fADdU[1] > rkBox.Extent(1) && fDdU[1]*fWdU[1] >= 0.0f )
        return false;

    fWdU[2] = rkRay.Direction().Dot(rkBox.Axis(2));
    fAWdU[2] = Math::FAbs(fWdU[2]);
    fDdU[2] = kDiff.Dot(rkBox.Axis(2));
    fADdU[2] = Math::FAbs(fDdU[2]);
    if ( fADdU[2] > rkBox.Extent(2) && fDdU[2]*fWdU[2] >= 0.0f )
        return false;

    Vector3 kWxD = rkRay.Direction().Cross(kDiff);

    fAWxDdU[0] = Math::FAbs(kWxD.Dot(rkBox.Axis(0)));
    fRhs = rkBox.Extent(1)*fAWdU[2] + rkBox.Extent(2)*fAWdU[1];
    if ( fAWxDdU[0] > fRhs )
        return false;

    fAWxDdU[1] = Math::FAbs(kWxD.Dot(rkBox.Axis(1)));
    fRhs = rkBox.Extent(0)*fAWdU[2] + rkBox.Extent(2)*fAWdU[0];
    if ( fAWxDdU[1] > fRhs )
        return false;

    fAWxDdU[2] = Math::FAbs(kWxD.Dot(rkBox.Axis(2)));
    fRhs = rkBox.Extent(0)*fAWdU[1] + rkBox.Extent(1)*fAWdU[0];
    if ( fAWxDdU[2] > fRhs )
        return false;

    return true;
}
示例#8
0
Real
closestPtRayTriangle(Ray3 const & ray, Vector3 const & v0, Vector3 const & edge01, Vector3 const & edge02, Real & s,
                     Vector3 & c1, Vector3 & c2)
{
  Real sqdist = closestPtLineTriangle(Line3::fromPointAndDirection(ray.getOrigin(), ray.getDirection()), v0, edge01, edge02,
                                      s, c1, c2);
  if (s >= 0)
    return sqdist;

  // Not the most efficient way but the most convenient
  LocalTriangle3 tri(v0, v0 + edge01, v0 + edge02);
  s = 0;
  c1 = ray.getOrigin();
  c2 = tri.closestPoint(c1);

  return (c1 - c2).squaredLength();
}
示例#9
0
//----------------------------------------------------------------------------
// @ BoundingSphere::Intersect()
// ---------------------------------------------------------------------------
// Determine intersection between sphere and ray
//-----------------------------------------------------------------------------
bool
BoundingSphere::Intersect( const Ray3& ray ) const
{
    // compute intermediate values
    Vector3 w = mCenter - ray.GetOrigin();
    float wsq = w.Dot(w);
    float proj = w.Dot(ray.GetDirection());
    float rsq = mRadius*mRadius;

    // if sphere behind ray, no intersection
    if ( proj < 0.0f && wsq > rsq )
        return false;
    float vsq = ray.GetDirection().Dot(ray.GetDirection());

    // test length of difference vs. radius
    return ( vsq*wsq - proj*proj <= vsq*rsq );
}
 Model::Hit VertexHandleManager::pickHandle(const Ray3& ray, const Renderer::Camera& camera, const Vec3& position, Model::Hit::HitType type) const {
     const FloatType distance = camera.pickPointHandle(ray, position, pref(Preferences::HandleRadius));
     if (!Math::isnan(distance)) {
         const Vec3 hitPoint = ray.pointAtDistance(distance);
         return Model::Hit::hit<Vec3>(type, distance, hitPoint, position);
     }
     
     return Model::Hit::NoHit;
 }
//----------------------------------------------------------------------------
Real Mgc::SqrDistance (const Ray3& rkRay, const Box3& rkBox, Real* pfLParam,
    Real* pfBParam0, Real* pfBParam1, Real* pfBParam2)
{
#ifdef _DEBUG
    // The four parameters pointers are either all non-null or all null.
    if ( pfLParam )
    {
        assert( pfBParam0 && pfBParam1 && pfBParam2 );
    }
    else
    {
        assert( !pfBParam0 && !pfBParam1 && !pfBParam2 );
    }
#endif

    Line3 kLine;
    kLine.Origin() = rkRay.Origin();
    kLine.Direction() = rkRay.Direction();

    Real fLP, fBP0, fBP1, fBP2;
    Real fSqrDistance = SqrDistance(kLine,rkBox,&fLP,&fBP0,&fBP1,&fBP2);
    if ( fLP >= 0.0f )
    {
        if ( pfLParam )
        {
            *pfLParam = fLP;
            *pfBParam0 = fBP0;
            *pfBParam1 = fBP1;
            *pfBParam2 = fBP2;
        }

        return fSqrDistance;
    }
    else
    {
        fSqrDistance = SqrDistance(rkRay.Origin(),rkBox,pfBParam0,
            pfBParam1,pfBParam2);

        if ( pfLParam )
            *pfLParam = 0.0f;

        return fSqrDistance;
    }
}
示例#12
0
Real Mgc::SqrDistance (const Vector3& rkPoint, const Ray3& rkRay,

    Real* pfParam)

{

    Vector3 kDiff = rkPoint - rkRay.Origin();

    Real fT = kDiff.Dot(rkRay.Direction());



    if ( fT <= 0.0f )

    {

        fT = 0.0f;

    }

    else

    {

        fT /= rkRay.Direction().SquaredLength();

        kDiff -= fT*rkRay.Direction();

    }



    if ( pfParam )

        *pfParam = fT;



    return kDiff.SquaredLength();

}
示例#13
0
Real Wml::SqrDistance (const Vector3<Real>& rkPoint, const Ray3<Real>& rkRay,
    Real* pfParam)
{
    Vector3<Real> kDiff = rkPoint - rkRay.Origin();
    Real fT = kDiff.Dot(rkRay.Direction());

    if ( fT <= (Real)0.0 )
    {
        fT = (Real)0.0;
    }
    else
    {
        fT /= rkRay.Direction().SquaredLength();
        kDiff -= fT*rkRay.Direction();
    }

    if ( pfParam )
        *pfParam = fT;

    return kDiff.SquaredLength();
}
示例#14
0
bool Wml::FindIntersection (const Ray3<Real>& rkRay,
    const Cylinder3<Real>& rkCylinder, int& riQuantity,
    Vector3<Real> akPoint[2])
{
    Real afT[2];

    if ( rkCylinder.Capped() )
    {
        riQuantity = Find(rkRay.Origin(),rkRay.Direction(),rkCylinder,afT);
    }
    else
    {
        riQuantity = FindHollow(rkRay.Origin(),rkRay.Direction(),
            rkCylinder,afT);
    }

    int iClipQuantity = 0;
    for (int i = 0; i < riQuantity; i++)
    {
        if ( afT[i] >= (Real)0.0 )
        {
            akPoint[iClipQuantity++] = rkRay.Origin() +
                afT[i]*rkRay.Direction();
        }
    }

    riQuantity = iClipQuantity;
    return riQuantity > 0;
}
 void SpikeGuideRenderer::add(const Ray3& ray, const FloatType length, View::MapDocumentSPtr document) {
     Model::PickResult pickResult = Model::PickResult::byDistance(document->editorContext());
     document->pick(ray, pickResult);
     
     const Model::Hit& hit = pickResult.query().pickable().type(Model::Brush::BrushHit).occluded().minDistance(1.0).first();
     if (hit.isMatch()) {
         if (hit.distance() <= length)
             addPoint(ray.pointAtDistance(hit.distance() - 0.01));
         addSpike(ray, Math::min(length, hit.distance()), length);
     } else {
         addSpike(ray, length, length);
     }
     m_valid = false;
 }
示例#16
0
Real
rayTorusIntersectionTime(Ray3 const & ray, Real torus_radius, Real torus_width)
{
  double r2pw2 = torus_radius * torus_radius + torus_width * torus_width;
  double r2mw2 = r2pw2 - 2 * torus_width * torus_width;

  Vector3 p2 = ray.getOrigin() * ray.getOrigin();
  Vector3 pu = ray.getOrigin() * ray.getDirection();
  Vector3 u2 = ray.getDirection() * ray.getDirection();

  double s[5];
  s[4] = u2[0] * (u2[0] + 2 * u2[1]) + u2[1] * (u2[1] + 2 * u2[2]) + u2[2] * (u2[2] + 2 * u2[0]);
  s[3] = 4 * (pu[0] + pu[1] + pu[2]) * (u2[0] + u2[1] + u2[2]);
  s[2] = 2 * (r2mw2 * u2[2] - r2pw2 * (u2[0] + u2[1]))
       + 8 * (pu[0] * pu[1] + pu[1] * pu[2] + pu[2] * pu[0])
       + 6 * (pu[0] * pu[0] + pu[1] * pu[1] + pu[2] * pu[2])
       + 2 * (p2[0] * (u2[1] + u2[2]) + p2[1] * (u2[2] + u2[0]) + p2[2] * (u2[0] + u2[1]));
  s[1] = 4 * (r2mw2 * pu[2] - r2pw2 * (pu[0] + pu[1]) + (p2[0] + p2[1] + p2[2]) * (pu[0] + pu[1] + pu[2]));
  s[0] = 2 * (r2mw2 * p2[2] - r2pw2 * (p2[0] + p2[1]) + p2[0] * p2[1] + p2[1] * p2[2] + p2[2] * p2[0])
       + p2[0] * p2[0] + p2[1] * p2[1] + p2[2] * p2[2] + r2mw2 * r2mw2;

  double roots[4];
  int num_roots = Math::solveQuartic(s[0], s[1], s[2], s[3], s[4], roots);

  double min_root = -1;
  for (int i = 0; i < num_roots; ++i)
    if (roots[i] >= 0 && (min_root < 0 || roots[i] < min_root))
      min_root = roots[i];

#if 0
  if (min_root >= 0)
    qDebug() << "min_root =" << min_root;
#endif

  return (Real)min_root;
}
示例#17
0
Color PhongMaterial::sample(const Ray3& ray, const Vec3& position, const Vec3& normal)
{
	// i don't know why global will lead to ld error
	//Vec3 lightDir = Vec3(1,1,1).normalize();
	//Color lightColor = Color::white;

//	Vec3 lightDir = Vec3(1,1,1).normalize();
	DirectionalLight lightDir(Vec3(-1,-1,-1));

	Color lightColor = Color::white;

	float NdotL = normal.dot(lightDir.L);
	//cout << "NdotL: " << NdotL << endl;
	Vec3 H = lightDir.L.substract(ray.getDirection()).normalize();
	float NdotH = normal.dot(H);
	//cout << "NdotH: " << NdotH << endl;
	Color diffuseTerm = diffuse.multiply(fmax(NdotL,0));
	Color specularTerm = specular.multiply( pow( fmax(NdotH,0), shininess));
//	cout << "diffTerm: " << diffuseTerm.getR() << " "<<diffuseTerm.getG() << " " << diffuseTerm.getB()  << endl;
//	cout << "specTerm: " << specularTerm.getR() << " " << specularTerm.getG() << " " << specularTerm.getB() << endl;
	
	Color ret = lightColor.modulate(diffuseTerm.add(specularTerm));
	if(ret.getR()>1) 	// it is possible that the color is overflow
	{
		ret.setR(1);

	}
	if(ret.getB()>1)
	{
		ret.setB(1);
	}
	if(ret.getG()>1)
	{
		ret.setG(1);
	}

	Color add = diffuseTerm.add(specularTerm);
	Color modulate = lightColor.modulate((add));

	//cout << "add: " << add.getR() << " " << add.getG() << " " << add.getB() << endl;
	//cout << "modulate: " << modulate.getR() << " " << modulate.getG() << " " << modulate.getB() << endl;

	//cout << "lightColor: " << lightColor.getR() << " " << lightColor.getG() << " " << lightColor.getB() << endl;


	//cout << "ret: " << ret.getR() << " " << ret.getG() << " " << ret.getB() << endl;
	return ret;
}
//----------------------------------------------------------------------------
bool Mgc::FindIntersection (const Ray3& rkRay, const Box3& rkBox,
    int& riQuantity, Vector3 akPoint[2])
{
    // convert ray to box coordinates
    Vector3 kDiff = rkRay.Origin() - rkBox.Center();
    Vector3 kOrigin(
        kDiff.Dot(rkBox.Axis(0)),
        kDiff.Dot(rkBox.Axis(1)),
        kDiff.Dot(rkBox.Axis(2))
    );
    Vector3 kDirection(
        rkRay.Direction().Dot(rkBox.Axis(0)),
        rkRay.Direction().Dot(rkBox.Axis(1)),
        rkRay.Direction().Dot(rkBox.Axis(2))
    );

    Real fT0 = 0.0f, fT1 = Math::MAX_REAL;
    bool bIntersects = FindIntersection(kOrigin,kDirection,rkBox.Extents(),
        fT0,fT1);

    if ( bIntersects )
    {
        if ( fT0 > 0.0f )
        {
            riQuantity = 2;
            akPoint[0] = rkRay.Origin() + fT0*rkRay.Direction();
            akPoint[1] = rkRay.Origin() + fT1*rkRay.Direction();
        }
        else  // fT0 == 0
        {
            riQuantity = 1;
            akPoint[0] = rkRay.Origin() + fT1*rkRay.Direction();
        }
    }
    else
    {
        riQuantity = 0;
    }

    return bIntersects;
}
 void CreateEntityTool::updateEntityPosition3D(const Ray3& pickRay, const Model::PickResult& pickResult) {
     assert(m_entity != NULL);
     
     MapDocumentSPtr document = lock(m_document);
     
     Vec3 delta;
     const Grid& grid = document->grid();
     const Model::Hit& hit = pickResult.query().pickable().type(Model::Brush::BrushHit).occluded().first();
     if (hit.isMatch()) {
         const Model::BrushFace* face = Model::hitToFace(hit);
         const Plane3 dragPlane = alignedOrthogonalDragPlane(hit.hitPoint(), face->boundary().normal);
         delta = grid.moveDeltaForBounds(dragPlane, m_entity->bounds(), document->worldBounds(), pickRay, hit.hitPoint());
     } else {
         const Vec3 newPosition = pickRay.pointAtDistance(Renderer::Camera::DefaultPointDistance);
         const Vec3 center = m_entity->bounds().center();
         delta = grid.moveDeltaForPoint(center, document->worldBounds(), newPosition - center);
     }
     
     if (delta.null())
         return;
     
     document->translateObjects(delta);
 }
        void CreateEntityTool::updateEntityPosition2D(const Ray3& pickRay) {
            assert(m_entity != NULL);
            
            MapDocumentSPtr document = lock(m_document);

            const Vec3 toMin = m_referenceBounds.min - pickRay.origin;
            const Vec3 toMax = m_referenceBounds.max - pickRay.origin;
            const Vec3 anchor = toMin.dot(pickRay.direction) > toMax.dot(pickRay.direction) ? m_referenceBounds.min : m_referenceBounds.max;
            const Plane3 dragPlane(anchor, -pickRay.direction);
            
            const FloatType distance = dragPlane.intersectWithRay(pickRay);
            if (Math::isnan(distance))
                return;
            
            const Vec3 hitPoint = pickRay.pointAtDistance(distance);
            
            const Grid& grid = document->grid();
            const Vec3 delta = grid.moveDeltaForBounds(dragPlane, m_entity->bounds(), document->worldBounds(), pickRay, hitPoint);
            
            if (delta.null())
                return;
            
            document->translateObjects(delta);
        }
 bool ResizeBrushesTool::resize(const Ray3& pickRay, const Renderer::Camera& camera) {
     assert(!m_dragFaces.empty());
     
     Model::BrushFace* dragFace = m_dragFaces.front();
     const Vec3& faceNormal = dragFace->boundary().normal;
     
     const Ray3::LineDistance distance = pickRay.distanceToLine(m_dragOrigin, faceNormal);
     if (distance.parallel)
         return true;
     
     const FloatType dragDist = distance.lineDistance;
     
     MapDocumentSPtr document = lock(m_document);
     const View::Grid& grid = document->grid();
     const Vec3 relativeFaceDelta = grid.snap(dragDist) * faceNormal;
     const Vec3 absoluteFaceDelta = grid.moveDelta(dragFace, faceNormal * dragDist);
     
     const Vec3 faceDelta = selectDelta(relativeFaceDelta, absoluteFaceDelta, dragDist);
     if (faceDelta.null())
         return true;
     
     if (m_splitBrushes) {
         if (splitBrushes(faceDelta)) {
             m_totalDelta += faceDelta;
             m_dragOrigin += faceDelta;
             m_splitBrushes = false;
         }
     } else {
         if (document->resizeBrushes(m_dragFaces, faceDelta)) {
             m_totalDelta += faceDelta;
             m_dragOrigin += faceDelta;
         }
     }
     
     return true;
 }
示例#22
0
bool BVaabb::TestIntersection(const Ray3& ray) const
{
	Vec3 normal;
	Ray3::IResult ret = ray.Intersects(mAABB, normal);
	return ret.first;
}
示例#23
0
// Intersect (Ray3)
//------------------------------------------------------------------------------
bool AABB3::Intersect( const Ray3 & ray, float & dist ) const
{
    const float ox = ray.GetOrigin().x;
    const float oy = ray.GetOrigin().y;
    const float oz = ray.GetOrigin().z;
    const float dx = ray.GetDir().x;
    const float dy = ray.GetDir().y;
    const float dz = ray.GetDir().z;

    float tx_min, ty_min, tz_min;
    float tx_max, ty_max, tz_max;

    // x
    float a = 1.f/dx;
    if ( a >= 0 )
    {
        tx_min = ( m_Min.x-ox ) * a;
        tx_max = ( m_Max.x-ox ) * a;
    }
    else
    {
        tx_min = ( m_Max.x-ox ) * a;
        tx_max = ( m_Min.x-ox ) * a;
    }

    // y
    float b = 1.f/dy;
    if ( b >= 0 )
    {
        ty_min = ( m_Min.y-oy ) * b;
        ty_max = ( m_Max.y-oy ) * b;
    }
    else
    {
        ty_min = ( m_Max.y-oy ) * b;
        ty_max = ( m_Min.y-oy ) * b;
    }

    // z
    float c = 1.f/dz;
    if ( c >= 0 )
    {
        tz_min = ( m_Min.z-oz ) * c;
        tz_max = ( m_Max.z-oz ) * c;
    }
    else
    {
        tz_min = ( m_Max.z-oz ) * c;
        tz_max = ( m_Min.z-oz ) * c;
    }

    float t0, t1;

    // find largest entering t-value
    t0 = tx_min > ty_min ? tx_min : ty_min;
    t0 = tz_min > t0 ? tz_min : t0;

    // find smallest exiting t-value
    t1 = tx_max < ty_max ? tx_max : ty_max;
    t1 = tz_max < t1 ? tz_max : t1;

    if ( t0 < t1 && t1 > 0.001f ) // EPSILON
    {
        dist = t0;
        return true;
    }

    return false;
}
示例#24
0
bool Mgc::FindIntersection (const Ray3& rkRay, const Sphere& rkSphere,

    int& riQuantity, Vector3 akPoint[2])

{

    // set up quadratic Q(t) = a*t^2 + 2*b*t + c

    Vector3 kDiff = rkRay.Origin() - rkSphere.Center();

    Real fA = rkRay.Direction().SquaredLength();

    Real fB = kDiff.Dot(rkRay.Direction());

    Real fC = kDiff.SquaredLength() -

        rkSphere.Radius()*rkSphere.Radius();



    Real afT[2];

    Real fDiscr = fB*fB - fA*fC;

    if ( fDiscr < 0.0f )

    {

        riQuantity = 0;

        return false;

    }

    else if ( fDiscr > 0.0f )

    {

        Real fRoot = Math::Sqrt(fDiscr);

        Real fInvA = 1.0f/fA;

        afT[0] = (-fB - fRoot)*fInvA;

        afT[1] = (-fB + fRoot)*fInvA;



        if ( afT[0] >= 0.0f )

        {

            riQuantity = 2;

            akPoint[0] = rkRay.Origin() + afT[0]*rkRay.Direction();

            akPoint[1] = rkRay.Origin() + afT[1]*rkRay.Direction();

            return true;

        }

        else if ( afT[1] >= 0.0f )

        {

            riQuantity = 1;

            akPoint[0] = rkRay.Origin() + afT[1]*rkRay.Direction();

            return true;

        }

        else

        {

            riQuantity = 0;

            return false;

        }

    }

    else

    {

        afT[0] = -fB/fA;

        if ( afT[0] >= 0.0f )

        {

            riQuantity = 1;

            akPoint[0] = rkRay.Origin() + afT[0]*rkRay.Direction();

            return true;

        }

        else

        {

            riQuantity = 0;

            return false;

        }

    }

}