idTech4.Renderer.idRenderWorld.FloodViewThroughArea C# (CSharp) Method

FloodViewThroughArea() private method

private FloodViewThroughArea ( Vector3 origin, int areaNumber, PortalStack portalStack ) : void
origin Vector3
areaNumber int
portalStack PortalStack
return void
		private void FloodViewThroughArea(Vector3 origin, int areaNumber, PortalStack portalStack)
		{
			int i, j;
			idWinding	winding; // we won't overflow because MAX_PORTAL_PLANES = 20
	
			PortalStack check;
			PortalStack newStack;
			PortalArea area = _portalAreas[areaNumber];			

			// cull models and lights to the current collection of planes
			AddAreaReferences(areaNumber, portalStack);

			if(_areaScreenRect[areaNumber].IsEmpty == true)
			{
				_areaScreenRect[areaNumber] = portalStack.Rectangle;
			}
			else
			{
				_areaScreenRect[areaNumber].Union(portalStack.Rectangle);
			}
	

			// go through all the portals
			Portal portal;

			for(portal = area.Portals; portal != null; portal = portal.Next)
			{
				// an enclosing door may have sealed the portal off
				if((portal.DoublePortal.BlockingBits  & PortalConnection.BlockView) == PortalConnection.BlockView)
				{
					continue;
				}

				// make sure this portal is facing away from the view
				float d = portal.Plane.Distance(origin);
					
				if(d < -0.1f)
				{
					continue;
				}

				// make sure the portal isn't in our stack trace,
				// which would cause an infinite loop
				for(check = portalStack; check != null; check = check.Next)
				{
					if(check.Portal == portal)
					{
						break; // don't recursively enter a stack
					}
				}
		
				if(check != null)
				{
					continue; // already in stack
				}

				// if we are very close to the portal surface, don't bother clipping
				// it, which tends to give epsilon problems that make the area vanish
				if(d < 1.0f)
				{
					// go through this portal
					newStack = portalStack;
					newStack.Portal = portal;
					newStack.Next = portalStack;

					FloodViewThroughArea(origin, portal.IntoArea, newStack);

					continue;
				}

				// clip the portal winding to all of the planes
				winding = portal.Winding;

				for(j = 0; j < portalStack.PortalPlaneCount; j++)
				{
					Plane neg = new Plane(-portalStack.PortalPlanes[j].Normal, -portalStack.PortalPlanes[j].D);

					if(winding.ClipInPlace(neg, 0) == false)
					{
						break;
					}
				}

				if(winding.PointCount == 0)
				{
					continue;	// portal not visible
				}

				// see if it is fogged out
				if(PortalIsFoggedOut(portal) == true)
				{
					continue;
				}

				// go through this portal
				newStack = new PortalStack();
				newStack.Portal = portal;
				newStack.Next = portalStack;

				// find the screen pixel bounding box of the remaining portal
				// so we can scissor things outside it
				newStack.Rectangle = ScreenRectangleFromWinding(winding, idE.RenderSystem.IdentitySpace);
		
				// slop might have spread it a pixel outside, so trim it back
				newStack.Rectangle.Intersect(portalStack.Rectangle);

				// generate a set of clipping planes that will further restrict
				// the visible view beyond just the scissor rect
				int addPlanes = winding.PointCount;

				if(addPlanes > idE.MaxPortalPlanes)
				{
					addPlanes = idE.MaxPortalPlanes;
				}

				newStack.PortalPlaneCount = 0;

				for(i = 0; i < addPlanes; i++)
				{
					j = i + 1;

					if(j == winding.PointCount)
					{
						j = 0;
					}

					Vector3 v1 = origin - winding[i];
					Vector3 v2 = origin - winding[j];

					newStack.PortalPlanes[newStack.PortalPlaneCount].Normal = Vector3.Cross( v2, v1 );
					
					// if it is degenerate, skip the plane
					newStack.PortalPlanes[newStack.PortalPlaneCount].Normalize();
					
					if(newStack.PortalPlanes[newStack.PortalPlaneCount].Normal.Length() < 0.01f)
					{
						continue;
					}

					newStack.PortalPlanes[newStack.PortalPlaneCount].FitThroughPoint(origin);
					newStack.PortalPlaneCount++;
				}

				// the last stack plane is the portal plane
				newStack.PortalPlanes[newStack.PortalPlaneCount] = portal.Plane;
				newStack.PortalPlaneCount++;

				FloodViewThroughArea(origin, portal.IntoArea, newStack);
			}
		}