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

📄 ogrecollisioncontext.cpp

📁 opcode是功能强大
💻 CPP
📖 第 1 页 / 共 2 页
字号:
///////////////////////////////////////////////////////////////////////////////
///  @file OgreCollisionContext.cpp
///  @brief <TODO: insert file description here>
///
///  @author The OgreOpcode Team
///  
///////////////////////////////////////////////////////////////////////////////
///  
///  This file is part of OgreOpcode.
///  
///  A lot of the code is based on the Nebula Opcode Collision module, see docs/Nebula_license.txt
///  
///  OgreOpcode is free software; you can redistribute it and/or
///  modify it under the terms of the GNU Lesser General Public
///  License as published by the Free Software Foundation; either
///  version 2.1 of the License, or (at your option) any later version.
///  
///  OgreOpcode is distributed in the hope that it will be useful,
///  but WITHOUT ANY WARRANTY; without even the implied warranty of
///  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
///  Lesser General Public License for more details.
///  
///  You should have received a copy of the GNU Lesser General Public
///  License along with OgreOpcode; if not, write to the Free Software
///  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
///  
///////////////////////////////////////////////////////////////////////////////
#include "OgreCollisionContext.h"
#include "OgreCollisionObject.h"
#include "OgreOpcodeMath.h"
#include "OgreCollisionManager.h"
#include "BP_Scene.h"

using namespace Ogre;
using namespace OgreOpcode::Details;

namespace OgreOpcode
{
	namespace Details
	{
		inline bool intervalOverlap(Real a0, Real a1, Real b0, Real b1)
		{
			// Only two ways for intervals to not overlap -- 
			//  a's max less than b's min, or a's min greater than b's max.
			// Otherwise they overlap.
			// return !(a1<b0 || a0>b1);
			// I just applied the De Morgan's law here in order to obtain short-circuit
			return (a1>=b0) && (a0<=b1);
		}
	} // Details

	// release all owned collide objects
	CollisionContext::~CollisionContext()
	{
		// remove collision objects
		while (!owned_list.empty())
		{
			destroyObject(*(owned_list.begin()));
		}
		delete mVisualDebugger;
		delete mBroadPhase;
	}

	// Construct a new collide object.
	CollisionObject *CollisionContext::createObject(const Ogre::String& name)
	{
		CollisionObject *co = new CollisionObject(name);
		co->setId(unique_id++);
		co->setContext(this);
		owned_list.push_back(co);
		return co;
	}

	CollisionContext::CollisionContext(const Ogre::String& name) :
	unique_id(0),
	mName(name),
	mRayCulling(true),
	mIsSAPDirty(true)
	{
		mVisualDebugger = new Details::OgreOpcodeDebugger(mName, CollisionManager::getSingletonPtr()->getSceneManager());
		mRecentContactList.clear();
		mBroadPhase = new BP_Scene(&proxList, &OgreOpcode::CollisionContext::addPair, &OgreOpcode::CollisionContext::removePair);
	}

	// Kill an owned collide object.
	void CollisionContext::destroyObject(CollisionObject *collObj)
	{
		if (collObj != 0)
		{
			if(collObj->isAttached())
			{
				rw_attached_list_iterator itAttached = find(attached_list.begin(), attached_list.end(), collObj);
				if (itAttached != attached_list.end())
				{
					attached_list.erase(itAttached);
				}
			}
			
			rw_owned_list_iterator itOwned = find(owned_list.begin(), owned_list.end(), collObj);
			if (itOwned != owned_list.end())
			{
				owned_list.erase(itOwned);
			}
			collObj->setAttached(false);
			collObj->remove_broadphase();
			collObj->setContext(0);
			delete collObj;
		}
	}

	void CollisionContext::addObject(CollisionObject *collObj)
	{
		if(collObj == 0)
			OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR, "Trying to add a null object.", "CollisionContext::addObject");
		
		attached_list.push_back(collObj);
		collObj->setAttached(true);
	}

	void CollisionContext::removeObject(CollisionObject *collObj)
	{
		if (collObj != 0)
		{
			collObj->setAttached(false);
			collObj->remove_broadphase();
			rw_attached_list_iterator itAttached = find(attached_list.begin(), attached_list.end(), collObj);
			if (itAttached != attached_list.end())
			{
				attached_list.erase(itAttached);
			}
		}
	}

	/// Call collide on each object in the context.
	/// After this, each object's collision array holds all collisions
	/// this object was involved with.
	int CollisionContext::collide(Real dt)
	{
		update(dt);

		
		
		// first, clear the collision counters in all collide objects
		for (attached_list_iterator i = attached_list.begin(); i != attached_list.end(); ++i)
		{
			(*i)->clearCollisions();
		}

		// then, run the broadphase 
		for (attached_list_iterator i = attached_list.begin(); i != attached_list.end(); ++i)
		{
			(*i)->do_broadphase();
		}

		// Loop through the Potentially Colliding Set and tell each CollisionObject to test against the other
		for (ProxList::iterator prox_it = proxList.begin(); prox_it != proxList.end(); ++prox_it) 
		{
			// If the shape is marked as being static, do not add it to the PCS.
			if(!(*prox_it).obj1->getShape()->isStatic())
				(*prox_it).obj1->addToCollideList((*prox_it).obj2);
			if(!(*prox_it).obj2->getShape()->isStatic())
			(*prox_it).obj2->addToCollideList((*prox_it).obj1);
		}

		// check the collision status for each object
		collideReportHandler.beginFrame();
		for (attached_list_iterator i = attached_list.begin(); i != attached_list.end(); ++i)
		{
			//if ( (*i)->needsUpdate() )
				(*i)->collide();
		}
		collideReportHandler.endFrame();

		int num_coll = collideReportHandler.getNumCollisions();
		return num_coll;
	}

	/// Get all collisions an object is involved in.
	/// Returns pointer to an internal collision array and
	/// the number of collisions.
	int CollisionContext::getCollisions(CollisionObject *collObj, CollisionPair **&cpPtr)
	{
		if (collObj->getNumCollisions() > 0)
		{
			return collideReportHandler.getCollisions(collObj,cpPtr);
		} else
		{
			cpPtr = 0;
			return 0;
		}
	}

	CollisionObject* CollisionContext::getAttachedObject(Ogre::String name)
	{
		for (attached_list_iterator i = attached_list.begin(); i != attached_list.end(); ++i)
		{
			if( (*i)->getName() == name )
				return (*i);
		}
		OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, "'" + name + "' is not attached! Does it even exsist?", "CollisionContext::getAttachedObject");
	}


	/// 
	const std::list<CollisionObject*>& CollisionContext::getPotentialColliders(const CollisionObject* collidee)
	{
		return collidee->collideList;
	}

	/// get reporter for for last collide() call.
	const CollisionReporter& CollisionContext::getCollisionReport()
	{
		return collideReportHandler;
	}

	/// 
	const int CollisionContext::getNumCollisions()
	{
		return collideReportHandler.getNumCollisions();
	}

	/// get reporter for for last Check...() call.
	const CollisionReporter& CollisionContext::getCheckReport()
	{
		return checkReportHandler;
	}

	/// visualize all objects in the context.
	void CollisionContext::visualize(bool doVisualize, bool doRadii, bool doContacts, bool doBBs, bool doShapes, bool doAABBs)
	{
		// if the debugger is down, just return
		if(!mVisualDebugger) return;

		mVisualDebugger->clearAll();
		for (attached_list_iterator i = attached_list.begin(); i != attached_list.end(); ++i)
		{
			(*i)->getShape()->clearViz();
		}

		if(doVisualize)
		{
			if (!attached_list.empty())
			{
				if(doRadii)
				{
					mVisualDebugger->beginRadii();
					for (attached_list_iterator i = attached_list.begin(); i != attached_list.end(); ++i)
					{
						(*i)->visualizeRadii();
					}
					mVisualDebugger->endRadii();
				}
				if(doContacts)
				{
					if( collideReportHandler.getNumCollisions() > 0)
					{
						mVisualDebugger->beginContacts();
						mVisualDebugger->beginContactNormals();
						for (attached_list_iterator i = attached_list.begin(); i != attached_list.end(); ++i)
						{
							(*i)->visualizeContacts();
						}
						mVisualDebugger->endContactNormals();
						mVisualDebugger->endContacts();
					}
						
					static int contactCount = 0;
					static bool bufferContacts = true;

					if( checkReportHandler.getNumCollisions() > 0)
					{
						CollisionPair **pick_report;
						int num_picks = checkReportHandler.getAllCollisions(pick_report);
						if(num_picks > 0)
						{

							for(int i = 0; i < num_picks; i++)
							{
								for (int currColl = 0; currColl < static_cast<int>(pick_report[i]->collInfos.size()); currColl++)
								{
									if(bufferContacts)
										contactCount++;
									CollisionInfo collInfo;
									collInfo.contact = pick_report[i]->collInfos[currColl].contact;
									collInfo.this_normal = pick_report[i]->collInfos[currColl].this_normal * 5;
									collInfo.other_normal = pick_report[i]->collInfos[currColl].other_normal * 5;
									mRecentContactList.push_back(collInfo);
									if(!bufferContacts)
										mRecentContactList.pop_front();
								}
							}
						}

						if(contactCount > 10)
							bufferContacts = false;

					}

					// render any collision contact points
					if (mRecentContactList.size() > 0)
					{
						mVisualDebugger->beginContacts();
						mVisualDebugger->beginContactNormals();

						std::list<CollisionInfo>::iterator contactIter;
						for (contactIter = mRecentContactList.begin(); contactIter != mRecentContactList.end(); ++contactIter)
						{
							Vector3 cnt = (*contactIter).contact;
							mVisualDebugger->addContactLine(cnt.x-0.5f,cnt.y,cnt.z, cnt.x+0.5f,cnt.y,cnt.z);
							mVisualDebugger->addContactLine(cnt.x,cnt.y-0.5f,cnt.z, cnt.x,cnt.y+0.5f,cnt.z);
							mVisualDebugger->addContactLine(cnt.x,cnt.y,cnt.z-0.5f, cnt.x,cnt.y,cnt.z+0.5f);

							Vector3 n = (*contactIter).this_normal * 5;
							mVisualDebugger->addContactNormalsLine(cnt.x,cnt.y,cnt.z, cnt.x+n.x,cnt.y+n.y,cnt.z+n.z);
							n = (*contactIter).other_normal * 5;
							mVisualDebugger->addContactNormalsLine(cnt.x,cnt.y,cnt.z, cnt.x+n.x,cnt.y+n.y,cnt.z+n.z);

						}
						
						mVisualDebugger->endContactNormals();
						mVisualDebugger->endContacts();
					}

				}

				if(doBBs)
				{
					mVisualDebugger->beginBBs();
					for (attached_list_iterator i = attached_list.begin(); i != attached_list.end(); ++i)
					{
						(*i)->visualizeBoundingBoxes();
					}
					mVisualDebugger->endBBs();
				}
				if(doShapes)
				{
					//mVisualDebugger->beginShapes();

⌨️ 快捷键说明

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