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

📄 ogrecollisioncontext.cpp

📁 opcode是功能强大
💻 CPP
📖 第 1 页 / 共 2 页
字号:

					for (attached_list_iterator i = attached_list.begin(); i != attached_list.end(); ++i)
					{
						if( (*i)->hasCollisions() || (*i)->hasCheckCollisions() )
							(*i)->getShape()->visualize(mVisualDebugger);
					}
					//mVisualDebugger->endShapes();
				}
				if(doAABBs)
				{
					mVisualDebugger->beginAABBs();

					for (attached_list_iterator i = attached_list.begin(); i != attached_list.end(); ++i)
					{
						if( (*i)->hasCollisions() || (*i)->hasCheckCollisions() )
							(*i)->getShape()->visualizeAABBs(mVisualDebugger);
					}
					mVisualDebugger->endAABBs();
				}
			}
		}
	}

	/// Do an instant check of a moving sphere in the collision volume.
	/// Fills out the provided collide report array and
	/// returns number of detected collisions.
	/// @param p0     [in] starting position
	/// @param v0     [in] vector to ending position
	/// @param radius [in] radius
	/// @param collClass [in] collision class for collision type query
	/// @param cr_ptr [out] pointer to array of pointers to CollisionPair's
	/// @return       number of detected contacts (1 per collide object)
	int CollisionContext::sweptSphereCheck(const Vector3& position, const Vector3& movementVector, Real radius, CollisionClass collClass, CollisionPair **& cpPtr, String ignorename)
	{
		// create a bounding box from the start and end position
		Vector3 endPosition(position + movementVector);
		Vector3 minv(n_min(position.x, endPosition.x) - radius, 
			n_min(position.y, endPosition.y) - radius, 
			n_min(position.z, endPosition.z) - radius);
		Vector3 maxv(n_max(position.x, endPosition.x) + radius, 
			n_max(position.y, endPosition.y) + radius, 
			n_max(position.z, endPosition.z) + radius);

		const int own_id = 0xffff;

		// initialize collision report handler
		checkReportHandler.beginFrame();

		// This simply goes through all attached objects, and
		// checks them for overlap, so ITS SLOW! Every object is
		// tested exactly once
		for (attached_list_iterator other = attached_list.begin(); other != attached_list.end(); ++other)
		{
			// see if we have overlaps in all 3 dimensions
			if ((minv.x < (*other)->maxv.x) && (maxv.x > (*other)->minv.x) &&
				(minv.y < (*other)->maxv.y) && (maxv.y > (*other)->minv.y) &&
				(minv.z < (*other)->maxv.z) && (maxv.z > (*other)->minv.z))
			{
				// see if the candidate is in the ignore types set
				CollisionType ct = CollisionManager::getSingletonPtr()->queryCollType(collClass,(*other)->getCollClass());
				if (COLLTYPE_IGNORE == ct) continue;

				checkReportHandler.mTotalObjObjTests++;
				if((*other)->getName() != ignorename)
				{
					if (COLLTYPE_QUICK == ct)
					{
						// Trying to extract position information from provided matrices.
						Vector3 p1 = Vector3((*other)->old_matrix[0][3], (*other)->old_matrix[1][3], (*other)->old_matrix[2][3]);
						Vector3 v1 = Vector3(Vector3((*other)->new_matrix[0][3], (*other)->new_matrix[1][3], (*other)->new_matrix[2][3]) - p1);

						// do the contact check between 2 moving spheres
						sphere s0(position,radius);
						sphere s1(p1,(*other)->getRadius());
						float u0,u1;
						checkReportHandler.mTotalBVBVTests++;
						if (s0.intersect_sweep(movementVector,s1,v1,u0,u1))
						{
							if ((u0>=0.0f) && (u0<1.0f))
							{
								// we have contact!

								// compute the 2 midpoints at the time of collision
								Vector3 c0(position + movementVector*u0);
								Vector3 c1(p1 + v1*u0);

								// compute the collide normal
								Vector3 d(c1-c0);
								if (d.length() > TINY)
								{
									d.normalise();
								} else
								{
									d = Vector3(0.0f, 1.0f, 0.0f);
								}

								// fill out a collide report and add to report handler
								CollisionPair cr;
								cr.this_object     = (*other);
								cr.other_object     = (*other);
								cr.tstamp  = 0.0;
								CollisionInfo collInfo;
								collInfo.contact = (d*radius) + c0;
								collInfo.this_normal = d;
								collInfo.other_normal = -d;
								cr.collInfos.push_back(collInfo);
								checkReportHandler.addCollision(cr,own_id,(*other)->id);
							}
						}
					}
					else // CONTACT and EXACT
					{
						// do sphere-shape collision check
						ICollisionShape* shape = (*other)->getShape();

						if (shape)
						{
							CollisionPair cp;
							cp.this_object = (*other);
							cp.other_object = (*other);
							bool ret = shape->sweptSphereCheck(ct, (*other)->getTransform(), position, movementVector, radius, cp);
							checkReportHandler.mTotalBVBVTests += cp.numBVBVTests;
							checkReportHandler.mTotalBVPrimTests += cp.numBVPrimTests;
							if (ret)
							{
								cp.this_object = (*other);
								cp.other_object = (*other);
								checkReportHandler.addCollision(cp, own_id, (*other)->id);
							}
						}
					}
				}

			}
		}
		checkReportHandler.endFrame();
		return checkReportHandler.getAllCollisions(cpPtr);
	}

	/// Test a ray against the collide objects in the collide context.
	/// The collType will be interpreted as follows:
	/// - COLLTYPE_IGNORE:        illegal (makes no sense)
	/// - COLLTYPE_QUICK:         occlusion check only
	/// - COLLTYPE_CONTACT:       return closest contact only
	/// - COLLTYPE_EXACT:         return all contacts (unsorted)
	/// @param  line        [in]  the ray to test in global space
	/// @param  collType    [in]  the collision type
	/// @param  collClass   [in]  optional coll class (COLLCLASS_ALWAYS_* if no coll class filtering wanted)
	/// @param  cpPtr       [out] will be filled with pointer to collide report pointers
	/// @return             number of detected contacts (1 per collide object)
	int CollisionContext::rayCheck(const Ogre::Ray line, const Real dist, CollisionType collType, CollisionClass collClass, CollisionPair**& cpPtr)
	{
		assert(collType != COLLTYPE_IGNORE);

		// create a bounding box from the line
		bbox3 bbox;
		bbox.begin_grow();
		bbox.grow(line.getOrigin());
		bbox.grow(line.getPoint(dist));
		const int ownId = 0xffff;

		// initialize collision report handler
		checkReportHandler.beginFrame();

		// go through all attached collide objects
		for (attached_list_iterator co = attached_list.begin(); co != attached_list.end(); ++co)
		{
			Vector3 coMin = (*co)->minv;
			Vector3 coMax = (*co)->maxv;
			// see if we have overlaps in all 3 dimensions
			if (intervalOverlap(bbox.vmin.x,bbox.vmax.x,coMin.x,coMax.x) &&
				intervalOverlap(bbox.vmin.y,bbox.vmax.y,coMin.y,coMax.y) &&
				intervalOverlap(bbox.vmin.z,bbox.vmax.z,coMin.z,coMax.z) )
			{
				// see if the candidate is in the ignore types set
				CollisionType ct = CollisionManager::getSingletonPtr()->queryCollType(collClass, (*co)->getCollClass());
				if (COLLTYPE_IGNORE == ct) 
				{
					continue;
				}


				// check collision
				ICollisionShape* shape = (*co)->getShape();
				if (shape)
				{
					checkReportHandler.mTotalObjObjTests++;
					CollisionPair cp;
					bool ret = shape->rayCheck(collType, (*co)->getTransform(), line, dist, cp, mRayCulling);
					checkReportHandler.mTotalBVBVTests += cp.numBVBVTests;
					checkReportHandler.mTotalBVBVTests += cp.numBVPrimTests;
					if (ret)
					{
						cp.this_object = (*co);
						cp.other_object = (*co);
						checkReportHandler.addCollision(cp, ownId, (*co)->id);
						if (COLLTYPE_QUICK == collType)
						{
							// break out of loop
							break;
						}
					}
				}
			}
		}
		checkReportHandler.endFrame();

		//if (COLLTYPE_CONTACT == collType) // FIXME!
		//{
		//	// get closest contact only
		//	return checkReportHandler.getClosestCollision(line.getOrigin(), cpPtr);
		//}
		//else
		//{
			// get all contacts (unsorted)
			return checkReportHandler.getAllCollisions(cpPtr);
		//}
	}

	/// Test a sphere against the collide objects in the collide context.
	/// The collType will be interpreted as follows:
	/// - COLLTYPE_IGNORE:        illegal (makes no sense)
	/// - COLLTYPE_QUICK:         return all contacts, do sphere-sphere check
	/// - COLLTYPE_CONTACT:       return closest contact only, sphere-shape
	/// - COLLTYPE_EXACT:         return all contacts (unsorted), sphere-shape
	/// @param  theSphere      [in]  the sphere to test in global space
	/// @param  collType    [in]  the collision type
	/// @param  collClass   [in]  optional coll class (COLLCLASS_ALWAYS_* if no coll class filtering wanted)
	/// @param  cpPtr       [out] will be filled with pointer to collide report pointers
	/// @return             number of detected contacts (1 per collide object)
	int CollisionContext::sphereCheck(const Sphere& theSphere, CollisionType collType, CollisionClass collClass, CollisionPair**& cpPtr)
	{
		assert(collType != COLLTYPE_IGNORE);

		sphere ball;
		ball.set(theSphere.getCenter(),theSphere.getRadius());
		// create a bounding box from the sphere
		Vector3 vmin(ball.p.x - ball.r, ball.p.y - ball.r, ball.p.z - ball.r);
		Vector3 vmax(ball.p.x + ball.r, ball.p.y + ball.r, ball.p.z + ball.r);
		bbox3 bbox(vmin, vmax);
		const int ownId = 0xffff;

		// initialize collision report handler
		checkReportHandler.beginFrame();

		// go through all attached collide objects
		sphere s0;
		for (attached_list_iterator co = attached_list.begin(); co != attached_list.end(); ++co)
		{
			// see if we have overlaps in all 3 dimensions
			if ((bbox.vmin.x < (*co)->maxv.x) && (bbox.vmax.x > (*co)->minv.x) &&
				(bbox.vmin.y < (*co)->maxv.y) && (bbox.vmax.y > (*co)->minv.y) &&
				(bbox.vmin.z < (*co)->maxv.z) && (bbox.vmax.z > (*co)->minv.z))
			{
				// see if the candidate is in the ignore types set
				CollisionType ct = CollisionManager::getSingletonPtr()->queryCollType(collClass, (*co)->getCollClass());
				if (COLLTYPE_IGNORE == ct)
				{
					continue;
				}

				checkReportHandler.mTotalObjObjTests++;
				if (COLLTYPE_QUICK == ct)
				{
					// do sphere-sphere collision check
					const Matrix4 coTrans = (*co)->getTransform();
					//s0.set(coTrans[0][3], coTrans[1][3], coTrans[2][3], (*co)->getRadius());
					s0.set((*co)->getShape()->getCenter(), (*co)->getRadius());
					checkReportHandler.mTotalBVBVTests++;
					if (ball.intersects(s0))
					{
						CollisionPair cp;
						cp.this_object = (*co);
						cp.other_object = (*co);
						checkReportHandler.addCollision(cp, ownId, (*co)->id);
					}
				}
				else
				{
					// do sphere-shape collision check
					ICollisionShape* shape = (*co)->getShape();
					if (shape)
					{
						CollisionPair cp;
						bool ret = shape->sphereCheck(collType, (*co)->getTransform(), theSphere, cp);
						checkReportHandler.mTotalBVBVTests += cp.numBVBVTests;
						checkReportHandler.mTotalBVPrimTests += cp.numBVPrimTests;
						if (ret)
						{
							cp.this_object = (*co);
							cp.other_object = (*co);
							checkReportHandler.addCollision(cp, ownId, (*co)->id);
						}
					}
				}
			}
		}
		checkReportHandler.endFrame();

		//if (COLLTYPE_CONTACT == collType)
		//{
		//	// get closest contact only
		//	return checkReportHandler.getClosestCollision(ball.p, cpPtr);
		//}
		//else
		//{
			// get all contacts (unsorted)
			return checkReportHandler.getAllCollisions(cpPtr);
		//}
	}


	void CollisionContext::update(Real dt)
	{
		for (attached_list_iterator co = attached_list.begin(); co != attached_list.end(); ++co)
		{
			(*co)->update(dt);
		}
	}

	/// reset position and timestamp of all attached collide objects to 0.0.
	/// This is useful at the beginning of a level to prevent phantom collisions
	/// (when objects are repositioned to their starting point in the level).
	void CollisionContext::reset()
	{
		Matrix4 identity = Matrix4::IDENTITY;
		for (attached_list_iterator co = attached_list.begin(); co != attached_list.end(); ++co)
		{
			// This must be done twice, so that old timestamp also becomes 0
			(*co)->update(-1.0, identity);
			(*co)->update(-1.0, identity);
		}

	}
}

⌨️ 快捷键说明

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