⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ogreopcodeline.cpp

📁 opcode是功能强大
💻 CPP
📖 第 1 页 / 共 3 页
字号:
					}
					else
					{
						// (0,+,0)
						Case00(1,0,2,kPnt,kDir,rkBox,pfLParam,fSqrDistance);
					}
				}
				else
				{
					if ( kDir.z > (Real)0.0 )
					{
						// (0,0,+)
						Case00(2,0,1,kPnt,kDir,rkBox,pfLParam,fSqrDistance);
					}
					else
					{
						// (0,0,0)
						Case000(kPnt,rkBox,fSqrDistance);
						if ( pfLParam )
							*pfLParam = (Real)0.0;
					}
				}
			}

			// undo reflections
			for (i = 0; i < 3; i++)
			{
				if ( bReflect[i] )
					kPnt[i] = -kPnt[i];
			}

			if ( pfBParam0 )
				*pfBParam0 = kPnt.x;

			if ( pfBParam1 )
				*pfBParam1 = kPnt.y;

			if ( pfBParam2 )
				*pfBParam2 = kPnt.z;

			return fSqrDistance;
		}
		// --------------------------------------------------------------------
		// Utility functions for picking
		// --------------------------------------------------------------------
		bool Clip( Real fDenom, Real fNumer, Real& rfT0, Real& rfT1)
		{
			// Return value is 'true' if line segment intersects the current test
			// plane.  Otherwise 'false' is returned in which case the line segment
			// is entirely clipped.

			if ( fDenom > 0.0 )
			{
				if ( fNumer > fDenom*rfT1 )
					return false;
				if ( fNumer > fDenom*rfT0 )
					rfT0 = fNumer/fDenom;
				return true;
			}
			else if ( fDenom < 0.0 )
			{
				if ( fNumer > fDenom*rfT0 )
					return false;
				if ( fNumer > fDenom*rfT1 )
					rfT1 = fNumer/fDenom;
				return true;
			}
			else
			{
				return fNumer <= 0.0;
			}
		}
		// --------------------------------------------------------------------
		bool FindIntersection( const Vector3& rkOrigin,
								const Vector3& rkDirection,
								const Vector3& afExtent,
								Real& rfT0,
								Real& rfT1)
		{
			Real fSaveT0 = rfT0, fSaveT1 = rfT1;

			return Clip(+rkDirection.x,-rkOrigin.x-afExtent[0],rfT0,rfT1) &&
					Clip(-rkDirection.x,+rkOrigin.x-afExtent[0],rfT0,rfT1) &&
					Clip(+rkDirection.y,-rkOrigin.y-afExtent[1],rfT0,rfT1) &&
					Clip(-rkDirection.y,+rkOrigin.y-afExtent[1],rfT0,rfT1) &&
					Clip(+rkDirection.z,-rkOrigin.z-afExtent[2],rfT0,rfT1) &&
					Clip(-rkDirection.z,+rkOrigin.z-afExtent[2],rfT0,rfT1) &&
					( rfT0 != fSaveT0 || rfT1 != fSaveT1 );
		}
		//---------------------------------------------------------------------
		Real Line::squaredDistance( const OrientedBox& rkBox ) const
		{
			Vector3 direction = end - start;

			Real fLP, fBP0, fBP1, fBP2;
			Real pfBParam0,pfBParam1,pfBParam2;
			Real fSqrDistance = sqrDistance(start, direction, rkBox,&fLP,&fBP0,&fBP1,&fBP2);
			if ( fLP >= (Real)0.0 )
			{
				if ( fLP <= (Real)1.0 )
				{
					//if ( pfLParam  ) *pfLParam = fLP;
					//if ( pfBParam0 ) *pfBParam0 = fBP0;
					//if ( pfBParam1 ) *pfBParam1 = fBP1;
					//if ( pfBParam2 ) *pfBParam2 = fBP2;
					return fSqrDistance;
				}
				else
				{
					// TODO implement distance between a point and a box
					fSqrDistance = sqrDistance( end, rkBox, &pfBParam0,&pfBParam1,&pfBParam2);
					//if ( pfLParam ) *pfLParam = (Real)1.0;
					return fSqrDistance;
				}
			}
			else
			{
				fSqrDistance = sqrDistance(start,rkBox, &pfBParam0,&pfBParam1,&pfBParam2);
				// if ( pfLParam ) *pfLParam = (Real)0.0;
				return fSqrDistance;
			}

			return 0.0;
		}
		// --------------------------------------------------------------------
		Real Line::distance( const OrientedBox& obb ) const
		{
			return Math::Sqrt( squaredDistance(obb) );
		}
		// --------------------------------------------------------------------
		// INTERSECTION TESTS
		// --------------------------------------------------------------------
		bool Line::intersect( const Aabb& aabb ) const
		{
			OBB obb(aabb);
			return intersect(obb);
		}
		// --------------------------------------------------------------------
		bool Line::intersect( const OBB& rkBox ) const
		{
			Vector3 dir = end - start;
			Real fAWdU[3], fADdU[3], fAWxDdU[3], fRhs;
			Vector3 kSDir = 0.5*dir;
			Vector3 kSCen = start + kSDir;
			Vector3 rot[3] = { rkBox.getOrientation().GetColumn(0),
							   rkBox.getOrientation().GetColumn(1),
                               rkBox.getOrientation().GetColumn(2) };

			Vector3 kDiff = kSCen - rkBox.getCenter();

			fAWdU[0] = Math::Abs(kSDir | rot[0]);
			fADdU[0] = Math::Abs(kDiff | rot[0]);
			fRhs = rkBox.getExtents()[0] + fAWdU[0];
			if ( fADdU[0] > fRhs )
				return false;

			fAWdU[1] = Math::Abs(kSDir | rot[1]);
			fADdU[1] = Math::Abs(kDiff | rot[1]);
			fRhs = rkBox.getExtents()[1] + fAWdU[1];
			if ( fADdU[1] > fRhs )
				return false;

			fAWdU[2] = Math::Abs(kSDir | rot[2]);
			fADdU[2] = Math::Abs(kDiff | rot[2]);
			fRhs = rkBox.getExtents()[2] + fAWdU[2];
			if ( fADdU[2] > fRhs )
				return false;

			Vector3 kWxD = kSDir ^ kDiff;

			fAWxDdU[0] = Math::Abs(kWxD | rot[0]);
			fRhs = rkBox.getExtents()[1]*fAWdU[2] + rkBox.getExtents()[2]*fAWdU[1];
			if ( fAWxDdU[0] > fRhs )
				return false;

			fAWxDdU[1] = Math::Abs(kWxD | rot[1]);
			fRhs = rkBox.getExtents()[0]*fAWdU[2] + rkBox.getExtents()[2]*fAWdU[0];
			if ( fAWxDdU[1] > fRhs )
				return false;

			fAWxDdU[2] = Math::Abs(kWxD | rot[2]);
			fRhs = rkBox.getExtents()[0]*fAWdU[1] + rkBox.getExtents()[1]*fAWdU[0];
			if ( fAWxDdU[2] > fRhs )
				return false;

			return true;
		}
		// --------------------------------------------------------------------
		bool Line::intersect( const Sphere& sphere ) const
		{
			Real fSqrDist = squaredDistance( sphere.getCenter() );
			return fSqrDist <= sphere.getRadius()*sphere.getRadius();
		}
		// --------------------------------------------------------------------
		bool Line::intersect( const Capsule& capsule ) const
		{
			Real fSqrDist = squaredDistance( Line(capsule.start, capsule.end) );
			return fSqrDist <= capsule.radius*capsule.radius;
		}
		// --------------------------------------------------------------------
		bool Line::pick( const Aabb& aabb, Real& dist ) const
		{
			OBB obb(aabb);
			return pick(obb,dist);
		}
		// --------------------------------------------------------------------
		bool Line::pick( const OBB& obb, Real& dist ) const
		{
			// convert line to box coordinates
			Vector3 kDiff = start - obb.getCenter();
			Vector3 rot[3] = { obb.getOrientation().GetColumn(0),
							   obb.getOrientation().GetColumn(1),
                               obb.getOrientation().GetColumn(2) };
			Vector3 kOrigin(
								kDiff | rot[0],
								kDiff | rot[1],
								kDiff | rot[2]
							);

			Vector3 direction = end - start;
			Vector3 kDirection(
									direction | rot[0],
									direction | rot[1],
									direction | rot[2]
								);

			Real fT0 = Math::NEG_INFINITY, fT1 = Math::POS_INFINITY;
			bool ret = FindIntersection(kOrigin,kDirection,obb.getExtents(),
				fT0,fT1);

			if ( ret )
			{
				if ( fT0 != fT1 )
					dist = std::min(fT0,fT1);
				else
					dist = fT0;
			}

			return ret;
		}
		// --------------------------------------------------------------------
		bool Line::pick( const Sphere& sphere, Real& dist ) const
		{
			// set up quadratic Q(t) = a*t^2 + 2*b*t + c
			Vector3 direction = end - start;
			Vector3 kDiff = start - sphere.getCenter();
			Real fA = direction.squaredLength();
			Real fB = kDiff | direction;
			Real fC = kDiff.squaredLength() - sphere.getRadius()*sphere.getRadius();

			Real afT[2];
			Real fDiscr = fB*fB - fA*fC;
			if ( fDiscr < 0.0 )
			{
				return false;
			}
			else if ( fDiscr > 0.0 )
			{
				Real fRoot = Math::Sqrt(fDiscr);
				Real fInvA = (1.0)/fA;
				afT[0] = (-fB - fRoot)*fInvA;
				afT[1] = (-fB + fRoot)*fInvA;

				dist = std::min(afT[0],afT[1]);
				return true;
			}
			else
			{
				dist = -fB/fA;
				return true;
			}
		}
		// --------------------------------------------------------------------
		// Ray3 implementation
		// --------------------------------------------------------------------
		Real Ray3::squaredDistance( const Vector3& point ) const
		{
			Vector3 delta = point - origin;
			Real proj = direction | delta;

			if ( proj < 0.0 )
				proj = 0.0;
			else
			{
				proj /= direction.squaredLength();
				delta += -proj*direction;
			}

			return delta.squaredLength();
		}
		// --------------------------------------------------------------------
		Real Ray3::distance( const Vector3& point ) const
		{
			return Math::Sqrt( squaredDistance(point) );
		}
		// --------------------------------------------------------------------
		Real Ray3::squaredDistance( const Line& line ) const
		{
			Vector3 lineDir = line.getDirection();
			Vector3 kDiff = line.start - origin;
			Real fA00 = lineDir.squaredLength();
			Real fA01 = -(lineDir|direction );
			Real fA11 = direction.squaredLength();
			Real fB0 = (kDiff|lineDir );
			Real fC = kDiff.squaredLength();
			Real fDet = Math::Abs(fA00*fA11-fA01*fA01);
			Real fB1, fS, fT, fSqrDist;

			if ( fDet >= LINE_EPSILON )
			{
				fB1 = -(kDiff|direction);
				fT = fA01*fB0-fA00*fB1;

				if ( fT >= (Real)0.0 )
				{
					// two interior points are closest, one on line and one on ray
					Real fInvDet = ((Real)1.0)/fDet;
					fS = (fA01*fB1-fA11*fB0)*fInvDet;
					fT *= fInvDet;
					fSqrDist = fS*(fA00*fS+fA01*fT+((Real)2.0)*fB0) +
						fT*(fA01*fS+fA11*fT+((Real)2.0)*fB1)+fC;
				}
				else
				{
					// end point of ray and interior point of line are closest
					fS = -fB0/fA00;
					fT = (Real)0.0;
					fSqrDist = fB0*fS+fC;
				}
			}
			else
			{
				// lines are parallel, closest pair with one point at ray origin
				fS = -fB0/fA00;
				fT = (Real)0.0;
				fSqrDist = fB0*fS+fC;
			}

			return Math::Abs(fSqrDist);
		}
		// --------------------------------------------------------------------
		Real Ray3::distance( const Line& line ) const
		{
			return Math::Sqrt( squaredDistance(line) );
		}
		// --------------------------------------------------------------------
		bool Ray3::intersect( const Aabb& aabb ) const
		{
			OBB obb(aabb);
			return intersect(obb);
		}
		// --------------------------------------------------------------------
		bool Ray3::intersect( const OBB& rkBox ) const
		{
			Real fWdU[3], fAWdU[3], fDdU[3], fADdU[3], fAWxDdU[3], fRhs;

			Vector3 rot[3] = { rkBox.getOrientation().GetColumn(0),
							   rkBox.getOrientation().GetColumn(1),
                               rkBox.getOrientation().GetColumn(2) };
			Vector3 kDiff = origin - rkBox.getCenter();

			fWdU[0] = direction | rot[0];
			fAWdU[0] = Math::Abs( fWdU[0]);
			fDdU[0] = kDiff | rot[0];
			fADdU[0] = Math::Abs( fDdU[0]);
			if ( fADdU[0] > rkBox.getExtents()[0] && fDdU[0]*fWdU[0] >= (Real)0.0 )
				return false;

			fWdU[1] = direction | rot[1];
			fAWdU[1] = Math::Abs( fWdU[1]);
			fDdU[1] = kDiff | rot[1];
			fADdU[1] = Math::Abs( fDdU[1]);
			if ( fADdU[1] > rkBox.getExtents()[1] && fDdU[1]*fWdU[1] >= (Real)0.0 )
				return false;

			fWdU[2] = direction | rot[2];
			fAWdU[2] = Math::Abs( fWdU[2]);
			fDdU[2] = kDiff | rot[2];
			fADdU[2] = Math::Abs( fDdU[2]);
			if ( fADdU[2] > rkBox.getExtents()[2] && fDdU[2]*fWdU[2] >= (Real)0.0 )
				return false;

			Vector3 kWxD = direction ^ kDiff;
			fAWxDdU[0] = Math::Abs( kWxD | rot[0] );
			fRhs = rkBox.getExtents()[1]*fAWdU[2] + rkBox.getExtents()[2]*fAWdU[1];
			if ( fAWxDdU[0] > fRhs )
				return false;

			fAWxDdU[1] = Math::Abs( kWxD | rot[1] );
			fRhs = rkBox.getExtents()[0]*fAWdU[2] + rkBox.getExtents()[2]*fAWdU[0];
			if ( fAWxDdU[1] > fRhs )
				return false;

			fAWxDdU[2] = Math::Abs( kWxD | rot[2] );
			fRhs = rkBox.getExtents()[0]*fAWdU[1] + rkBox.getExtents()[1]*fAWdU[0];
			if ( fAWxDdU[2] > fRhs )
				return false;

			return true;
		}
		// --------------------------------------------------------------------
		bool Ray3::intersect( const Sphere& sphere ) const
		{
			Real squaredDist = squaredDistance( sphere.getCenter() );
			return squaredDist <= sphere.getRadius()*sphere.getRadius();
		}
		// --------------------------------------------------------------------
		bool Ray3::intersect( const Capsule& capsule ) const
		{
			Real squaredDist = squaredDistance( Line(capsule.start, capsule.end) );
			return squaredDist <= capsule.radius*capsule.radius;
		}
		// --------------------------------------------------------------------
		bool Ray3::pick( const Aabb& aabb, Real& dist ) const
		{
			OBB obb(aabb);
			return pick(obb, dist);
		}
		// --------------------------------------------------------------------
		bool Ray3::pick( const OBB& obb, Real& dist ) const
		{
			dist = 0.0f;

			// convert ray to box coordinates
			Vector3 kDiff = origin - obb.getCenter();
			Vector3 rot[3] = { obb.getOrientation().GetColumn(0),
							   obb.getOrientation().GetColumn(1),
                               obb.getOrientation().GetColumn(2) };
			Vector3 kOrigin(
								kDiff | rot[0],
								kDiff | rot[1],
								kDiff | rot[2]
							);

			Vector3 kDirection(
									direction | rot[0],
									direction | rot[1],
									direction | rot[2]
							);

			Real fT0 = 0.0,
					fT1 = Math::POS_INFINITY;

			bool ret = FindIntersection(kOrigin,kDirection,obb.getExtents(), fT0,fT1);

			if ( ret )
			{
				if ( fT0 > 0.0 )
					dist = std::min(fT0,fT1);
				else  // fT0 == 0
					dist = fT1;
			}

			return ret;
		}
		// --------------------------------------------------------------------
		bool Ray3::pick( const Sphere& sphere, Real& dist ) const
		{
			// set up quadratic Q(t) = a*t^2 + 2*b*t + c
			Vector3 kDiff = origin - sphere.getCenter();
			Real fA = direction.squaredLength();
			Real fB = kDiff | direction;
			Real fC = kDiff.squaredLength() - sphere.getRadius()*sphere.getRadius();

			Real afT[2];
			Real fDiscr = fB*fB - fA*fC;
			dist = 0.0;

			// tests if the code won't return intersections
			if ( fDiscr < 0.0 )
				return false;

			if ( fDiscr > 0.0 )
			{
				Real fRoot = Math::Sqrt(fDiscr);
				Real fInvA = (1.0)/fA;
				afT[0] = (-fB - fRoot)*fInvA;
				afT[1] = (-fB + fRoot)*fInvA;

				// aft[1]>=afT[0] >= 0.0
				if ( afT[0] >= 0.0 )
				{
					dist = std::min(afT[0],afT[1]);
					return true;
				}
				else if ( afT[1] >= 0.0 )
				{
					dist = afT[1];
					return true;
				}
				else
					return false;
			}
			else
			{
				afT[0] = -fB/fA;
				if ( afT[0] >= 0.0 )
				{
					dist = afT[0];
					return true;
				}
				else
					return false;
			}
		}
		// --------------------------------------------------------------------
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -