Beispiel #1
0
		/// <summary>
		/// This may be entered multiple times with different planes if more than
		/// one portal sees into the area.
		/// </summary>
		/// <param name="areaNumber"></param>
		/// <param name="portalStack"></param>
		private void AddAreaReferences(int areaNumber, PortalStack portalStack)
		{
			// mark the viewCount, so r_showPortals can display the
			// considered portals
			_portalAreas[areaNumber].ViewCount = idE.RenderSystem.ViewCount;
			
			// add the models and lights, using more precise culling to the planes
			AddAreaEntityReferences(areaNumber, portalStack);
			// TODO: AddAreaLightRefs( areaNum, ps );
		}
Beispiel #2
0
		/// <summary>
		/// Any models that are visible through the current portalStack will have their scissor.
		/// </summary>
		/// <param name="areaNumber"></param>
		/// <param name="portalStack"></param>
		private void AddAreaEntityReferences(int areaNumber, PortalStack portalStack)
		{
			PortalArea area = _portalAreas[areaNumber];

			for(AreaReference areaRef = area.EntityReference.NextArea; areaRef != area.EntityReference; areaRef = areaRef.NextArea)
			{
				idRenderEntity entity = areaRef.Entity;
				
				// debug tool to allow viewing of only one entity at a time
				if((idE.CvarSystem.GetInteger("r_singleEntity") > 0) && (idE.CvarSystem.GetInteger("r_singleEntity") != entity.EntityIndex))
				{
					continue;
				}

				// remove decals that are completely faded away
				// TODO: R_FreeEntityDefFadedDecals( entity, tr.viewDef->renderView.time );

				// check for completely suppressing the model
				if(idE.CvarSystem.GetBool("r_skipSuppress") == false)
				{
					if(entity.Parameters.SuppressSurfaceInViewID == idE.RenderSystem.ViewDefinition.RenderView.ViewID)
					{
						continue;
					}
					else if(entity.Parameters.AllowSurfaceInViewID != idE.RenderSystem.ViewDefinition.RenderView.ViewID)
					{
						continue;
					}
				}

				// cull reference bounds
				if(CullEntityByPortals(entity, portalStack) == true)
				{
					// we are culled out through this portal chain, but it might
					// still be visible through others
					continue;
				}

				ViewEntity viewEntity = SetEntityDefViewEntity(entity);

				// possibly expand the scissor rect
				viewEntity.ScissorRectangle.Union(portalStack.Rectangle);
			}
		}
Beispiel #3
0
		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);
			}
		}
Beispiel #4
0
		/// <summary>
		/// Finds viewLights and viewEntities by flowing from an origin through the visible portals.
		/// origin point can see into.  The planes array defines a volume (positive
		/// sides facing in) that should contain the origin, such as a view frustum or a point light box.
		/// Zero planes assumes an unbounded volume.
		/// </summary>
		/// <param name="origin"></param>
		/// <param name="planes"></param>
		private void FlowViewThroughPortals(Vector3 origin, int planeCount, Plane[] planes)
		{
			View viewDef = idE.RenderSystem.ViewDefinition;

			PortalStack portalStack = new PortalStack();
			portalStack.Rectangle = viewDef.Scissor;
			portalStack.PortalPlaneCount = planeCount;

			for(int i = 0; i < planeCount; i++)
			{
				portalStack.PortalPlanes[i] = planes[i];
			}

			if(viewDef.AreaNumber < 0)
			{
				for(int i = 0; i < _portalAreaCount; i++)
				{
					_areaScreenRect[i] = viewDef.Scissor;
				}

				// if outside the world, mark everything
				for(int i = 0; i < _portalAreaCount; i++)
				{
					AddAreaReferences(i, portalStack);
				}
			}
			else
			{
				for(int i = 0; i < _portalAreaCount; i++)
				{
					_areaScreenRect[i] = new idScreenRect();
				}

				// flood out through portals, setting area viewCount
				FloodViewThroughArea(origin, viewDef.AreaNumber, portalStack);
			}		
		}	
Beispiel #5
0
		/// <summary>
		/// Return true if the entity reference bounds do not intersect the current portal chain.
		/// </summary>
		/// <param name="entity"></param>
		/// <param name="portalStack"></param>
		/// <returns></returns>
		private bool CullEntityByPortals(idRenderEntity entity, PortalStack portalStack)
		{
			if(idE.CvarSystem.GetBool("r_useEntityCulling") == false)
			{
				return false;
			}

			// try to cull the entire thing using the reference bounds.
			// we do not yet do callbacks or dynamic model creation,
			// because we want to do all touching of the model after
			// we have determined all the lights that may effect it,
			// which optimizes cache usage
			return idHelper.CullLocalBox(entity.ReferenceBounds, entity.ModelMatrix, portalStack.PortalPlaneCount, portalStack.PortalPlanes);
		}