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

📄 ogreopcodemath.h

📁 opcode是功能强大
💻 H
📖 第 1 页 / 共 2 页
字号:
				if (bb.vmin.z<vmin.z) vmin.z=bb.vmin.z;
				if (bb.vmax.x>vmax.x) vmax.x=bb.vmax.x;
				if (bb.vmax.y>vmax.y) vmax.y=bb.vmax.y;
				if (bb.vmax.z>vmax.z) vmax.z=bb.vmax.z;
			};

			// get point of intersection of 3d line with planes
			// on const x,y,z
			bool isect_const_x(const float x, const line3& l, Ogre::Vector3& out) const
			{
				if (l.m.x != 0.0f)
				{
					float t = (x - l.b.x) / l.m.x;
					if ((t>=0.0f) && (t<=1.0f))
					{
						// point of intersection...
						out = l.ipol(t);
						return true;
					}
				}
				return false;
			}

			bool isect_const_y(const float y, const line3& l, Ogre::Vector3& out) const
			{
				if (l.m.y != 0.0f)
				{
					float t = (y - l.b.y) / l.m.y;
					if ((t>=0.0f) && (t<=1.0f))
					{
						// point of intersection...
						out = l.ipol(t);
						return true;
					}
				}
				return false;
			}

			bool isect_const_z(const float z, const line3& l, Ogre::Vector3& out) const
			{
				if (l.m.z != 0.0f)
				{
					float t = (z - l.b.z) / l.m.z;
					if ((t>=0.0f) && (t<=1.0f))
					{
						// point of intersection...
						out = l.ipol(t);
						return true;
					}
				}
				return false;
			}

			// point in polygon check for sides with constant x,y and z
			bool pip_const_x(const Ogre::Vector3& p) const
			{
				if ((p.y>=vmin.y)&&(p.y<=vmax.y)&&(p.z>=vmin.z)&&(p.z<=vmax.z)) return true;
				else return false;
			}

			bool pip_const_y(const Ogre::Vector3& p) const
			{
				if ((p.x>=vmin.x)&&(p.x<=vmax.x)&&(p.z>=vmin.z)&&(p.z<=vmax.z)) return true;
				else return false;
			}

			bool pip_const_z(const Ogre::Vector3& p) const
			{
				if ((p.x>=vmin.x)&&(p.x<=vmax.x)&&(p.y>=vmin.y)&&(p.y<=vmax.y)) return true;
				else return false;
			}

			//--- check if box intersects or contains line ------------------
			bool intersect(const line3& line) const
			{
				// For each side of box, check if point of intersection
				// lies within this sides 2d rectangle. If at least one
				// intersection occurs, the line intersects the box
				// (usually, there will be 2 intersections).
				// The line parameter t for the intersection is computed
				// by resolving the formula:
				//  p = line.b + line.m*t
				// after t:
				//  t = (p - line.b) / line.m
				// if line.m is zero, the line is parallel to the plane in
				// question.
				// MAY BE EXTENDED TO RETURN CLOSEST POINT OF INTERSECTION!

				// check if at least one of the 2 points is included in the volume
				Ogre::Vector3 s(line.start());
				Ogre::Vector3 e(line.end());
				if (((s.x>=vmin.x) && (s.y>=vmin.y) && (s.z>=vmin.z) &&
					(s.x<=vmax.x) && (s.y<=vmax.y) && (s.z<=vmax.z)) ||
					((e.x>=vmin.x) && (e.y>=vmin.y) && (e.z>=vmin.z) &&
					(e.x<=vmax.x) && (e.y<=vmax.y) && (e.z<=vmax.z)))
				{
					return true;
				} else
				{
					// otherwise do intersection check
					int i;
					Ogre::Vector3 ipos;
					for (i=0; i<6; i++)
					{
						switch (i)
						{
							// left side, vmin.x is constant
						case 0:
							if (isect_const_x(vmin.x,line,ipos) && pip_const_x(ipos)) return true;
							break;
						case 1:
							if (isect_const_x(vmax.x,line,ipos) && pip_const_x(ipos)) return true;
							break;
						case 2:
							if (isect_const_y(vmin.y,line,ipos) && pip_const_y(ipos)) return true;
							break;
						case 3:
							if (isect_const_y(vmax.y,line,ipos) && pip_const_y(ipos)) return true;
							break;
						case 4:
							if (isect_const_z(vmin.z,line,ipos) && pip_const_z(ipos)) return true;
							break;
						case 5:
							if (isect_const_z(vmax.z,line,ipos) && pip_const_z(ipos)) return true;
							break;
						}
					}
				}
				return false;
			}

			/**
			@brief Gets closest intersection with AABB.
			If the line starts inside the box,  start point is returned in ipos.
			@param line the pick ray
			@param ipos closest point of intersection if successful, trash otherwise
			@return true if an intersection occurs
			*/
			bool intersect(const line3& line, Ogre::Vector3& ipos) const
			{
				// Handle special case for start point inside box
				if (line.b.x >= vmin.x && line.b.y >= vmin.y && line.b.z >= vmin.z &&
					line.b.x <= vmax.x && line.b.y <= vmax.y && line.b.z <= vmax.z)
				{
					ipos = line.b;
					return true;
				}

				// Order planes to check, closest three only
				int plane[3];
				if (line.m.x > 0) plane[0] = 0;
				else              plane[0] = 1;
				if (line.m.y > 0) plane[1] = 2;
				else              plane[1] = 3;
				if (line.m.z > 0) plane[2] = 4;
				else              plane[2] = 5;

				for (int i = 0; i < 3; ++i)
				{
					switch (plane[i])
					{
					case 0:
						if (isect_const_x(vmin.x,line,ipos) && pip_const_x(ipos)) return true;
						break;
					case 1:
						if (isect_const_x(vmax.x,line,ipos) && pip_const_x(ipos)) return true;
						break;
					case 2:
						if (isect_const_y(vmin.y,line,ipos) && pip_const_y(ipos)) return true;
						break;
					case 3:
						if (isect_const_y(vmax.y,line,ipos) && pip_const_y(ipos)) return true;
						break;
					case 4:
						if (isect_const_z(vmin.z,line,ipos) && pip_const_z(ipos)) return true;
						break;
					case 5:
						if (isect_const_z(vmax.z,line,ipos) && pip_const_z(ipos)) return true;
						break;
					}
				}

				return false;
			}

			//--- check if box intersects, contains or is contained in other box
			//--- by doing 3 projection tests for each dimension, if all 3 test 
			//--- return true, then the 2 boxes intersect
			int line_test(float v0, float v1, float w0, float w1)
			{
				// quick rejection test
				if ((v1<w0) || (v0>w1)) return OUTSIDE;
				else if ((v0==w0) && (v1==w1)) return ISEQUAL;
				else if ((v0>=w0) && (v1<=w1)) return ISCONTAINED;
				else if ((v0<=w0) && (v1>=w1)) return CONTAINS;
				else return CLIPS;
			}

			int intersect(bbox3 box)
			{
				int and_code = 0xffff;
				int or_code  = 0;
				int cx,cy,cz;
				cx = line_test(vmin.x,vmax.x,box.vmin.x,box.vmax.x);
				and_code&=cx; or_code|=cx;
				cy = line_test(vmin.y,vmax.y,box.vmin.y,box.vmax.y);
				and_code&=cy; or_code|=cy;
				cz = line_test(vmin.z,vmax.z,box.vmin.z,box.vmax.z);
				and_code&=cz; or_code|=cz;
				if (or_code == 0) return OUTSIDE;
				else if (and_code != 0)
				{
					return and_code;
				} else
				{
					// only if all test produced a non-outside result,
					// an intersection has occured
					if (cx && cy && cz) return CLIPS;
					else                return OUTSIDE;
				}
			}
		};

		/// Just for ease of use, let bbox be an AABB. :P
		typedef bbox3 Aabb;

		class sphere
		{
		public:
			Ogre::Vector3 p;      // position
			Ogre::Real   r;      // radius

			//--- constructors ----------------------------------------------
			sphere() : r(1.0f) {};
			sphere(const Ogre::Vector3& _p, Ogre::Real _r) : p(_p), r(_r) {};
			sphere(const sphere& s) : p(s.p), r(s.r) {};
			sphere(Ogre::Real _x, Ogre::Real _y, Ogre::Real _z, Ogre::Real _r) 
				: r(_r)
			{
				p = Ogre::Vector3(_x,_y,_z);
			};

			//--- set position and radius ---
			void set(const Ogre::Vector3& _p, Ogre::Real _r)
			{
				p = _p;
				r = _r;
			};
			void set(Ogre::Real _x, Ogre::Real _y, Ogre::Real _z, Ogre::Real _r)
			{
				p = Ogre::Vector3(_x, _y, _z);
				r = _r;
			};

			//--- check if 2 spheres overlap, without contact point ---------
			bool intersects(const sphere& s) const
			{
				Ogre::Vector3 d(s.p-p);
				Ogre::Real rsum = s.r+r;
				if (d.squaredLength() <= (rsum*rsum)) return true;
				else                                return false;
			};

			//--- check if 2 moving spheres have contact --------------------
			//--- taken from "Simple Intersection Tests For Games" ----------
			//--- article in Gamasutra, Oct 18 1999 -------------------------
			bool intersect_sweep(const Ogre::Vector3& va,     // in: distance travelled by 'this'
				const sphere&  sb,     // in: the other sphere
				const Ogre::Vector3& vb,     // in: distance travelled by 'sb'
				Ogre::Real& u0,             // out: normalized intro contact u0
				Ogre::Real& u1)             // out: normalized outro contact u1
			{
				Ogre::Vector3 vab(vb - va);
				Ogre::Vector3 ab(sb.p - p);
				Ogre::Real rab = r + sb.r;

				// check if spheres are currently overlapping...
				if ((ab.dotProduct(ab)) <= (rab*rab))
				{
					u0 = 0.0f;
					u1 = 0.0f;
					return true;
				} else
				{
					// check if they hit each other
					Ogre::Real a = vab.dotProduct(vab);
					if ((a<-TINY) || (a>+TINY))
					{
						// if a is '0' then the objects don't move relative to each other
						Ogre::Real b = (vab.dotProduct(ab)) * 2.0f;
						Ogre::Real c = (ab.dotProduct(ab)) - (rab * rab);
						Ogre::Real q = b*b - 4*a*c;
						if (q >= 0.0f) {
							// 1 or 2 contacts
							Ogre::Real sq = (Ogre::Real)sqrt(q);
							Ogre::Real d  = 1.0f / (2.0f*a);
							Ogre::Real r1 = (-b + sq) * d;
							Ogre::Real r2 = (-b - sq) * d;
							if (r1 < r2)
							{
								u0 = r1;
								u1 = r2;
							} else
							{
								u0 = r2;
								u1 = r1;
							}
							return true;
						} else
							return false;
					} else
						return false;
				}
			};
		};

		// includes the OBB header. looks strange, huh ? :P 
		//#include "OgreOrientedBox.h"

		/* Triangle/triangle intersection test routine,
		* by Tomas Moller, 1997.
		* See article "A Fast Triangle-Triangle Intersection Test",
		* Journal of Graphics Tools, 2(2), 1997
		* updated: 2001-06-20 (added line of intersection)
		*
		* 2005-04-15 ported to CS by Andrew Dai

		* 2006-06-21 ported to Ogre by Jacob Moen
		*/
		/**
		* A 3D line segment. (Nicked from CrystalSpace)
		*/
		class Segment3
		{
		private:
			/// Start.
			Ogre::Vector3 _start;
			/// End.
			Ogre::Vector3 _end;

		public:
			/// Make a new segment and initialize with the given values.
			Segment3 (const Ogre::Vector3& s, const Ogre::Vector3& e) { _start = s; _end = e; }
			/// Make a new uninitialized segment.
			Segment3 () { }

			/// Set segment to given values.
			inline void set (const Ogre::Vector3& s, const Ogre::Vector3& e)
			{ _start = s; _end = e; }

			/// Set the start of the segment.
			inline void setStart (const Ogre::Vector3& s) { _start = s; }

			/// Set the end of the segment.
			inline void setEnd (const Ogre::Vector3& e) { _end = e; }

			/// Get the start of the segment.
			inline const Ogre::Vector3& start () const { return _start; }

			/// Get the end of the segment.
			inline const Ogre::Vector3& end () const { return _end; }

			/// Get the start of the segment.
			inline Ogre::Vector3& start () { return _start; }

			/// Get the end of the segment.
			inline Ogre::Vector3& end () { return _end; }
		};

		class Intersect3
		{
		public:
			/**
			* Test intersection between two triangles.
			* \param tri1 Vertices of triangle 1
			* \param tri2 Vertices of triangle 2
			* \return true if the triangles intersect, otherwise false
			*/
			static bool triangleTriangle (const Ogre::Vector3 tri1[3],
				const Ogre::Vector3 tri2[3]);

			/**
			* Calculate intersection between two triangles and return it
			* in isectline.
			* \param tri1 Vertices of triangle 1
			* \param tri2 Vertices of triangle 2
			* \param[out] isectline The line segment where they intersect
			* \param[out] coplanar Returns whether the triangles are coplanar
			* \return true if the triangles intersect, otherwise false
			*/
			static bool triangleTriangle (const Ogre::Vector3 tri1[3],
				const Ogre::Vector3 tri2[3],
				Segment3& isectline, bool& coplanar);

		};

		Ogre::String decimalToBinary(unsigned int i);

		bool powerOf2(unsigned int i);
	}
}


#endif // __OgreOpcodeMath_h__

⌨️ 快捷键说明

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