Example #1
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;
                    }
                }
            }
        }           
    }