/** Delete a anti portal instance by name */
	void PCZSceneManager::destroyAntiPortal(const String& portalName)
	{
		// find the anti portal from the master portal list
		AntiPortal* p;
		AntiPortal* thePortal = 0;
		AntiPortalList::iterator it = mAntiPortals.begin();
		while (it != mAntiPortals.end())
		{
			p = *it;
			if (p->getName() == portalName)
			{
				thePortal = p;
				// erase entry in the master list
				mAntiPortals.erase(it);
				break;
			}
			it++;
		}
		if (thePortal)
		{
			// remove the Portal from it's home zone
			PCZone* homeZone = thePortal->getCurrentHomeZone();
			if (homeZone)
			{
				// inform zone of portal change 
				homeZone->setPortalsUpdated(true);
				homeZone->_removeAntiPortal(thePortal);
			}

			// delete the portal instance
			OGRE_DELETE thePortal;
		}
	}
	/* Find the best (smallest) zone that contains a point
	*/
	PCZone * PCZSceneManager::findZoneForPoint(Vector3 & point)
	{
		PCZone * zone;
		PCZone * bestZone = mDefaultZone;
		Real bestVolume = Ogre::Math::POS_INFINITY;

		ZoneMap::iterator zit = mZones.begin();

		while ( zit != mZones.end() )
		{
			zone = zit->second;
			AxisAlignedBox aabb;
			zone->getAABB(aabb);
			SceneNode * enclosureNode = zone->getEnclosureNode();
			if (enclosureNode != 0)
			{
				// since this is the "local" AABB, add in world translation of the enclosure node
				aabb.setMinimum(aabb.getMinimum() + enclosureNode->_getDerivedPosition());
				aabb.setMaximum(aabb.getMaximum() + enclosureNode->_getDerivedPosition());
			}
			if (aabb.contains(point))
			{
				if (aabb.volume() < bestVolume)
				{
					// this zone is "smaller" than the current best zone, so make it
					// the new best zone
					bestZone = zone;
					bestVolume = aabb.volume();
				}
			}
			// proceed to next zone in the list
			++zit;
		}
		return bestZone;
	}
Exemplo n.º 3
0
	void DefaultZone::_checkNodeAgainstPortals(PCZSceneNode * pczsn, Portal * ignorePortal)
	{
		if (pczsn == mEnclosureNode ||
			pczsn->allowedToVisit() == false)
		{
			// don't do any checking of enclosure node versus portals
			return;
		}

		PCZone * connectedZone;
        for ( PortalList::iterator it = mPortals.begin(); it != mPortals.end(); ++it )
        {
			Portal * p = *it;
			//Check if the portal intersects the node
			if (p != ignorePortal &&
				p->intersects(pczsn) != Portal::NO_INTERSECT)
			{
				// node is touching this portal
				connectedZone = p->getTargetZone();
				// add zone to the nodes visiting zone list unless it is the home zone of the node
				if (connectedZone != pczsn->getHomeZone() &&
					!pczsn->isVisitingZone(connectedZone))
				{
					pczsn->addZoneToVisitingZonesMap(connectedZone);
					// tell the connected zone that the node is visiting it
					connectedZone->_addNode(pczsn);
					//recurse into the connected zone
					connectedZone->_checkNodeAgainstPortals(pczsn, p->getTargetPortal());
				}
			}
        }
	}
    bool PCZSceneManager::setOption( const String & key, const void * val )
    {
        if ( key == "ShowBoundingBoxes" )
        {
            mShowBoundingBoxes = * static_cast < const bool * > ( val );
            return true;
        }

        else if ( key == "ShowPortals" )
        {
            mShowPortals = * static_cast < const bool * > ( val );
            return true;
        }
		// send option to each zone
		ZoneMap::iterator i;
		PCZone * zone;
		for (i = mZones.begin(); i != mZones.end(); i++)
		{
			zone = i->second;
	         if (zone->setOption(key, val ) == true)
			 {
				 return true;
			 }
		}
		
		// try regular scenemanager option
        return SceneManager::setOption( key, val );


    }
	// delete a portal instance by pointer
	void PCZSceneManager::destroyPortal(Portal * p)
	{
		// remove the portal from it's target portal
		Portal * targetPortal = p->getTargetPortal();
		if (targetPortal)
		{
			targetPortal->setTargetPortal(0); // the targetPortal will still have targetZone value, but targetPortal will be invalid
		}
		// remove the Portal from it's home zone
		PCZone * homeZone = p->getCurrentHomeZone();
		if (homeZone)
		{
			// inform zone of portal change. Do here since PCZone is abstract 
			homeZone->setPortalsUpdated(true);   
			homeZone->_removePortal(p);
		}

		// remove the portal from the master portal list
		PortalList::iterator it = std::find( mPortals.begin(), mPortals.end(), p );
		if (it != mPortals.end())
		{
			mPortals.erase(it);
		}
		// delete the portal instance
		OGRE_DELETE p;
	}
    // Create a camera for the scene
    Camera * PCZSceneManager::createCamera( const String &name )
    {
		// Check name not used
		if (mCameras.find(name) != mCameras.end())
		{
			OGRE_EXCEPT(
				Exception::ERR_DUPLICATE_ITEM,
				"A camera with the name " + name + " already exists",
				"PCZSceneManager::createCamera" );
		}

        Camera * c = OGRE_NEW PCZCamera( name, this );
        mCameras.insert( CameraList::value_type( name, c ) );

	    // create visible bounds aab map entry
	    mCamVisibleObjectsMap[c] = VisibleObjectsBoundsInfo();
    	
		// tell all the zones about the new camera
		ZoneMap::iterator i;
		PCZone * zone;
		for (i = mZones.begin(); i != mZones.end(); i++)
		{
			zone = i->second;
	        zone->notifyCameraCreated( c );
		}

        return c;
    }
	// main visibility determination & render queue filling routine
	// over-ridden from base/default scene manager.  This is *the*
	// main call.
	void PCZSceneManager::_findVisibleObjects(Camera* cam,
											  VisibleObjectsBoundsInfo* visibleBounds,
											  bool onlyShadowCasters)
	{
		// clear the render queue
		getRenderQueue()->clear();

		// if we are re-rendering the scene again with the same camera, we can just use the cache.
		// this helps post processing compositors.
		unsigned long frameCount = Root::getSingleton().getNextFrameNumber();
		if (mLastActiveCamera == cam && mFrameCount == frameCount)
		{
			RenderQueue* queue = getRenderQueue();
			size_t count = mVisible.size();
			for (size_t i = 0; i < count; ++i)
			{
				((PCZSceneNode*)mVisible[i])->_addToRenderQueue(
					cam, queue, onlyShadowCasters, visibleBounds);
			}
			return;
		}

		// increment the visibility frame counter
		mFrameCount = frameCount;
		mLastActiveCamera = cam;

		// clear the list of visible nodes
		mVisible.clear();

		// turn off sky 
		enableSky(false);

		// remove all extra culling planes
		((PCZCamera*)cam)->removeAllExtraCullingPlanes();

		// update the camera
		((PCZCamera*)cam)->update();

		// get the home zone of the camera
		PCZone* cameraHomeZone = ((PCZSceneNode*)(cam->getParentSceneNode()))->getHomeZone();

		// walk the zones, starting from the camera home zone,
		// adding all visible scene nodes to the mVisibles list
		cameraHomeZone->setLastVisibleFrame(mFrameCount);
		cameraHomeZone->findVisibleNodes((PCZCamera*)cam, 
										  mVisible, 
										  getRenderQueue(),
										  visibleBounds, 
										  onlyShadowCasters,
										  mDisplayNodes,
										  mShowBoundingBoxes);
	}
	// create any zone-specific data necessary for all zones for the given node
	void PCZSceneManager::createZoneSpecificNodeData(PCZSceneNode * node)
	{
		ZoneMap::iterator i;
		PCZone * zone;
		for (i = mZones.begin(); i != mZones.end(); i++)
		{
			zone = i->second;
			if (zone->requiresZoneSpecificNodeData())
			{
				zone->createNodeZoneData(node);
			}
		}		
	}
Exemplo n.º 9
0
    //-----------------------------------------------------------------------
    void PCZLight::updateZones(PCZone * defaultZone, unsigned long frameCount)
    {
        //update the zones this light affects
        PCZone * homeZone;
        affectedZonesList.clear();
        mAffectsVisibleZone = false;
        PCZSceneNode * sn = (PCZSceneNode*)(this->getParentSceneNode());
        if (sn)
        {
            // start with the zone the light is in
            homeZone = sn->getHomeZone();
            if (homeZone)
            {
                affectedZonesList.push_back(homeZone);
                if (homeZone->getLastVisibleFrame() == frameCount)
                {
                    mAffectsVisibleZone = true;
                }
            }
            else
            {
                // error - scene node has no homezone!
                // just say it affects the default zone and leave it at that.
                affectedZonesList.push_back(defaultZone);
                if (defaultZone->getLastVisibleFrame() == frameCount)
                {
                    mAffectsVisibleZone = true;
                }
                return;
            }
        }
        else
        {
            // ERROR! not connected to a scene node,                 
            // just say it affects the default zone and leave it at that.
            affectedZonesList.push_back(defaultZone);
            if (defaultZone->getLastVisibleFrame() == frameCount)
            {
                mAffectsVisibleZone = true;
            }
            return;
        }

        // now check visibility of each portal in the home zone.  If visible to
        // the light then add the target zone of the portal to the list of
        // affected zones and recurse into the target zone
        static PCZFrustum portalFrustum;
        Vector3 v = getDerivedPosition();
        portalFrustum.setOrigin(v);
        homeZone->_checkLightAgainstPortals(this, frameCount, &portalFrustum, 0);
    }
Exemplo n.º 10
0
	/** Overridden from SceneManager */
    void PCZSceneManager::_renderScene(Camera* cam, Viewport *vp, bool includeOverlays)
    {
		// notify all the zones that a scene render is starting
		ZoneMap::iterator i;
		PCZone * zone;
		for (i = mZones.begin(); i != mZones.end(); i++)
		{
			zone = i->second;
	        zone->notifyBeginRenderScene();
		}

		// do the regular _renderScene
        SceneManager::_renderScene(cam, vp, includeOverlays);
    }
Exemplo n.º 11
0
	/** Mark nodes dirty for every zone with moving portal in the scene */
	void PCZSceneManager::_dirtyNodeByMovingPortals(void)
	{
		PCZone * zone;
		ZoneMap::iterator zit = mZones.begin();

		while ( zit != mZones.end() )
		{
			zone = zit->second;
			// this call mark nodes dirty base on moving portals 
			zone->dirtyNodeByMovingPortals(); 
			// proceed to next zone in the list
			++zit;
		}
	}
Exemplo n.º 12
0
	void PCZSceneManager::_updatePortalZoneData(void)
	{
		PCZone * zone;
	    ZoneMap::iterator zit = mZones.begin();

	    while ( zit != mZones.end() )
	    {
		    zone = zit->second;
			// this callchecks for portal zone changes & applies zone data changes as necessary
			zone->updatePortalsZoneData(); 
			// proceed to next zone in the list
		    ++zit;
	    }
	}
Exemplo n.º 13
0
	/** Overridden from SceneManager */
	void PCZSceneManager::setWorldGeometryRenderQueue(uint8 qid)
	{
		// tell all the zones about the new WorldGeometryRenderQueue
		ZoneMap::iterator i;
		PCZone * zone;
		for (i = mZones.begin(); i != mZones.end(); i++)
		{
			zone = i->second;
	        zone->notifyWorldGeometryRenderQueue( qid );
		}
		// call the regular scene manager version
		SceneManager::setWorldGeometryRenderQueue(qid);

	}
Exemplo n.º 14
0
	void PCZSceneManager::setZoneGeometry(const String & zoneName,
										  PCZSceneNode * parentNode,
										  const String & filename)
	{
		ZoneMap::iterator i;
		PCZone * zone;
		i = mZones.find(zoneName);
		if (i != mZones.end())
		{
			zone = i->second;
			zone->setZoneGeometry( filename, parentNode );
			return;
		}

	}
Exemplo n.º 15
0
	/** Delete a anti portal instance by pointer */
	void PCZSceneManager::destroyAntiPortal(AntiPortal * p)
	{
		// remove the Portal from it's home zone
		PCZone* homeZone = p->getCurrentHomeZone();
		if (homeZone)
		{
			// inform zone of portal change. Do here since PCZone is abstract 
			homeZone->setPortalsUpdated(true);
			homeZone->_removeAntiPortal(p);
		}

		// remove the portal from the master portal list
		AntiPortalList::iterator it = std::find(mAntiPortals.begin(), mAntiPortals.end(), p);
		if (it != mAntiPortals.end()) mAntiPortals.erase(it);

		// delete the portal instance
		OGRE_DELETE p;
	}
Exemplo n.º 16
0
	/** Create a zone from a file (type of file
		* depends on the zone type
		* ZoneType_Default uses an Ogre Model (.mesh) file
		* ZoneType_Octree uses an Ogre Model (.mesh) file
		* ZoneType_Terrain uses a Terrain.CFG file
		*/
	PCZone * PCZSceneManager::createZoneFromFile(const String &zoneTypeName,
												 const String &zoneName,
												 PCZSceneNode * parentNode,
												 const String &filename)
	{
		PCZone * newZone;

        // create a new default zone
		newZone = mZoneFactoryManager->createPCZone(this, zoneTypeName, zoneName);
		// add to the global list of zones
		mZones[newZone->getName()] = newZone;
		if (filename != "none")
		{
			// set the zone geometry
			newZone->setZoneGeometry(filename, parentNode);
		}
		
		return newZone;
	}
Exemplo n.º 17
0
    /* The following function does the following:
     * 1) Remove references to the node from zones the node is visiting
     * 2) Clear the node's list of zones it is visiting
     */
    void PCZSceneNode::clearNodeFromVisitedZones( void )
    {
        if (mVisitingZones.size() > 0)
        {
            // first go through the list of zones this node is visiting 
            // and remove references to this node
            PCZone* zone;
            ZoneMap::iterator it = mVisitingZones.begin();

            while ( it != mVisitingZones.end() )
            {
                zone = it->second;
                zone->removeNode(this);
                ++it;
            }

            // second, clear the visiting zones list
            mVisitingZones.clear();

        }
    }
Exemplo n.º 18
0
	/* Create a zone with the given name and parent zone */
	PCZone * PCZSceneManager::createZone(const String& zoneType, const String& instanceName)
	{
		if (mZones.find(instanceName) != mZones.end())
		{
			OGRE_EXCEPT(
				Exception::ERR_DUPLICATE_ITEM,
				"A zone with the name " + instanceName + " already exists",
				"PCZSceneManager::createZone" );
		}
		PCZone * newZone = mZoneFactoryManager->createPCZone(this, zoneType, instanceName);
		if (newZone)
		{
			// add to the global list of zones
			mZones[instanceName] = newZone;
		}
		if (newZone->requiresZoneSpecificNodeData())
		{
			createZoneSpecificNodeData(newZone);
		}
		return newZone;
	}
Exemplo n.º 19
0
    void PCZSceneManager::findNodesIn( const Ray &r, 
                                       PCZSceneNodeList &list, 
                                       PCZone * startZone, 
                                       PCZSceneNode *exclude  )
    {
        PortalList visitedPortals;
		if (startZone)
		{
			// start in startzone, and recurse through portals if necessary
			startZone->_findNodes(r, list, visitedPortals, true, true, exclude);
		}
		else
		{
			ZoneMap::iterator i;
			PCZone * zone;
			for (i = mZones.begin(); i != mZones.end(); i++)
			{
				zone = i->second;
				zone->_findNodes( r, list, visitedPortals, false, false, exclude );
			}
		}
    }
Exemplo n.º 20
0
	// delete a portal instance by pointer
	void PCZSceneManager::destroyPortal(const String & portalName)
	{
		// find the portal from the master portal list
		Portal * p;
		Portal * thePortal = 0;
		PortalList::iterator it = mPortals.begin();
		while (it != mPortals.end())
		{
			p = *it;
			if (p->getName() == portalName)
			{
				thePortal = p;
				// erase entry in the master list
				mPortals.erase(it);
				break;
			}
			it++;
		}
		if (thePortal)
		{
			// remove the portal from it's target portal
			Portal * targetPortal = thePortal->getTargetPortal();
			if (targetPortal)
			{
				targetPortal->setTargetPortal(0); // the targetPortal will still have targetZone value, but targetPortal will be invalid
			}
			// remove the Portal from it's home zone
			PCZone * homeZone = thePortal->getCurrentHomeZone();
			if (homeZone)
			{
				// inform zone of portal change 
				homeZone->setPortalsUpdated(true);   
				homeZone->_removePortal(thePortal);
			}

			// delete the portal instance
			OGRE_DELETE thePortal;
		}
	}
Exemplo n.º 21
0
    void PCZSceneManager::findNodesIn( const PlaneBoundedVolume &volume, 
                                       PCZSceneNodeList &list, 
                                       PCZone * startZone, 
                                       PCZSceneNode *exclude )
    {
        PortalList visitedPortals;
		if (startZone)
		{
			// start in startzone, and recurse through portals if necessary
			startZone->_findNodes(volume, list, visitedPortals, true, true, exclude);
		}
		else
		{
			// no start zone specified, so check all zones
			ZoneMap::iterator i;
			PCZone * zone;
			for (i = mZones.begin(); i != mZones.end(); i++)
			{
				zone = i->second;
				zone->_findNodes( volume, list, visitedPortals, false, false, exclude );
			}
		}
    }
Exemplo n.º 22
0
 // update zone-specific data for any zone that the node is touching
 void PCZSceneNode::updateZoneData(void)
 {
     ZoneData* zoneData;
     PCZone * zone;
     // make sure home zone data is updated
     zone = mHomeZone;
     if (zone->requiresZoneSpecificNodeData())
     {
         zoneData = getZoneData(zone);
         zoneData->update();
     }
     // update zone data for any zones visited
     ZoneMap::iterator it = mVisitingZones.begin();
     while ( it != mVisitingZones.end() )
     {
         zone = it->second;
         if (zone->requiresZoneSpecificNodeData())
         {
             zoneData = getZoneData(zone);
             zoneData->update();
         }
         ++it;
     }
 }
Exemplo n.º 23
0
    /* The following function checks if a node has left it's current home zone.
	* This is done by checking each portal in the zone.  If the node has crossed
	* the portal, then the current zone is no longer the home zone of the node.  The
	* function then recurses into the connected zones.  Once a zone is found where
	* the node does NOT cross out through a portal, that zone is the new home zone.
    * When this function is done, the node should have the correct home zone already
	* set.  A pointer is returned to this zone as well.
	*
	* NOTE: If the node does not have a home zone when this function is called on it,
	*       the function will do its best to find the proper zone for the node using
	*       bounding box volume testing.  This CAN fail to find the correct zone in
	*		some scenarios, so it is best for the user to EXPLICITLY set the home
	*		zone of the node when the node is added to the scene using 
	*       PCZSceneNode::setHomeZone()
	*/
    void PCZSceneManager::_updateHomeZone( PCZSceneNode * pczsn, bool allowBackTouches )
    {
	    // Skip if root PCZoneTree has been destroyed (shutdown conditions)
	    if (!mDefaultZone)
		    return;

		PCZone * startzone;
		PCZone * newHomeZone;

		// start with current home zone of the node
		startzone = pczsn->getHomeZone();

		if (startzone)
		{
			if (!pczsn->isAnchored())
			{
				newHomeZone = startzone->updateNodeHomeZone(pczsn, false);
			}
			else
			{
				newHomeZone = startzone;
			}

			if (newHomeZone != startzone)
			{
				// add the node to the home zone
				newHomeZone->_addNode(pczsn);
			}
		}
		else
		{
			// the node hasn't had it's home zone set yet, so do our best to
			// find the home zone using volume testing.  
			Vector3 nodeCenter = pczsn->_getDerivedPosition();
			PCZone * bestZone = findZoneForPoint(nodeCenter);
			// set the best zone as the node's home zone
			pczsn->setHomeZone(bestZone);
			// add the node to the zone
			bestZone->_addNode(pczsn);
		}

		return;

    }
Exemplo n.º 24
0
    /** (recursive) check the given light against all portals in the zone
    * NOTE: This is the default implementation, which doesn't take advantage
    *       of any zone-specific optimizations for checking portal visibility
    */
    void DefaultZone::_checkLightAgainstPortals(PCZLight *light, 
                                                unsigned long frameCount, 
                                                PCZFrustum *portalFrustum,
                                                Portal * ignorePortal)
    {
		for ( PortalList::iterator it = mPortals.begin(); it != mPortals.end(); ++it )
		{
			Portal * p = *it;
            if (p != ignorePortal)
            {
                // calculate the direction vector from light to portal
                Vector3 lightToPortal = p->getDerivedCP() - light->getDerivedPosition();
                if (portalFrustum->isVisible(p))
                {
                    // portal is facing the light, but some light types need to
                    // check illumination radius too.
                    PCZone * targetZone = p->getTargetZone();
                    switch(light->getType())
                    {
                    case Light::LT_POINT:
                        // point lights - just check if within illumination range
                        if (lightToPortal.length() <= light->getAttenuationRange())
                        {
 							// if portal is quad portal it must be pointing towards the light 
							if ((p->getType() == Portal::PORTAL_TYPE_QUAD && lightToPortal.dotProduct(p->getDerivedDirection()) < 0.0) ||
								(p->getType() != Portal::PORTAL_TYPE_QUAD))
							{
								if (!light->affectsZone(targetZone))
								{
									light->addZoneToAffectedZonesList(targetZone);
									if (targetZone->getLastVisibleFrame() == frameCount)
									{
										light->setAffectsVisibleZone(true);
									}
									// set culling frustum from the portal
									portalFrustum->addPortalCullingPlanes(p);
									// recurse into the target zone of the portal
									p->getTargetZone()->_checkLightAgainstPortals(light, 
																				frameCount, 
																				portalFrustum,
																				p->getTargetPortal());
									// remove the planes added by this portal
									portalFrustum->removePortalCullingPlanes(p);
								}
							}
                        }
                        break;
                    case Light::LT_DIRECTIONAL:
                        // directionals have infinite range, so just make sure
                        // the direction is facing the portal
                        if (lightToPortal.dotProduct(light->getDerivedDirection()) >= 0.0)
                        {
 							// if portal is quad portal it must be pointing towards the light 
							if ((p->getType() == Portal::PORTAL_TYPE_QUAD && lightToPortal.dotProduct(p->getDerivedDirection()) < 0.0) ||
								(p->getType() != Portal::PORTAL_TYPE_QUAD))
							{
								if (!light->affectsZone(targetZone))
								{
									light->addZoneToAffectedZonesList(targetZone);
									if (targetZone->getLastVisibleFrame() == frameCount)
									{
										light->setAffectsVisibleZone(true);
									}
									// set culling frustum from the portal
									portalFrustum->addPortalCullingPlanes(p);
									// recurse into the target zone of the portal
									p->getTargetZone()->_checkLightAgainstPortals(light, 
																				frameCount, 
																				portalFrustum,
																				p->getTargetPortal());
									// remove the planes added by this portal
									portalFrustum->removePortalCullingPlanes(p);
								}
							}
                        }
                        break;
                    case Light::LT_SPOTLIGHT:
                        // spotlights - just check if within illumination range
                        // Technically, we should check if the portal is within
                        // the cone of illumination, but for now, we'll leave that
                        // as a future optimisation.
                        if (lightToPortal.length() <= light->getAttenuationRange())
                        {
 							// if portal is quad portal it must be pointing towards the light 
							if ((p->getType() == Portal::PORTAL_TYPE_QUAD && lightToPortal.dotProduct(p->getDerivedDirection()) < 0.0) ||
								(p->getType() != Portal::PORTAL_TYPE_QUAD))
							{
								if (!light->affectsZone(targetZone))
								{
									light->addZoneToAffectedZonesList(targetZone);
									if (targetZone->getLastVisibleFrame() == frameCount)
									{
										light->setAffectsVisibleZone(true);
									}
									// set culling frustum from the portal
									portalFrustum->addPortalCullingPlanes(p);
									// recurse into the target zone of the portal
									p->getTargetZone()->_checkLightAgainstPortals(light, 
																				frameCount, 
																				portalFrustum,
																				p->getTargetPortal());
									// remove the planes added by this portal
									portalFrustum->removePortalCullingPlanes(p);
								}
							}
                        }
                        break;
                    }
                }
            }
        }           
    }