Redefine() public method

Redefine this plane based on a normal and a point.
public Redefine ( Axiom.Math.Vector3 rkNormal, Axiom.Math.Vector3 rkPoint ) : void
rkNormal Axiom.Math.Vector3 Normal vector
rkPoint Axiom.Math.Vector3 Point vector
return void
Ejemplo n.º 1
0
		public void CalculateMinLevelDist2( Real C )
#endif
		{
			//level 0 has no delta.
			this.mMinLevelDistSqr[ 0 ] = 0;

			int i, j;

			for ( var level = 1; level < this.mOptions.maxGeoMipMapLevel; level++ )
			{
				this.mMinLevelDistSqr[ level ] = 0;

				var step = 1 << level;
				// The step of the next higher LOD
				var higherstep = step >> 1;

#if AXIOM_SAFE_ONLY
					ITypePointer<float> pDeltas = null;
#else
				float* pDeltas = null;
#endif
				BufferBase dataPtr;
				if ( this.mOptions.lodMorph )
				{
					// Create a set of delta values (store at index - 1 since 0 has none)
					this.mDeltaBuffers[ level - 1 ] = CreateDeltaBuffer();
					// Lock, but don't discard (we want the pre-initialised zeros)

					dataPtr = this.mDeltaBuffers[ level - 1 ].Lock( BufferLocking.Normal );
					pDeltas = dataPtr.ToFloatPointer();
				}

				for ( j = 0; j < this.mOptions.tileSize - step; j += step )
				{
					for ( i = 0; i < this.mOptions.tileSize - step; i += step )
					{
						/* Form planes relating to the lower detail tris to be produced
						For tri lists and even tri strip rows, they are this shape:
						x---x
						| / |
						x---x
						For odd tri strip rows, they are this shape:
						x---x
						| \ |
						x---x
						*/

						var v1 = new Vector3( Vertex( i, j, 0 ), Vertex( i, j, 1 ), Vertex( i, j, 2 ) );
						var v2 = new Vector3( Vertex( i + step, j, 0 ), Vertex( i + step, j, 1 ), Vertex( i + step, j, 2 ) );
						var v3 = new Vector3( Vertex( i, j + step, 0 ), Vertex( i, j + step, 1 ), Vertex( i, j + step, 2 ) );
						var v4 = new Vector3( Vertex( i + step, j + step, 0 ), Vertex( i + step, j + step, 1 ),
						                      Vertex( i + step, j + step, 2 ) );

						Plane t1, t2;
						t1 = new Plane();
						t2 = new Plane();
						var backwardTri = false;
						if ( !this.mOptions.useTriStrips || j%2 == 0 )
						{
							t1.Redefine( v1, v3, v2 );
							t2.Redefine( v2, v3, v4 );
						}
						else
						{
							t1.Redefine( v1, v3, v4 );
							t2.Redefine( v1, v4, v2 );
							backwardTri = true;
						}

						// include the bottommost row of vertices if this is the last row
						var zubound = ( j == ( this.mOptions.tileSize - step ) ? step : step - 1 );
						for ( var z = 0; z <= zubound; z++ )
						{
							// include the rightmost col of vertices if this is the last col
							var xubound = ( i == ( this.mOptions.tileSize - step ) ? step : step - 1 );
							for ( var x = 0; x <= xubound; x++ )
							{
								var fulldetailx = i + x;
								var fulldetailz = j + z;
								if ( fulldetailx%step == 0 && fulldetailz%step == 0 )
								{
									// Skip, this one is a vertex at this level
									continue;
								}

								var zpct = (Real)z/(Real)step;
								var xpct = (Real)x/(Real)step;

								//interpolated height
								var actualPos = new Vector3( Vertex( fulldetailx, fulldetailz, 0 ), Vertex( fulldetailx, fulldetailz, 1 ),
								                             Vertex( fulldetailx, fulldetailz, 2 ) );
								Real interp_h;
								// Determine which tri we're on
								if ( ( xpct + zpct <= 1.0f && !backwardTri ) || ( xpct + ( 1 - zpct ) <= 1.0f && backwardTri ) )
								{
									// Solve for x/z
									interp_h = ( -( t1.Normal.x*actualPos.x ) - t1.Normal.z*actualPos.z - t1.D )/t1.Normal.y;
								}
								else
								{
									// Second tri
									interp_h = ( -( t2.Normal.x*actualPos.x ) - t2.Normal.z*actualPos.z - t2.D )/t2.Normal.y;
								}

								Real actual_h = Vertex( fulldetailx, fulldetailz, 1 );
								//Check: not sure about fabs used here...
								Real delta = Math.Abs( interp_h - actual_h );

								var D2 = delta*delta*C*C;

								if ( this.mMinLevelDistSqr[ level ] < D2 )
								{
									this.mMinLevelDistSqr[ level ] = D2;
								}

								// Should be save height difference?
								// Don't morph along edges
								if ( this.mOptions.lodMorph && fulldetailx != 0 && fulldetailx != ( this.mOptions.tileSize - 1 ) &&
								     fulldetailz != 0 &&
								     fulldetailz != ( this.mOptions.tileSize - 1 ) )
								{
									// Save height difference
									pDeltas[ (int)( fulldetailx + ( fulldetailz*this.mOptions.tileSize ) ) ] = interp_h - actual_h;
								}
							}
						}
					}
				}

				// Unlock morph deltas if required
				if ( this.mOptions.lodMorph )
				{
					this.mDeltaBuffers[ level - 1 ].Unlock();
				}
			}


			// Post validate the whole set
			for ( i = 1; i < this.mOptions.maxGeoMipMapLevel; i++ )
			{
				// Make sure no LOD transition within the tile
				// This is especially a problem when using large tiles with flat areas
				/* Hmm, this can look bad on some areas, disable for now
				Vector3 delta(_vertex(0,0,0), mCenter.y, _vertex(0,0,2));
				delta = delta - mCenter;
				Real minDist = delta.squaredLength();
				mMinLevelDistSqr[ i ] = std::max(mMinLevelDistSqr[ i ], minDist);
				*/

				//make sure the levels are increasing...
				if ( this.mMinLevelDistSqr[ i ] < this.mMinLevelDistSqr[ i - 1 ] )
				{
					this.mMinLevelDistSqr[ i ] = this.mMinLevelDistSqr[ i - 1 ];
				}
			}

			// Now reverse traverse the list setting the 'next level down'
			Real lastDist = -1;
			var lastIndex = 0;
			for ( i = this.mOptions.maxGeoMipMapLevel - 1; i >= 0; --i )
			{
				if ( i == this.mOptions.maxGeoMipMapLevel - 1 )
				{
					// Last one is always 0
					lastIndex = i;
					lastDist = this.mMinLevelDistSqr[ i ];
					this.mNextLevelDown[ i ] = 0;
				}
				else
				{
					this.mNextLevelDown[ i ] = lastIndex;
					if ( this.mMinLevelDistSqr[ i ] != lastDist )
					{
						lastIndex = i;
						lastDist = this.mMinLevelDistSqr[ i ];
					}
				}
			}
		}
Ejemplo n.º 2
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 );
				}
			}
		}
Ejemplo n.º 3
0
		public PixelBox CalculateNormals( Rectangle rect, ref Rectangle outFinalRect )
		{
			// Widen the rectangle by 1 element in all directions since height
			// changes affect neighbours normals
			var widenedRect = new Rectangle( Utility.Max( 0L, rect.Left - 1L ), Utility.Max( 0L, rect.Top - 1L ),
											 Utility.Min( (long)this.mSize, rect.Right + 1L ),
											 Utility.Min( (long)this.mSize, rect.Bottom + 1L ) );

			// allocate memory for RGB
			var pData = new byte[widenedRect.Width*widenedRect.Height*3];
			var pixbox = new PixelBox( (int)widenedRect.Width, (int)widenedRect.Height, 1, PixelFormat.BYTE_RGB,
									   BufferBase.Wrap( pData ) );

			// Evaluate normal like this
			//  3---2---1
			//  | \ | / |
			//	4---P---0
			//  | / | \ |
			//	5---6---7

			var plane = new Plane();
			for ( var y = widenedRect.Top; y < widenedRect.Bottom; ++y )
			{
				for ( var x = widenedRect.Left; x < widenedRect.Right; ++x )
				{
					var cumulativeNormal = Vector3.Zero;

					// Build points to sample
					var centrePoint = Vector3.Zero;
					var adjacentPoints = new Vector3[8];
					GetPointFromSelfOrNeighbour( x, y, ref centrePoint );
					GetPointFromSelfOrNeighbour( x + 1, y, ref adjacentPoints[ 0 ] );
					GetPointFromSelfOrNeighbour( x + 1, y + 1, ref adjacentPoints[ 1 ] );
					GetPointFromSelfOrNeighbour( x, y + 1, ref adjacentPoints[ 2 ] );
					GetPointFromSelfOrNeighbour( x - 1, y + 1, ref adjacentPoints[ 3 ] );
					GetPointFromSelfOrNeighbour( x - 1, y, ref adjacentPoints[ 4 ] );
					GetPointFromSelfOrNeighbour( x - 1, y - 1, ref adjacentPoints[ 5 ] );
					GetPointFromSelfOrNeighbour( x, y - 1, ref adjacentPoints[ 6 ] );
					GetPointFromSelfOrNeighbour( x + 1, y - 1, ref adjacentPoints[ 7 ] );

					for ( var i = 0; i < 8; ++i )
					{
						plane.Redefine( centrePoint, adjacentPoints[ i ], adjacentPoints[ ( i + 1 )%8 ] );
						cumulativeNormal += plane.Normal;
					}

					// normalise & store normal
					cumulativeNormal.Normalize();

					// encode as RGB, object space
					// invert the Y to deal with image space
					var storeX = x - widenedRect.Left;
					var storeY = widenedRect.Bottom - y - 1;

					var pStore = ( ( storeY*widenedRect.Width ) + storeX )*3;
					pData[ pStore++ ] = (byte)( ( cumulativeNormal.x + 1.0f )*0.5f*255.0f );
					pData[ pStore++ ] = (byte)( ( cumulativeNormal.y + 1.0f )*0.5f*255.0f );
					pData[ pStore++ ] = (byte)( ( cumulativeNormal.z + 1.0f )*0.5f*255.0f );
				} //x
			} //y

			outFinalRect = widenedRect;
			return pixbox;
		}
Ejemplo n.º 4
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 );
		}
Ejemplo n.º 5
0
		public Rectangle CalculateHeightDeltas( Rectangle rect )
		{
			var clampedRect = new Rectangle( rect );

			clampedRect.Left = Utility.Max( 0L, clampedRect.Left );
			clampedRect.Top = Utility.Max( 0L, clampedRect.Top );
			clampedRect.Right = Utility.Min( (long)this.mSize, clampedRect.Right );
			clampedRect.Bottom = Utility.Min( (long)this.mSize, clampedRect.Bottom );

			var finalRect = new Rectangle( clampedRect );
			QuadTree.PreDeltaCalculation( clampedRect );

			// Iterate over target levels, 
			for ( var targetLevel = 1; targetLevel < NumLodLevels; ++targetLevel )
			{
				var sourceLevel = targetLevel - 1;
				var step = 1 << targetLevel;

				// need to widen the dirty rectangle since change will affect surrounding
				// vertices at lower LOD
				var widendRect = rect;
				widendRect.Left = Utility.Max( 0L, widendRect.Left - step );
				widendRect.Top = Utility.Max( 0L, widendRect.Top - step );
				widendRect.Right = Utility.Min( (long)this.mSize, widendRect.Right + step );
				widendRect.Bottom = Utility.Min( (long)this.mSize, widendRect.Bottom + step );

				// keep a merge of the widest
				finalRect = finalRect.Merge( widendRect );

				// now round the rectangle at this level so that it starts & ends on 
				// the step boundaries
				var lodRect = new Rectangle( widendRect );
				lodRect.Left -= lodRect.Left%step;
				lodRect.Top -= lodRect.Top%step;
				if ( lodRect.Right%step != 0 )
				{
					lodRect.Right += step - ( lodRect.Right%step );
				}
				if ( lodRect.Bottom%step != 0 )
				{
					lodRect.Bottom += step - ( lodRect.Bottom%step );
				}

				for ( var j = (int)lodRect.Top; j < lodRect.Bottom - step; j += step )
				{
					for ( var i = (int)lodRect.Left; i < lodRect.Right - step; i += step )
					{
						// Form planes relating to the lower detail tris to be produced
						// For even tri strip rows, they are this shape:
						// 2---3
						// | / |
						// 0---1
						// For odd tri strip rows, they are this shape:
						// 2---3
						// | \ |
						// 0---1
						var v0 = Vector3.Zero;
						var v1 = Vector3.Zero;
						var v2 = Vector3.Zero;
						var v3 = Vector3.Zero;

						GetPointAlign( i, j, Alignment.Align_X_Y, ref v0 );
						GetPointAlign( i + step, j, Alignment.Align_X_Y, ref v1 );
						GetPointAlign( i, j + step, Alignment.Align_X_Y, ref v2 );
						GetPointAlign( i + step, j + step, Alignment.Align_X_Y, ref v3 );

						var t1 = new Plane();
						var t2 = new Plane();
						var backwardTri = false;
						// Odd or even in terms of target level
						if ( ( j/step )%2 == 0 )
						{
							t1.Redefine( v0, v1, v3 );
							t2.Redefine( v0, v3, v2 );
						}
						else
						{
							t1.Redefine( v1, v3, v2 );
							t2.Redefine( v0, v1, v2 );
							backwardTri = true;
						}

						//include the bottommost row of vertices if this is the last row
						var yubound = ( j == ( this.mSize - step ) ? step : step - 1 );
						for ( var y = 0; y <= yubound; y++ )
						{
							// include the rightmost col of vertices if this is the last col
							var xubound = ( i == ( this.mSize - step ) ? step : step - 1 );
							for ( var x = 0; x <= xubound; x++ )
							{
								var fulldetailx = i + x;
								var fulldetaily = j + y;
								if ( fulldetailx%step == 0 && fulldetaily%step == 0 )
								{
									// Skip, this one is a vertex at this level
									continue;
								}
								var ypct = (Real)y/(Real)step;
								var xpct = (Real)x/(Real)step;

								//interpolated height
								var actualPos = Vector3.Zero;
								GetPointAlign( fulldetailx, fulldetaily, Alignment.Align_X_Y, ref actualPos );
								Real interp_h = 0;
								// Determine which tri we're on 
								if ( ( xpct > ypct && !backwardTri ) || ( xpct > ( 1 - ypct ) && backwardTri ) )
								{
									// Solve for x/z
									interp_h = ( -t1.Normal.x*actualPos.x - t1.Normal.y*actualPos.y - t1.D )/t1.Normal.z;
								}
								else
								{
									// Second tri
									interp_h = ( -t2.Normal.x*actualPos.x - t2.Normal.y*actualPos.y - t2.D )/t2.Normal.z;
								}

								var actual_h = actualPos.z;
								var delta = interp_h - actual_h;

								// max(delta) is the worst case scenario at this LOD
								// compared to the original heightmap
								if ( delta == float.NaN )
								{
								}
								// tell the quadtree about this 
								QuadTree.NotifyDelta( (ushort)fulldetailx, (ushort)fulldetaily, (ushort)sourceLevel, delta );


								// If this vertex is being removed at this LOD, 
								// then save the height difference since that's the move
								// it will need to make. Vertices to be removed at this LOD
								// are halfway between the steps, but exclude those that
								// would have been eliminated at earlier levels
								int halfStep = step/2;
								if ( ( ( fulldetailx%step ) == halfStep && ( fulldetaily%halfStep ) == 0 ) ||
									 ( ( fulldetaily%step ) == halfStep && ( fulldetailx%halfStep ) == 0 ) )
								{
#if !AXIOM_SAFE_ONLY
									unsafe
#endif
									{
										// Save height difference 
										var pDest = GetDeltaData( fulldetailx, fulldetaily ).ToFloatPointer();
										pDest[ 0 ] = delta;
									}
								}
							} //x
						} //y
					}
				} //j
			} //targetlevel

			QuadTree.PostDeltaCalculation( clampedRect );

			return finalRect;
		}
Ejemplo n.º 6
0
		public float GetHeightAtTerrainPosition( Real x, Real y )
		{
			// get left / bottom points (rounded down)
			Real factor = this.mSize - 1;
			Real invFactor = 1.0f/factor;

			var startX = (long)( x*factor );
			var startY = (long)( y*factor );
			var endX = startX + 1;
			var endY = startY + 1;

			// now get points in terrain space (effectively rounding them to boundaries)
			// note that we do not clamp! We need a valid plane
			Real startXTS = startX*invFactor;
			Real startYTS = startY*invFactor;
			Real endXTS = endX*invFactor;
			Real endYTS = endY*invFactor;

			//now clamp
			endX = Utility.Min( endX, (long)this.mSize - 1 );
			endY = Utility.Min( endY, (long)this.mSize - 1 );

			// get parametric from start coord to next point
			Real xParam = ( x - startXTS )/invFactor;
			Real yParam = ( y - startYTS )/invFactor;

			/* For even / odd tri strip rows, triangles are this shape:
				even     odd
				3---2   3---2
				| / |   | \ |
				0---1   0---1
				*/

			// Build all 4 positions in terrain space, using point-sampled height
			var v0 = new Vector3( startXTS, startYTS, GetHeightAtPoint( startX, startY ) );
			var v1 = new Vector3( endXTS, startYTS, GetHeightAtPoint( endX, startY ) );
			var v2 = new Vector3( endXTS, endYTS, GetHeightAtPoint( endX, endY ) );
			var v3 = new Vector3( startXTS, endYTS, GetHeightAtPoint( startX, endY ) );
			//define this plane in terrain space
			var plane = new Plane();
			if ( startY%2 != 0 )
			{
				//odd row
				var secondTri = ( ( 1.0f - yParam ) > xParam );
				if ( secondTri )
				{
					plane.Redefine( v0, v1, v3 );
				}
				else
				{
					plane.Redefine( v1, v2, v3 );
				}
			}
			else
			{
				//even row
				var secondtri = ( yParam > xParam );
				if ( secondtri )
				{
					plane.Redefine( v0, v2, v3 );
				}
				else
				{
					plane.Redefine( v0, v1, v2 );
				}
			}

			//solve plane quation for z
			return ( -plane.Normal.x*x - plane.Normal.y*y - plane.D )/plane.Normal.z;
		}