Axiom.Core.Frustum._updateFrustum C# (CSharp) Метод

_updateFrustum() защищенный Метод

protected _updateFrustum ( ) : void
Результат void
		protected virtual void _updateFrustum()
		{
			Real vpTop, vpRight, vpBottom, vpLeft;

			CalculateProjectionParameters( out vpLeft, out vpRight, out vpBottom, out vpTop );

			if ( !_customProjectionMatrix )
			{
				// The code below will dealing with general projection
				// parameters, similar glFrustum and glOrtho.
				// Doesn't optimise manually except division operator, so the
				// code more self-explaining.

				float inv_w = 1.0f / ( vpRight - vpLeft );
				float inv_h = 1.0f / ( vpTop - vpBottom );
				float inv_d = 1.0f / ( _farDistance - _nearDistance );

				// Recalc if frustum params changed
				if ( _projectionType == Projection.Perspective )
				{
					// Calc matrix elements
					float A = 2.0f * _nearDistance * inv_w;
					float B = 2.0f * _nearDistance * inv_h;
					float C = ( vpRight + vpLeft ) * inv_w;
					float D = ( vpTop + vpBottom ) * inv_h;
					float q, qn;
					if ( _farDistance == 0.0f )
					{
						// Infinite far plane
						q = Frustum.InfiniteFarPlaneAdjust - 1.0f;
						qn = _nearDistance * ( Frustum.InfiniteFarPlaneAdjust - 2.0f );
					}
					else
					{
						q = -( _farDistance + _nearDistance ) * inv_d;
						qn = -2.0f * ( _farDistance * _nearDistance ) * inv_d;
					}

					// NB: This creates 'uniform' perspective projection matrix,
					// which depth range [-1,1], right-handed rules
					//
					// [ A   0   C   0  ]
					// [ 0   B   D   0  ]
					// [ 0   0   q   qn ]
					// [ 0   0   -1  0  ]
					//
					// A = 2 * near / (right - left)
					// B = 2 * near / (top - bottom)
					// C = (right + left) / (right - left)
					// D = (top + bottom) / (top - bottom)
					// q = - (far + near) / (far - near)
					// qn = - 2 * (far * near) / (far - near)

					_projectionMatrix = Matrix4.Zero;
					_projectionMatrix.m00 = A;
					_projectionMatrix.m02 = C;
					_projectionMatrix.m11 = B;
					_projectionMatrix.m12 = D;
					_projectionMatrix.m22 = q;
					_projectionMatrix.m23 = qn;
					_projectionMatrix.m32 = -1.0f;

					if ( useObliqueDepthProjection )
					{
						// Translate the plane into view space

						// Don't use getViewMatrix here, incase overrided by
						// camera and return a cull frustum view matrix
						UpdateView();

						Plane plane = _viewMatrix * obliqueProjPlane;

						// Thanks to Eric Lenyel for posting this calculation
						// at www.terathon.com

						// Calculate the clip-space corner point opposite the
						// clipping plane
						// as (sgn(clipPlane.x), sgn(clipPlane.y), 1, 1) and
						// transform it into camera space by multiplying it
						// by the inverse of the projection matrix

						/* generalised version
						Vector4 q = matrix.inverse() *
						Vector4(Math::Sign(plane.normal.x),
						Math::Sign(plane.normal.y), 1.0f, 1.0f);
						 */
						Vector4 q1 = new Vector4();
						q1.x = ( System.Math.Sign( plane.Normal.x ) + _projectionMatrix.m02 ) / _projectionMatrix.m00;
						q1.y = ( System.Math.Sign( plane.Normal.y ) + _projectionMatrix.m12 ) / _projectionMatrix.m11;
						q1.z = -1.0f;
						q1.w = ( 1.0f + _projectionMatrix.m22 ) / _projectionMatrix.m23;

						// Calculate the scaled plane vector
						Vector4 clipPlane4d = new Vector4( plane.Normal.x, plane.Normal.y, plane.Normal.z, plane.D );
						Vector4 c = clipPlane4d * ( 2.0f / ( clipPlane4d.Dot( q1 ) ) );

						// Replace the third row of the projection matrix
						_projectionMatrix.m20 = c.x;
						_projectionMatrix.m21 = c.y;
						_projectionMatrix.m22 = c.z + 1.0f;
						_projectionMatrix.m23 = c.w;
					}
				} // perspective
				else if ( _projectionType == Projection.Orthographic )
				{
					float A = 2.0f * inv_w;
					float B = 2.0f * inv_h;
					float C = -( vpRight + vpLeft ) * inv_w;
					float D = -( vpTop + vpBottom ) * inv_h;
					float q, qn;
					if ( _farDistance == 0.0f )
					{
						// Can not do infinite far plane here, avoid divided zero only
						q = -Frustum.InfiniteFarPlaneAdjust / _nearDistance;
						qn = -Frustum.InfiniteFarPlaneAdjust - 1.0f;
					}
					else
					{
						q = -2.0f * inv_d;
						qn = -( _farDistance + _nearDistance ) * inv_d;
					}

					// NB: This creates 'uniform' orthographic projection matrix,
					// which depth range [-1,1], right-handed rules
					//
					// [ A   0   0   C  ]
					// [ 0   B   0   D  ]
					// [ 0   0   q   qn ]
					// [ 0   0   0   1  ]
					//
					// A = 2 * / (right - left)
					// B = 2 * / (top - bottom)
					// C = - (right + left) / (right - left)
					// D = - (top + bottom) / (top - bottom)
					// q = - 2 / (far - near)
					// qn = - (far + near) / (far - near)

					_projectionMatrix = Matrix4.Zero;
					_projectionMatrix.m00 = A;
					_projectionMatrix.m03 = C;
					_projectionMatrix.m11 = B;
					_projectionMatrix.m13 = D;
					_projectionMatrix.m22 = q;
					_projectionMatrix.m23 = qn;
					_projectionMatrix.m33 = 1.0f;
				} // ortho
			} // if !_customProjectionMatrix

			// grab a reference to the current render system
			RenderSystem renderSystem = Root.Instance.RenderSystem;
			// API specific
            renderSystem.ConvertProjectionMatrix(_projectionMatrix, out _projectionMatrixRS);
			// API specific for Gpu Programs
            renderSystem.ConvertProjectionMatrix(_projectionMatrix, out _projectionMatrixRSDepth, true);

			// Calculate bounding box (local)
			// Box is from 0, down -Z, max dimensions as determined from far plane
			// If infinite view frustum just pick a far value
			float farDist = ( _farDistance == 0.0f ) ? 100000.0f : _farDistance;

			// Near plane bounds
			Vector3 min = new Vector3( vpLeft, vpBottom, -farDist );
			Vector3 max = new Vector3( vpRight, vpTop, 0 );

			if ( _customProjectionMatrix )
			{
				// Some custom projection matrices can have unusual inverted settings
				// So make sure the AABB is the right way around to start with
				Vector3 tmp = min;
				min.Floor( max );
				max.Ceil( tmp );
			}

			float radio = 1.0f;
			if ( _projectionType == Projection.Perspective )
			{
				// Merge with far plane bounds
				radio = _farDistance / _nearDistance;
				min.Floor( new Vector3( vpLeft * radio, vpBottom * radio, -_farDistance ) );
				max.Ceil( new Vector3( vpRight * radio, vpTop * radio, 0 ) );
			}

			_boundingBox.SetExtents( min, max );

			_recalculateFrustum = false;

			// Signal to update frustum clipping planes
			_recalculateFrustumPlanes = true;
		}