/* Attempt to automatically connect unconnected portals to proper target zones 
		* by looking for matching portals in other zones which are at the same location
		*/
	void PCZSceneManager::connectPortalsToTargetZonesByLocation(void)
	{
		// go through every zone to find portals
		ZoneMap::iterator i, iend;
		PCZone* zone;
		iend = mZones.end();
		bool foundMatch;
		for (i = mZones.begin(); i != iend; i++)
		{
			zone = i->second;
			// go through all the portals in the zone
			Portal* portal;
			PortalList::iterator pi, piend;
			piend = zone->mPortals.end();
			for (pi = zone->mPortals.begin(); pi != piend; pi++)
			{
				portal = *pi;
				//portal->updateDerivedValues();
				if (portal->getTargetZone() == 0)
				{
					// this is a portal without a connected zone - look for 
					// a matching portal in another zone
					PCZone* zone2;
					ZoneMap::iterator j= mZones.begin();
					foundMatch = false;
					while (!foundMatch && j != mZones.end())
					{
						zone2 = j->second;
						if (zone2 != zone) // make sure we don't look in the same zone
						{
							Portal * portal2 = zone2->findMatchingPortal(portal);
							if (portal2)
							{
								// found a match!
								Ogre::LogManager::getSingletonPtr()->logMessage("Connecting portal "+portal->getName()+" to portal "+portal2->getName());
								foundMatch = true;
								portal->setTargetZone(zone2);
								portal->setTargetPortal(portal2);
								portal2->setTargetZone(zone);
								portal2->setTargetPortal(portal);
							}
						}
						j++;
					}
					if (foundMatch == false)
					{
						// error, didn't find a matching portal!
						OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, 
							"Could not find matching portal for portal " + portal->getName(), 
							"PCZSceneManager::connectPortalsToTargetZonesByLocation");

					}
				}
			}			
		}
	}
Example #2
0
	/** Update the zone data for the portals in the zone
	* NOTE: All portal spatial data must be up-to-date before calling this routine.
	*/
	void DefaultZone::updatePortalsZoneData(void)
	{
		PortalList transferPortalList;
		AntiPortalList transferAntiPortalList;
		// check each portal to see if it's intersecting another portal of smaller size
		for ( PortalList::iterator it = mPortals.begin(); it != mPortals.end(); ++it )
		{
			Portal * p = *it;
			bool portalNeedUpdate = p->needUpdate();

			Real pRadius = p->getRadius();

			// First we check against portals in the SAME zone (and only if they have a 
			// target zone different from the home zone)
			// Here we check only against portals that moved and of smaller size.

			// We do not need to check portal againts previous portals 
			// since it would have been already checked.
			// Hence we start with the next portal after the current portal.
			PortalList::iterator it2 = it;
			for ( ++it2; it2 != mPortals.end(); ++it2 )
			{
				Portal * p2 = (*it2);

				// Skip portal if it doesn't need updating.
				// If both portals are not moving, then there's no need to check between them.
				if (!portalNeedUpdate && !p2->needUpdate()) continue;

				// Skip portal if it's not pointing to another zone.
				if (p2->getTargetZone() == this) continue;

				// Skip portal if it's pointing to the same target zone as this portal points to
				if (p2->getTargetZone() == p->getTargetZone()) continue;

				if (pRadius > p2->getRadius())
				{
					// Portal#1 is bigger than Portal#2, check for crossing
					if (p2->getCurrentHomeZone() != p->getTargetZone() && p2->crossedPortal(p))
					{
						// portal#2 crossed portal#1 - flag portal#2 to be moved to portal#1's target zone
						p2->setNewHomeZone(p->getTargetZone());
						transferPortalList.push_back(p2);
					}
				}
				else if (pRadius < p2->getRadius())
				{
					// Portal #2 is bigger than Portal #1, check for crossing
					if (p->getCurrentHomeZone() != p2->getTargetZone() && p->crossedPortal(p2))
					{
						// portal#1 crossed portal#2 - flag portal#1 to be moved to portal#2's target zone
						p->setNewHomeZone(p2->getTargetZone());
						transferPortalList.push_back(p);
						continue;
					}
				}
			}

			// Secondly we check againts the antiportals of this zone.
			for (AntiPortalList::iterator ait = mAntiPortals.begin(); ait != mAntiPortals.end(); ++ait)
			{
				AntiPortal* ap = (*ait);

				// Skip portal if it doesn't need updating.
				// If both portals are not moving, then there's no need to check between them.
				if (!portalNeedUpdate && !ap->needUpdate()) continue;

				// only check for crossing if AntiPortal smaller than portal.
				if (pRadius > ap->getRadius())
				{
					// Portal#1 is bigger than AntiPortal, check for crossing
					if (ap->crossedPortal(p))
					{
						// AntiPortal crossed Portal#1 - flag AntiPortal to be moved to Portal#1's target zone
						ap->setNewHomeZone(p->getTargetZone());
						transferAntiPortalList.push_back(ap);
					}
				}
			}

			// Skip portal if it doesn't need updating.
			if (!portalNeedUpdate) continue;

			// Thirdly we check against portals in the target zone (and only if that target
			// zone is different from the home zone)
			PCZone * tzone = p->getTargetZone();
			if (tzone != this)
			{
				for ( PortalList::iterator it3 = tzone->mPortals.begin(); it3 != tzone->mPortals.end(); ++it3 )
				{
					Portal * p3 = (*it3);
					// only check against bigger regular portals
					if (pRadius < p3->getRadius())
					{
						// Portal#3 is bigger than Portal#1, check for crossing
						if (p->getCurrentHomeZone() != p3->getTargetZone() && p->crossedPortal(p3))
						{
							// Portal#1 crossed Portal#3 - switch target zones for Portal#1
							p->setTargetZone(p3->getTargetZone());
							break;
						}
					}
				}
			}
		}
		// transfer any portals to new zones that have been flagged
		for ( PortalList::iterator it = transferPortalList.begin(); it != transferPortalList.end(); ++it )
		{
			Portal * p = *it;
			if (p->getNewHomeZone() != 0)
			{
				_removePortal(p);
				p->getNewHomeZone()->_addPortal(p);
				p->setNewHomeZone(0);
			}
		}
		// transfer any anti portals to new zones that have been flagged
		for (AntiPortalList::iterator it = transferAntiPortalList.begin(); it != transferAntiPortalList.end(); ++it)
		{
			AntiPortal* p = *it;
			if (p->getNewHomeZone() != 0)
			{
				_removeAntiPortal(p);
				p->getNewHomeZone()->_addAntiPortal(p);
				p->setNewHomeZone(0);
			}
		}
	}