Intersects() public méthode

Tests whether this ray intersects the given box.
public Intersects ( AxisAlignedBox box ) : IntersectResult
box AxisAlignedBox
Résultat IntersectResult
		protected virtual void ProcessLeaf( BspNode leaf, Ray tracingRay, float maxDistance, float traceDistance )
		{
			//Check ray against objects
			foreach ( MovableObject obj in leaf.Objects.Values )
			{
				// Skip this object if collision not enabled
				if ( ( obj.QueryFlags & queryMask ) == 0 )
				{
					continue;
				}

				//Test object as bounding box
				IntersectResult result = tracingRay.Intersects( obj.GetWorldBoundingBox() );
				// if the result came back positive and intersection point is inside
				// the node, fire the event handler
				if ( result.Hit && result.Distance <= maxDistance )
				{
					this.listener.OnQueryResult( obj, result.Distance + traceDistance );
				}
			}

			var boundedVolume = new PlaneBoundedVolume( PlaneSide.Positive );
			BspBrush intersectBrush = null;
			float intersectBrushDist = float.PositiveInfinity;

			if ( ( QueryTypeMask & (ulong)SceneQueryTypeMask.WorldGeometry ) != 0 )
			{
				// Check ray against brushes
				if ( ( QueryTypeMask & (ulong)SceneQueryTypeMask.WorldGeometry ) != 0 )
				{
					for ( int brushPoint = 0; brushPoint < leaf.SolidBrushes.Length; brushPoint++ )
					{
						BspBrush brush = leaf.SolidBrushes[ brushPoint ];

						if ( brush == null )
						{
							continue;
						}

						boundedVolume.planes = brush.Planes;

						IntersectResult result = tracingRay.Intersects( boundedVolume );
						// if the result came back positive and intersection point is inside
						// the node, check if this brush is closer
						if ( result.Hit && result.Distance <= maxDistance )
						{
							if ( result.Distance < intersectBrushDist )
							{
								intersectBrushDist = result.Distance;
								intersectBrush = brush;
							}
						}
					}

					if ( intersectBrush != null )
					{
						this.listener.OnQueryResult( intersectBrush.Fragment, intersectBrushDist + traceDistance );
						this.StopRayTracing = true;
					}
				}
			}

			if ( intersectBrush != null )
			{
				this.listener.OnQueryResult( intersectBrush.Fragment, intersectBrushDist + traceDistance );
				this.StopRayTracing = true;
			}
		}
Exemple #2
0
		public override void FindNodes( Ray t,
									  ref List<PCZSceneNode> list,
									  List<Portal> visitedPortals,
									  bool includeVisitors,
									  bool recurseThruPortals,
									  PCZSceneNode exclude )
		{
			// if this zone has an enclosure, check against the enclosure AABB first
			if ( null != mEnclosureNode )
			{
				IntersectResult nsect = t.Intersects( mEnclosureNode.WorldAABB );
				if ( !nsect.Hit )
				{
					// AABB of zone does not intersect t, just return.
					return;
				}
			}

			// check nodes at home in this zone
			foreach ( PCZSceneNode pczsn in mHomeNodeList )
			{
				if ( pczsn != exclude )
				{
					// make sure node is not already in the list (might have been added in another
					// zone it was visiting)
					if ( !list.Contains( pczsn ) )
					{
						IntersectResult nsect = t.Intersects( pczsn.WorldAABB );
						if ( nsect.Hit )
						{
							list.Add( pczsn );
						}
					}
				}
			}

			if ( includeVisitors )
			{
				// check visitor nodes
				foreach ( PCZSceneNode pczsn in mVisitorNodeList )
				{
					if ( pczsn != exclude )
					{
						// make sure node is not already in the list (might have been added in another
						// zone it was visiting)

						if ( !list.Contains( pczsn ) )
						{
							IntersectResult nsect = t.Intersects( pczsn.WorldAABB );
							if ( nsect.Hit )
							{
								list.Add( pczsn );
							}
						}
					}
				}
			}

			// if asked to, recurse through portals
			if ( recurseThruPortals )
			{
				foreach ( Portal portal in mPortals )
				{
					// check portal versus boundign box
					if ( portal.intersects( t ) )
					{
						// make sure portal hasn't already been recursed through
						if ( !visitedPortals.Contains( portal ) )
						{
							// save portal to the visitedPortals list
							visitedPortals.Add( portal );
							// recurse into the connected zone
							portal.getTargetZone().FindNodes( t,
																ref list,
																visitedPortals,
																includeVisitors,
																recurseThruPortals,
																exclude );
						}
					}
				}
			}

		}
Exemple #3
0
		public override void FindNodes( Ray t, ref List<PCZSceneNode> list, List<Portal> visitedPortals, bool includeVisitors, bool recurseThruPortals, PCZSceneNode exclude )
		{
			// if this zone has an enclosure, check against the enclosure AABB first
			if ( null != mEnclosureNode )
			{
				IntersectResult nsect = t.Intersects( mEnclosureNode.WorldAABB );
				if ( !nsect.Hit )
				{
					// AABB of zone does not intersect t, just return.
					return;
				}
			}

			// use the Octree to more efficiently find nodes intersecting the ray
			rootOctree._findNodes( t, ref list, exclude, includeVisitors, false );

			// if asked to, recurse through portals
			if ( recurseThruPortals )
			{
				foreach ( Portal portal in mPortals )
				{
					// check portal versus boundign box
					if ( portal.intersects( t ) )
					{
						// make sure portal hasn't already been recursed through

						if ( !visitedPortals.Contains( portal ) )
						{
							// save portal to the visitedPortals list
							visitedPortals.Add( portal );
							// recurse into the connected zone
							portal.getTargetZone().FindNodes( t,
															  ref list,
															  visitedPortals,
															  includeVisitors,
															  recurseThruPortals,
															  exclude );
						}
					}
				}
			}

		}
		protected virtual void ProcessNode( BspNode node, Ray tracingRay, float maxDistance, float traceDistance )
		{
			// check if ray already encountered a solid brush
			if ( this.StopRayTracing )
			{
				return;
			}

			if ( node.IsLeaf )
			{
				ProcessLeaf( node, tracingRay, maxDistance, traceDistance );
				return;
			}

			IntersectResult result = tracingRay.Intersects( node.SplittingPlane );
			if ( result.Hit )
			{
				if ( result.Distance < maxDistance )
				{
					if ( node.GetSide( tracingRay.Origin ) == PlaneSide.Negative )
					{
						ProcessNode( node.BackNode, tracingRay, result.Distance, traceDistance );
						Vector3 splitPoint = tracingRay.Origin + tracingRay.Direction*result.Distance;
						ProcessNode( node.FrontNode, new Ray( splitPoint, tracingRay.Direction ), maxDistance - result.Distance,
						             traceDistance + result.Distance );
					}
					else
					{
						ProcessNode( node.FrontNode, tracingRay, result.Distance, traceDistance );
						Vector3 splitPoint = tracingRay.Origin + tracingRay.Direction*result.Distance;
						ProcessNode( node.BackNode, new Ray( splitPoint, tracingRay.Direction ), maxDistance - result.Distance,
						             traceDistance + result.Distance );
					}
				}
				else
				{
					ProcessNode( node.GetNextNode( tracingRay.Origin ), tracingRay, maxDistance, traceDistance );
				}
			}
			else
			{
				ProcessNode( node.GetNextNode( tracingRay.Origin ), tracingRay, maxDistance, traceDistance );
			}
		}
		public bool CalculateCurrentLod( Camera cam, Real cFactor )
		{
			this.mSelfOrChildRendered = false;

			//check children first.
			int childrenRenderedOut = 0;
			if ( !IsLeaf )
			{
				for ( int i = 0; i < 4; ++i )
				{
					if ( this.mChildren[ i ].CalculateCurrentLod( cam, cFactor ) )
					{
						++childrenRenderedOut;
					}
				}
			}

			if ( childrenRenderedOut == 0 )
			{
				// no children were within their LOD ranges, so we should consider our own
				Vector3 localPos = cam.DerivedPosition - this.mLocalCentre - this.mTerrain.Position;
				Real dist;
				if ( TerrainGlobalOptions.UseRayBoxDistanceCalculation )
				{
					// Get distance to this terrain node (to closest point of the box)
					// head towards centre of the box (note, box may not cover mLocalCentre because of height)
					var dir = this.mAABB.Center - localPos;
					dir.Normalize();
					var ray = new Ray( localPos, dir );
					var intersectRes = ray.Intersects( this.mAABB );

					// ray will always intersect, we just want the distance
					dist = intersectRes.Distance;
				}
				else
				{
					// distance to tile centre
					dist = localPos.Length;
					// deduct half the radius of the box, assume that on average the 
					// worst case is best approximated by this
					dist -= ( this.mBoundingRadius*0.5f );
				}

				// Do material LOD
				var material = Material;
				LodStrategy str = material.LodStrategy;
				Real lodValue = str.GetValue( this.mMovable, cam );
				// Get the index at this biased depth
				this.mMaterialLodIndex = (ushort)material.GetLodIndex( lodValue );


				// For each LOD, the distance at which the LOD will transition *downwards*
				// is given by 
				// distTransition = maxDelta * cFactor;
				int lodLvl = 0;
				this.mCurrentLod = -1;
				foreach ( LodLevel i in this.mLodLevels )
				{
					// If we have no parent, and this is the lowest LOD, we always render
					// this is the 'last resort' so to speak, we always enoucnter this last
					if ( lodLvl + 1 == this.mLodLevels.Count && this.mParent == null )
					{
						CurrentLod = lodLvl;
						this.mSelfOrChildRendered = true;
						this.mLodTransition = 0;
					}
					else
					{
						//check the distance
						LodLevel ll = i;
						// Calculate or reuse transition distance
						Real distTransition;
						if ( Utility.RealEqual( cFactor, ll.LastCFactor ) )
						{
							distTransition = ll.LastTransitionDist;
						}
						else
						{
							distTransition = ll.MaxHeightDelta*cFactor;
							ll.LastCFactor = cFactor;
							ll.LastTransitionDist = distTransition;
						}

						if ( dist < distTransition )
						{
							// we're within range of this LOD
							CurrentLod = lodLvl;
							this.mSelfOrChildRendered = true;

							if ( this.mTerrain.IsMorphRequired )
							{
								// calculate the transition percentage
								// we need a percentage of the total distance for just this LOD, 
								// which means taking off the distance for the next higher LOD
								// which is either the previous entry in the LOD list, 
								// or the largest of any children. In both cases these will
								// have been calculated before this point, since we process
								// children first. Distances at lower LODs are guaranteed
								// to be larger than those at higher LODs

								Real distTotal = distTransition;
								if ( IsLeaf )
								{
									// Any higher LODs?
									if ( !i.Equals( this.mLodLevels[ 0 ] ) )
									{
										int prev = lodLvl - 1;
										distTotal -= this.mLodLevels[ prev ].LastTransitionDist;
									}
								}
								else
								{
									// Take the distance of the lowest LOD of child
									LodLevel childLod =
										this.mChildWithMaxHeightDelta.GetLodLevel( (ushort)( this.mChildWithMaxHeightDelta.LodCount - 1 ) );
									distTotal -= childLod.LastTransitionDist;
								}
								// fade from 0 to 1 in the last 25% of the distance
								Real distMorphRegion = distTotal*0.25f;
								Real distRemain = distTransition - dist;

								this.mLodTransition = 1.0f - ( distRemain/distMorphRegion );
								this.mLodTransition = System.Math.Min( 1.0f, this.mLodTransition );
								this.mLodTransition = System.Math.Max( 0.0f, this.mLodTransition );

								// Pass both the transition % and target LOD (GLOBAL current + 1)
								// this selectively applies the morph just to the
								// vertices which would drop out at this LOD, even 
								// while using the single shared vertex data
								this.mRend.SetCustomParameter( Terrain.LOD_MORPH_CUSTOM_PARAM,
								                               new Vector4( this.mLodTransition, this.mCurrentLod + this.mBaseLod + 1, 0, 0 ) );
							} //end if

							// since LODs are ordered from highest to lowest detail, 
							// we can stop looking now
							break;
						} //end if
					} //end else
					++lodLvl;
				} //end for each
			} //end if
			else
			{
				// we should not render ourself
				this.mCurrentLod = -1;
				this.mSelfOrChildRendered = true;
				if ( childrenRenderedOut < 4 )
				{
					// only *some* children decided to render on their own, but either 
					// none or all need to render, so set the others manually to their lowest
					for ( int i = 0; i < 4; ++i )
					{
						TerrainQuadTreeNode child = this.mChildren[ i ];
						if ( !child.IsSelfOrChildrenRenderedAtCurrentLod )
						{
							child.CurrentLod = child.LodCount - 1;
							child.LodTransition = 1.0f;
						}
					}
				} //(childRenderedCount < 4)
			} // (childRenderedCount == 0)

			return this.mSelfOrChildRendered;
		}
Exemple #6
0
		public void WidenRectByVector( Vector3 vec, Rectangle inRect, Real minHeight, Real maxHeight, ref Rectangle outRect )
		{
			outRect = inRect;

			var p = new Plane();
			switch ( Alignment )
			{
				case Alignment.Align_X_Y:
					p.Redefine( Vector3.UnitZ, new Vector3( 0, 0, vec.z < 0.0f ? minHeight : maxHeight ) );
					break;

				case Alignment.Align_X_Z:
					p.Redefine( Vector3.UnitY, new Vector3( 0, vec.y < 0.0f ? minHeight : maxHeight, 0 ) );
					break;

				case Alignment.Align_Y_Z:
					p.Redefine( Vector3.UnitX, new Vector3( vec.x < 0.0f ? minHeight : maxHeight, 0, 0 ) );
					break;
			}
			var verticalVal = vec.Dot( p.Normal );

			if ( Utility.RealEqual( verticalVal, 0.0f ) )
			{
				return;
			}

			var corners = new Vector3[4];
			var startHeight = verticalVal < 0.0f ? maxHeight : minHeight;
			GetPoint( inRect.Left, inRect.Top, startHeight, ref corners[ 0 ] );
			GetPoint( inRect.Right - 1, inRect.Top, startHeight, ref corners[ 1 ] );
			GetPoint( inRect.Left, inRect.Bottom - 1, startHeight, ref corners[ 2 ] );
			GetPoint( inRect.Right - 1, inRect.Bottom - 1, startHeight, ref corners[ 3 ] );

			for ( int i = 0; i < 4; ++i )
			{
				var ray = new Ray( corners[ i ] + this.mPos, vec );
				var rayHit = ray.Intersects( p );
				if ( rayHit.Hit )
				{
					var pt = ray.GetPoint( rayHit.Distance );
					// convert back to terrain point
					var terrainHitPos = Vector3.Zero;
					GetTerrainPosition( pt, ref terrainHitPos );
					// build rectangle which has rounded down & rounded up values
					// remember right & bottom are exclusive
					var mergeRect = new Rectangle( (long)terrainHitPos.x*( this.mSize - 1 ), (long)terrainHitPos.y*( this.mSize - 1 ),
												   (long)( terrainHitPos.x*(float)( this.mSize - 1 ) + 0.5f ) + 1,
												   (long)( terrainHitPos.y*(float)( this.mSize - 1 ) + 0.5f ) + 1 );
					outRect.Merge( mergeRect );
				}
			}
		}
Exemple #7
0
		protected KeyValuePair<bool, Vector3> CheckQuadIntersection( int x, int z, Ray ray )
		{
			// build the two planes belonging to the quad's triangles
			Vector3 v1 = new Vector3( x, this.mHeightData[ z + this.mSize*x ], z ),
					v2 = new Vector3( x + 1, this.mHeightData[ z + this.mSize*( x + 1 ) ], z ),
					v3 = new Vector3( x, this.mHeightData[ ( z + 1 ) + this.mSize*x ], z + 1 ),
					v4 = new Vector3( x + 1, this.mHeightData[ ( z + 1 ) + this.mSize*( x + 1 ) ], z + 1 );

			Plane p1 = new Plane(), p2 = new Plane();
			var oddRow = false;
			if ( z%2 != 0 )
			{
				/* odd
					3---4
					| \ |
					1---2
					*/
				p1.Redefine( v2, v4, v3 );
				p2.Redefine( v1, v2, v3 );
				oddRow = true;
			}
			else
			{
				/* even
					3---4
					| / |
					1---2
					*/
				p1.Redefine( v1, v2, v4 );
				p2.Redefine( v1, v4, v3 );
			}
			// Test for intersection with the two planes. 
			// Then test that the intersection points are actually
			// still inside the triangle (with a small error margin)
			// Also check which triangle it is in
			var planeInt = ray.Intersects( p1 );
			if ( planeInt.Hit )
			{
				var where = ray.GetPoint( planeInt.Distance );
				var rel = where - v1;
				if ( rel.x >= -0.01 && rel.x <= 1.01 && rel.z >= -0.01 && rel.z <= 1.01 // quad bounds
					 && ( ( rel.x >= rel.z && !oddRow ) || ( rel.x >= ( 1 - rel.z ) && oddRow ) ) ) // triangle bounds
				{
					return new KeyValuePair<bool, Vector3>( true, where );
				}
			}
			planeInt = ray.Intersects( p2 );
			if ( planeInt.Hit )
			{
				var where = ray.GetPoint( planeInt.Distance );
				var rel = where - v1;
				if ( rel.x >= -0.01 && rel.x <= 1.01 && rel.z >= -0.01 && rel.z <= 1.01 // quad bounds
					 && ( ( rel.x <= rel.z && !oddRow ) || ( rel.x <= ( 1 - rel.z ) && oddRow ) ) ) // triangle bounds
				{
					return new KeyValuePair<bool, Vector3>( true, where );
				}
			}

			return new KeyValuePair<bool, Vector3>( false, Vector3.Zero );
		}
Exemple #8
0
		public KeyValuePair<bool, Vector3> RayIntersects( Ray ray, bool cascadeToNeighbours, Real distanceLimit )
		{
			KeyValuePair<bool, Vector3> Result;
			// first step: convert the ray to a local vertex space
			// we assume terrain to be in the x-z plane, with the [0,0] vertex
			// at origin and a plane distance of 1 between vertices.
			// This makes calculations easier.
			var rayOrigin = ray.Origin - Position;
			var rayDirection = ray.Direction;
			// change alignment
			Vector3 tmp;
			switch ( Alignment )
			{
				case Alignment.Align_X_Y:
					Utility.Swap<Real>( ref rayOrigin.y, ref rayOrigin.z );
					Utility.Swap<Real>( ref rayDirection.y, ref rayDirection.z );
					break;

				case Alignment.Align_Y_Z:
					// x = z, z = y, y = -x
					tmp.x = rayOrigin.z;
					tmp.z = rayOrigin.y;
					tmp.y = -rayOrigin.x;
					rayOrigin = tmp;
					tmp.x = rayDirection.z;
					tmp.z = rayDirection.y;
					tmp.y = -rayDirection.x;
					rayDirection = tmp;
					break;

				case Alignment.Align_X_Z:
					// already in X/Z but values increase in -Z
					rayOrigin.z = -rayOrigin.z;
					rayDirection.z = -rayDirection.z;
					break;
			}
			// readjust coordinate origin
			rayOrigin.x += this.mWorldSize/2;
			rayOrigin.z += this.mWorldSize/2;
			// scale down to vertex level
			rayOrigin.x /= this.mScale;
			rayOrigin.z /= this.mScale;
			rayDirection.x /= this.mScale;
			rayDirection.z /= this.mScale;
			rayDirection.Normalize();
			var localRay = new Ray( rayOrigin, rayDirection );

			// test if the ray actually hits the terrain's bounds
			var maxHeight = MaxHeight;
			var minHeight = MinHeight;

			var aabb = new AxisAlignedBox( new Vector3( 0, minHeight, 0 ), new Vector3( this.mSize, maxHeight, this.mSize ) );
			var aabbTest = localRay.Intersects( aabb );
			if ( !aabbTest.Hit )
			{
				if ( cascadeToNeighbours )
				{
					var neighbour = RaySelectNeighbour( ray, distanceLimit );
					if ( neighbour != null )
					{
						return neighbour.RayIntersects( ray, cascadeToNeighbours, distanceLimit );
					}
				}
				return new KeyValuePair<bool, Vector3>( false, new Vector3() );
			}
			// get intersection point and move inside
			var cur = localRay.GetPoint( aabbTest.Distance );

			// now check every quad the ray touches
			var quadX = Utility.Min( Utility.Max( (int)( cur.x ), 0 ), (int)this.mSize - 2 );
			var quadZ = Utility.Min( Utility.Max( (int)( cur.z ), 0 ), (int)this.mSize - 2 );
			var flipX = ( rayDirection.x < 0 ? 0 : 1 );
			var flipZ = ( rayDirection.z < 0 ? 0 : 1 );
			var xDir = ( rayDirection.x < 0 ? -1 : 1 );
			var zDir = ( rayDirection.z < 0 ? -1 : 1 );

			Result = new KeyValuePair<bool, Vector3>( true, Vector3.Zero );
			var dummyHighValue = (Real)this.mSize*10000;

			while ( cur.y >= ( minHeight - 1e-3 ) && cur.y <= ( maxHeight + 1e-3 ) )
			{
				if ( quadX < 0 || quadX >= (int)this.mSize - 1 || quadZ < 0 || quadZ >= (int)this.mSize - 1 )
				{
					break;
				}

				Result = CheckQuadIntersection( quadX, quadZ, localRay );
				if ( Result.Key )
				{
					break;
				}

				// determine next quad to test
				var xDist = Utility.RealEqual( rayDirection.x, 0.0f ) ? dummyHighValue : ( quadX - cur.x + flipX )/rayDirection.x;
				var zDist = Utility.RealEqual( rayDirection.z, 0.0f ) ? dummyHighValue : ( quadZ - cur.z + flipZ )/rayDirection.z;
				if ( xDist < zDist )
				{
					quadX += xDir;
					cur += rayDirection*xDist;
				}
				else
				{
					quadZ += zDir;
					cur += rayDirection*zDist;
				}
			}
			var resVec = Vector3.Zero;

			if ( Result.Key )
			{
				// transform the point of intersection back to world space
				resVec = Result.Value;
				resVec.x *= this.mScale;
				resVec.z *= this.mScale;
				resVec.x -= this.mWorldSize/2;
				resVec.z -= this.mWorldSize/2;
				switch ( Alignment )
				{
					case Alignment.Align_X_Y:
						Utility.Swap<Real>( ref resVec.y, ref resVec.z );
						break;

					case Alignment.Align_Y_Z:
						// z = x, y = z, x = -y
						tmp.x = -rayOrigin.y;
						tmp.y = rayOrigin.z;
						tmp.z = rayOrigin.x;
						rayOrigin = tmp;
						break;

					case Alignment.Align_X_Z:
						resVec.z = -resVec.z;
						break;
				}
				resVec += Position;
			}
			else if ( cascadeToNeighbours )
			{
				var neighbour = RaySelectNeighbour( ray, distanceLimit );
				if ( neighbour != null )
				{
					Result = neighbour.RayIntersects( ray, cascadeToNeighbours, distanceLimit );
				}
			}
			return new KeyValuePair<bool, Vector3>( Result.Key, resVec );
		}
Exemple #9
0
		// Check if a portal intersects a ray
		// NOTE: Kinda using my own invented routine here for quad portals... Better do a lot of testing!
		public bool intersects( Ray ray )
		{
			// Only check if portal is open
			if ( mOpen )
			{
				if ( mType == PORTAL_TYPE.PORTAL_TYPE_QUAD )
				{
					// since ogre doesn't have built in support for a quad, I'm going to first
					// find the intersection point (if any) of the ray and the portal plane.  Then
					// using the intersection point, I take the cross product of each side of the portal
					// (0,1,intersect), (1,2, intersect), (2,3, intersect), and (3,0,intersect).  If
					// all 4 cross products have vectors pointing in the same direction, then the
					// intersection point is within the portal, otherwise it is outside.

					IntersectResult result = ray.Intersects( mDerivedPlane );

					if ( result.Hit )
					{
						// the ray intersects the plane, now walk around the edges
						Vector3 isect = ray.GetPoint( result.Distance );
						Vector3 cross, vect1, vect2;
						Vector3 cross2, vect3, vect4;
						vect1 = mDerivedCorners[ 1 ] - mDerivedCorners[ 0 ];
						vect2 = isect - mDerivedCorners[ 0 ];
						cross = vect1.Cross( vect2 );
						vect3 = mDerivedCorners[ 2 ] - mDerivedCorners[ 1 ];
						vect4 = isect - mDerivedCorners[ 1 ];
						cross2 = vect3.Cross( vect4 );
						if ( cross.Dot( cross2 ) < 0 )
						{
							return false;
						}
						vect1 = mDerivedCorners[ 3 ] - mDerivedCorners[ 2 ];
						vect2 = isect - mDerivedCorners[ 2 ];
						cross = vect1.Cross( vect2 );
						if ( cross.Dot( cross2 ) < 0 )
						{
							return false;
						}
						vect1 = mDerivedCorners[ 0 ] - mDerivedCorners[ 3 ];
						vect2 = isect - mDerivedCorners[ 3 ];
						cross = vect1.Cross( vect2 );
						if ( cross.Dot( cross2 ) < 0 )
						{
							return false;
						}
						// all cross products pointing same way, so intersect
						// must be on the inside of the portal!
						return true;
					}

					return false;
				}
				else if ( mType == PORTAL_TYPE.PORTAL_TYPE_AABB )
				{
					AxisAlignedBox aabb = new AxisAlignedBox( mDerivedCorners[ 0 ], mDerivedCorners[ 1 ] );
					IntersectResult result = ray.Intersects( aabb );
					return result.Hit;
				}
				else // sphere
				{
					IntersectResult result = ray.Intersects( mDerivedSphere );
					return result.Hit;
				}
			}
			return false;
		}