Intersect() public method

public Intersect ( Rectangle rhs ) : Rectangle
rhs Rectangle
return Rectangle
Ejemplo n.º 1
0
		public void NeighbourModified( NeighbourIndex index, Rectangle edgerect, Rectangle shadowrect )
		{
			// We can safely assume that we would not have been contacted if it wasn't 
			// important
			var neighbour = GetNeighbour( index );
			if ( neighbour == null )
			{
				return; // bogus request
			}

			var updateGeom = false;
			byte updateDerived = 0;

			if ( !edgerect.IsNull )
			{
				// update edges; match heights first, then recalculate normals
				// reduce to just single line / corner
				var heightMatchRect = new Rectangle();
				GetEdgeRect( index, 1, ref heightMatchRect );
				heightMatchRect = heightMatchRect.Intersect( edgerect );

				for ( var y = heightMatchRect.Top; y < heightMatchRect.Bottom; ++y )
				{
					for ( var x = heightMatchRect.Left; x < heightMatchRect.Right; ++x )
					{
						long nx = 0, ny = 0;
						GetNeighbourPoint( index, x, y, ref nx, ref ny );
						var neighbourHeight = neighbour.GetHeightAtPoint( nx, ny );
						if ( !Utility.RealEqual( neighbourHeight, GetHeightAtPoint( x, y ), 1e-3f ) )
						{
							SetHeightAtPoint( x, y, neighbourHeight );
							if ( !updateGeom )
							{
								updateGeom = true;
								updateDerived |= DERIVED_DATA_ALL;
							}
						}
					}
				}
				// if we didn't need to update heights, we still need to update normals
				// because this was called only if neighbor changed
				if ( !updateGeom )
				{
					// ideally we would deal with normal dirty rect separately (as we do with
					// lightmaps) because a dirty geom rectangle will actually grow by one 
					// element in each direction for normals recalculation. However for
					// the sake of one row/column it's really not worth it.
					this.mDirtyDerivedDataRect.Merge( edgerect );
					updateDerived |= DERIVED_DATA_NORMALS;
				}
			}

			if ( !shadowrect.IsNull )
			{
				// update shadows
				// here we need to widen the rect passed in based on the min/max height 
				// of the *neighbour*
				var lightVec = TerrainGlobalOptions.LightMapDirection;
				var widenedRect = new Rectangle();
				WidenRectByVector( lightVec, shadowrect, neighbour.MinHeight, neighbour.MaxHeight, ref widenedRect );

				// set the special-case lightmap dirty rectangle
				this.mDirtyLightmapFromNeighboursRect.Merge( widenedRect );
				updateDerived |= DERIVED_DATA_LIGHTMAP;
			}

			if ( updateGeom )
			{
				UpdateGeometry();
			}
			if ( updateDerived != 0 )
			{
				UpdateDerivedData( false, updateDerived );
			}
		}
Ejemplo n.º 2
0
		public void NotifyNeighbours()
		{
			// There are 3 things that can need updating:
			// Height at edge - match to neighbour (first one to update 'loses' to other since read-only)
			// Normal at edge - use heights from across boundary too
			// Shadows across edge
			// The extent to which these can affect the current tile vary:
			// Height at edge - only affected by a change at the adjoining edge / corner
			// Normal at edge - only affected by a change to the 2 rows adjoining the edge / corner
			// Shadows across edge - possible effect extends based on the projection of the
			// neighbour AABB along the light direction (worst case scenario)
			if ( !this.mDirtyGeometryRectForNeighbours.IsNull )
			{
				var dirtyRectForNeighbours = new Rectangle( this.mDirtyGeometryRectForNeighbours );
				this.mDirtyGeometryRectForNeighbours.IsNull = true;
				// calculate light update rectangle
				var lightVec = TerrainGlobalOptions.LightMapDirection;
				var lightmapRect = new Rectangle();
				WidenRectByVector( lightVec, dirtyRectForNeighbours, MinHeight, MaxHeight, ref lightmapRect );

				for ( var i = 0; i < (int)NeighbourIndex.Count; ++i )
				{
					var ni = (NeighbourIndex)( i );
					var neighbour = GetNeighbour( ni );
					if ( neighbour == null )
					{
						continue;
					}

					// Intersect the incoming rectangles with the edge regions related to this neighbour
					var edgeRect = new Rectangle();
					GetEdgeRect( ni, 2, ref edgeRect );
					var heightEdgeRect = edgeRect.Intersect( dirtyRectForNeighbours );
					var lightmapEdgeRect = edgeRect.Intersect( lightmapRect );

					if ( !heightEdgeRect.IsNull || !lightmapRect.IsNull )
					{
						// ok, we have something valid to pass on
						var neighbourHeightEdgeRect = new Rectangle();
						var neighbourLightmapEdgeRect = new Rectangle();
						if ( !heightEdgeRect.IsNull )
						{
							GetNeighbourEdgeRect( ni, heightEdgeRect, ref neighbourHeightEdgeRect );
						}

						if ( !lightmapRect.IsNull )
						{
							GetNeighbourEdgeRect( ni, lightmapEdgeRect, ref neighbourLightmapEdgeRect );
						}

						neighbour.NeighbourModified( GetOppositeNeighbour( ni ), neighbourHeightEdgeRect, neighbourLightmapEdgeRect );
					}
				}
			}
		}