예제 #1
0
		public void Define( Array controlPointArray, VertexDeclaration declaration, int width, int height,
		                    int uMaxSubdivisionLevel, int vMaxSubdivisionLevel, VisibleSide visibleSide, BufferUsage vbUsage,
		                    BufferUsage ibUsage, bool vbUseShadow, bool ibUseShadow )
		{
			VertexBufferUsage = vbUsage;
			UseVertexShadowBuffer = vbUseShadow;
			IndexBufferUsage = ibUsage;
			UseIndexShadowBuffer = ibUseShadow;

			// Init patch builder
			// define the surface
			// NB clone the declaration to make it independent
			this.vertexDeclaration = (VertexDeclaration)declaration.Clone();
			this.patchSurface.DefineSurface( controlPointArray, this.vertexDeclaration, width, height, PatchSurfaceType.Bezier,
			                                 uMaxSubdivisionLevel, vMaxSubdivisionLevel, visibleSide );
		}
예제 #2
0
파일: PatchMesh.cs 프로젝트: axiom3d/axiom
        public void Define(Array controlPointArray, VertexDeclaration declaration, int width, int height,
                           int uMaxSubdivisionLevel, int vMaxSubdivisionLevel, VisibleSide visibleSide, BufferUsage vbUsage,
                           BufferUsage ibUsage, bool vbUseShadow, bool ibUseShadow)
        {
            VertexBufferUsage     = vbUsage;
            UseVertexShadowBuffer = vbUseShadow;
            IndexBufferUsage      = ibUsage;
            UseIndexShadowBuffer  = ibUseShadow;

            // Init patch builder
            // define the surface
            // NB clone the declaration to make it independent
            this.vertexDeclaration = (VertexDeclaration)declaration.Clone();
            this.patchSurface.DefineSurface(controlPointArray, this.vertexDeclaration, width, height, PatchSurfaceType.Bezier,
                                            uMaxSubdivisionLevel, vMaxSubdivisionLevel, visibleSide);
        }
예제 #3
0
        // ------------------------------------
        // ------------------------------------
        /// <summary>
        ///     Creates a new PatchMesh.
        /// </summary>
        /// <remarks>
        ///     As defined in <see cref="MeshManager.CreateBezierPatch" />.
        /// </remarks>
        public PatchMesh(string name, System.Array controlPointBuffer, VertexDeclaration declaration,
            int width, int height, int uMaxSubdivisionLevel, int vMaxSubdivisionLevel, VisibleSide visibleSide,
            BufferUsage vbUsage, BufferUsage ibUsage, bool vbUseShadow, bool ibUseShadow)
            : base(name)
        {
            vertexBufferUsage = vbUsage;
            useVertexShadowBuffer = vbUseShadow;
            indexBufferUsage = ibUsage;
            useIndexShadowBuffer = ibUseShadow;

            // Init patch builder
            // define the surface
            // NB clone the declaration to make it independent
            vertexDeclaration = (VertexDeclaration)declaration.Clone();
            patchSurface.DefineSurface(controlPointBuffer, vertexDeclaration, width, height,
                PatchSurfaceType.Bezier, uMaxSubdivisionLevel, vMaxSubdivisionLevel, visibleSide);
        }
예제 #4
0
		/// <summary>
		///     Creates a Bezier patch based on an array of control vertices.
		/// </summary>
		public PatchMesh CreateBezierPatch( string name, string group, Array controlPointBuffer, VertexDeclaration declaration,
			int width, int height, int uMaxSubdivisionLevel, int vMaxSubdivisionLevel, VisibleSide visibleSide,
			BufferUsage vbUsage, BufferUsage ibUsage, bool vbUseShadow, bool ibUseShadow )
		{
			if ( width < 3 || height < 3 )
			{
				throw new Exception( "Bezier patch requires at least 3x3 control points." );
			}
			PatchMesh mesh = (PatchMesh)this[ name ];

			if ( mesh != null )
			{
				throw new AxiomException( "A mesh with the name {0} already exists!", name );
			}

			mesh = new PatchMesh( this, name, nextHandle, group );

			mesh.Define( controlPointBuffer, declaration, width, height, uMaxSubdivisionLevel, vMaxSubdivisionLevel, visibleSide, vbUsage, ibUsage, vbUseShadow, ibUseShadow );

			mesh.Load();

			_add( mesh );

			return mesh;
		}
        /// <summary>
        ///     Sets up the surface by defining it's control points, type and initial subdivision level.
        /// </summary>
        /// <remarks>
        ///     This method initialises the surface by passing it a set of control points. The type of curves to be used
        ///     are also defined here, although the only supported option currently is a bezier patch. You can also
        ///     specify a global subdivision level here if you like, although it is recommended that the parameter
        ///     is left as AUTO_LEVEL, which means the system decides how much subdivision is required (based on the
        ///     curvature of the surface).
        /// </remarks>
        /// <param name="controlPoints">
        ///     A pointer to a buffer containing the vertex data which defines control points 
        ///     of the curves rather than actual vertices. Note that you are expected to provide not
        ///     just position information, but potentially normals and texture coordinates too. The
        ///     format of the buffer is defined in the VertexDeclaration parameter.
        /// </param>
        /// <param name="decl">
        ///     VertexDeclaration describing the contents of the buffer. 
        ///     Note this declaration must _only_ draw on buffer source 0!
        /// </param>
        /// <param name="width">Specifies the width of the patch in control points.</param>
        /// <param name="height">Specifies the height of the patch in control points.</param>
        /// <param name="type">The type of surface.</param>
        /// <param name="uMaxSubdivisionLevel">
        ///     If you want to manually set the top level of subdivision, 
        ///     do it here, otherwise let the system decide.
        /// </param>
        /// <param name="vMaxSubdivisionLevel">
        ///     If you want to manually set the top level of subdivision, 
        ///     do it here, otherwise let the system decide.
        /// </param>
        /// <param name="side">Determines which side of the patch (or both) triangles are generated for.</param>
        public unsafe void DefineSurface(System.Array controlPointBuffer, VertexDeclaration declaration, int width, int height, 
            PatchSurfaceType type, int uMaxSubdivisionLevel, int vMaxSubdivisionLevel, VisibleSide visibleSide)
        {
            if (height == 0 || width == 0) {
                return; // Do nothing - garbage
            }

            this.type = type;
            this.controlWidth = width;
            this.controlHeight = height;
            this.controlCount = width * height;
            this.controlPointBuffer = controlPointBuffer;
            this.declaration = declaration;

            // Copy positions into Vector3 vector
            controlPoints.Clear();
            VertexElement elem = declaration.FindElementBySemantic(VertexElementSemantic.Position);
            int vertSize = declaration.GetVertexSize(0);
            byte *pVert = (byte*)Marshal.UnsafeAddrOfPinnedArrayElement(controlPointBuffer, 0);
            float* pReal = null;

            for (int i = 0; i < controlCount; i++) {
                pReal = (float*)(pVert + elem.Offset);
                controlPoints.Add(new Vector3(pReal[0], pReal[1], pReal[2]));
                pVert += vertSize;
            }

            this.side = visibleSide;

            // Determine max level
            // Initialise to 100% detail
            subdivisionFactor = 1.0f;

            if (uMaxSubdivisionLevel == AUTO_LEVEL) {
                uLevel = maxULevel = GetAutoULevel();
            }
            else {
                uLevel = maxULevel = uMaxSubdivisionLevel;
            }

            if (vMaxSubdivisionLevel == AUTO_LEVEL) {
                vLevel = maxVLevel = GetAutoVLevel();
            }
            else {
                vLevel = maxVLevel = vMaxSubdivisionLevel;
            }

            // Derive mesh width / height
            meshWidth  = (LevelWidth(maxULevel) - 1) * ((controlWidth-1) / 2) + 1;
            meshHeight = (LevelWidth(maxVLevel) - 1) * ((controlHeight-1) / 2) + 1;

            // Calculate number of required vertices / indexes at max resolution
            requiredVertexCount = meshWidth * meshHeight;
            int iterations = (side == VisibleSide.Both)? 2 : 1;
            requiredIndexCount = (meshWidth-1) * (meshHeight - 1) * 2 * iterations * 3;

            // Calculate bounds based on control points
            Vector3 min = Vector3.Zero;
            Vector3 max = Vector3.Zero;
            float maxSqRadius = 0.0f;
            bool first = true;

            for(int i = 0; i < controlPoints.Count; i++) {
                Vector3 vec = controlPoints[i];
                if (first) {
                    min = max = vec;
                    maxSqRadius = vec.LengthSquared;
                    first = false;
                }
                else {
                    min.Floor(vec);
                    max.Ceil(vec);
                    maxSqRadius = MathUtil.Max(vec.LengthSquared, maxSqRadius);
                }
            }

            // set the bounds of the patch
            aabb.SetExtents(min, max);
            boundingSphereRadius = MathUtil.Sqrt(maxSqRadius);
        }
예제 #6
0
        // ------------------------------------

        // ------------------------------------
        /// <summary>
        ///     Creates a new PatchMesh.
        /// </summary>
        /// <remarks>
        ///     As defined in <see cref="MeshManager.CreateBezierPatch" />.
        /// </remarks>
        public PatchMesh(string name, System.Array controlPointBuffer, VertexDeclaration declaration,
                         int width, int height, int uMaxSubdivisionLevel, int vMaxSubdivisionLevel, VisibleSide visibleSide,
                         BufferUsage vbUsage, BufferUsage ibUsage, bool vbUseShadow, bool ibUseShadow) : base(name)
        {
            vertexBufferUsage     = vbUsage;
            useVertexShadowBuffer = vbUseShadow;
            indexBufferUsage      = ibUsage;
            useIndexShadowBuffer  = ibUseShadow;

            // Init patch builder
            // define the surface
            // NB clone the declaration to make it independent
            vertexDeclaration = (VertexDeclaration)declaration.Clone();
            patchSurface.DefineSurface(controlPointBuffer, vertexDeclaration, width, height,
                                       PatchSurfaceType.Bezier, uMaxSubdivisionLevel, vMaxSubdivisionLevel, visibleSide);
        }
        /// <summary>
        ///     Creates a Bezier patch based on an array of control vertices.
        /// </summary>
        /// <param name="name"></param>
        /// <param name="controlPointBuffer"></param>
        /// <param name="declaration"></param>
        /// <param name="width"></param>
        /// <param name="height"></param>
        /// <param name="uMaxSubdivisionLevel"></param>
        /// <param name="vMaxSubdivisionLevel"></param>
        /// <param name="visibleSide"></param>
        /// <param name="vbUsage"></param>
        /// <param name="ibUsage"></param>
        /// <param name="vbUseShadow"></param>
        /// <param name="ibUseShadow"></param>
        /// <returns></returns>
        public PatchMesh CreateBezierPatch(string name, System.Array controlPointBuffer, VertexDeclaration declaration,
            int width, int height, int uMaxSubdivisionLevel, int vMaxSubdivisionLevel, VisibleSide visibleSide,
            BufferUsage vbUsage, BufferUsage ibUsage, bool vbUseShadow, bool ibUseShadow)
        {
            PatchMesh mesh = (PatchMesh)GetByName(name);

            if(mesh != null) {
                throw new AxiomException("A mesh with the name {0} already exists!", name);
            }

            mesh = new PatchMesh(name, controlPointBuffer, declaration, width, height,
                uMaxSubdivisionLevel, vMaxSubdivisionLevel, visibleSide, vbUsage, ibUsage, vbUseShadow, ibUseShadow);

            mesh.IsManuallyDefined = true;

            base.Load(mesh, 0);

            return mesh;
        }
예제 #8
0
        /// <summary>
        ///     Sets up the surface by defining it's control points, type and initial subdivision level.
        /// </summary>
        /// <remarks>
        ///     This method initialises the surface by passing it a set of control points. The type of curves to be used
        ///     are also defined here, although the only supported option currently is a bezier patch. You can also
        ///     specify a global subdivision level here if you like, although it is recommended that the parameter
        ///     is left as AUTO_LEVEL, which means the system decides how much subdivision is required (based on the
        ///     curvature of the surface).
        /// </remarks>
        /// <param name="controlPointArray">
        ///     An array containing the vertex data which define control points of the curves
        ///     rather than actual vertices. Note that you are expected to provide not
        ///     just position information, but potentially normals and texture coordinates too.
        ///     The array is internally treated as a contiguous memory buffer without any gaps between the elements.
        ///     The format of the buffer is defined in the VertexDeclaration parameter.
        /// </param>
        /// <param name="declaration">
        ///     VertexDeclaration describing the contents of the buffer.
        ///     Note this declaration must _only_ draw on buffer source 0!
        /// </param>
        /// <param name="width">Specifies the width of the patch in control points.</param>
        /// <param name="height">Specifies the height of the patch in control points.</param>
        /// <param name="type">The type of surface.</param>
        /// <param name="uMaxSubdivisionLevel">
        ///     If you want to manually set the top level of subdivision,
        ///     do it here, otherwise let the system decide.
        /// </param>
        /// <param name="vMaxSubdivisionLevel">
        ///     If you want to manually set the top level of subdivision,
        ///     do it here, otherwise let the system decide.
        /// </param>
        /// <param name="visibleSide">Determines which side of the patch (or both) triangles are generated for.</param>
        public void DefineSurface(Array controlPointArray, VertexDeclaration declaration, int width, int height,
                                  PatchSurfaceType type, int uMaxSubdivisionLevel, int vMaxSubdivisionLevel,
                                  VisibleSide visibleSide)
        {
            if (height == 0 || width == 0)
            {
                return;                 // Do nothing - garbage
            }

            //pin the input to have a pointer
            Memory.UnpinObject(controlPointArray);
            this.controlPointBuffer = Memory.PinObject(controlPointArray);

            this.type          = type;
            this.controlWidth  = width;
            this.controlHeight = height;
            this.controlCount  = width * height;
            this.declaration   = declaration;

            // Copy positions into Vector3 vector
            this.controlPoints.Clear();
            var elem     = declaration.FindElementBySemantic(VertexElementSemantic.Position);
            var vertSize = declaration.GetVertexSize(0);

#if !AXIOM_SAFE_ONLY
            unsafe
#endif
            {
                var pVert = this.controlPointBuffer;
                for (var i = 0; i < this.controlCount; i++)
                {
                    var pReal = (pVert + ((i * vertSize) + elem.Offset)).ToFloatPointer();
                    this.controlPoints.Add(new Vector3(pReal[0], pReal[1], pReal[2]));
                }
            }
            this.side = visibleSide;

            // Determine max level
            // Initialize to 100% detail
            this.subdivisionFactor = 1.0f;

            if (uMaxSubdivisionLevel == AUTO_LEVEL)
            {
                this.uLevel = this.maxULevel = GetAutoULevel();
            }
            else
            {
                this.uLevel = this.maxULevel = uMaxSubdivisionLevel;
            }

            if (vMaxSubdivisionLevel == AUTO_LEVEL)
            {
                this.vLevel = this.maxVLevel = GetAutoVLevel();
            }
            else
            {
                this.vLevel = this.maxVLevel = vMaxSubdivisionLevel;
            }

            // Derive mesh width / height
            this.meshWidth  = (LevelWidth(this.maxULevel) - 1) * ((this.controlWidth - 1) / 2) + 1;
            this.meshHeight = (LevelWidth(this.maxVLevel) - 1) * ((this.controlHeight - 1) / 2) + 1;

            // Calculate number of required vertices / indexes at max resolution
            this.requiredVertexCount = this.meshWidth * this.meshHeight;
            var iterations = (this.side == VisibleSide.Both) ? 2 : 1;
            this.requiredIndexCount = (this.meshWidth - 1) * (this.meshHeight - 1) * 2 * iterations * 3;

            // Calculate bounds based on control points
            var min         = Vector3.Zero;
            var max         = Vector3.Zero;
            var maxSqRadius = 0.0f;
            var first       = true;

            for (var i = 0; i < this.controlPoints.Count; i++)
            {
                var vec = this.controlPoints[i];
                if (first)
                {
                    min         = max = vec;
                    maxSqRadius = vec.LengthSquared;
                    first       = false;
                }
                else
                {
                    min.Floor(vec);
                    max.Ceil(vec);
                    maxSqRadius = Utility.Max(vec.LengthSquared, maxSqRadius);
                }
            }

            // set the bounds of the patch
            this.aabb.SetExtents(min, max);
            this.boundingSphereRadius = Utility.Sqrt(maxSqRadius);
        }
예제 #9
0
		/// <summary>
		///     Sets up the surface by defining it's control points, type and initial subdivision level.
		/// </summary>
		/// <remarks>
		///     This method initialises the surface by passing it a set of control points. The type of curves to be used
		///     are also defined here, although the only supported option currently is a bezier patch. You can also
		///     specify a global subdivision level here if you like, although it is recommended that the parameter
		///     is left as AUTO_LEVEL, which means the system decides how much subdivision is required (based on the
		///     curvature of the surface).
		/// </remarks>
		/// <param name="controlPointArray">
		///     An array containing the vertex data which define control points of the curves
		///     rather than actual vertices. Note that you are expected to provide not
		///     just position information, but potentially normals and texture coordinates too.
		///     The array is internally treated as a contiguous memory buffer without any gaps between the elements.
		///     The format of the buffer is defined in the VertexDeclaration parameter.
		/// </param>
		/// <param name="declaration">
		///     VertexDeclaration describing the contents of the buffer.
		///     Note this declaration must _only_ draw on buffer source 0!
		/// </param>
		/// <param name="width">Specifies the width of the patch in control points.</param>
		/// <param name="height">Specifies the height of the patch in control points.</param>
		/// <param name="type">The type of surface.</param>
		/// <param name="uMaxSubdivisionLevel">
		///     If you want to manually set the top level of subdivision,
		///     do it here, otherwise let the system decide.
		/// </param>
		/// <param name="vMaxSubdivisionLevel">
		///     If you want to manually set the top level of subdivision,
		///     do it here, otherwise let the system decide.
		/// </param>
		/// <param name="visibleSide">Determines which side of the patch (or both) triangles are generated for.</param>
		public void DefineSurface( Array controlPointArray, VertexDeclaration declaration, int width, int height,
		                           PatchSurfaceType type, int uMaxSubdivisionLevel, int vMaxSubdivisionLevel,
		                           VisibleSide visibleSide )
		{
			if ( height == 0 || width == 0 )
			{
				return; // Do nothing - garbage
			}

			//pin the input to have a pointer
			Memory.UnpinObject( controlPointArray );
			this.controlPointBuffer = Memory.PinObject( controlPointArray );

			this.type = type;
			this.controlWidth = width;
			this.controlHeight = height;
			this.controlCount = width*height;
			this.declaration = declaration;

			// Copy positions into Vector3 vector
			this.controlPoints.Clear();
			var elem = declaration.FindElementBySemantic( VertexElementSemantic.Position );
			var vertSize = declaration.GetVertexSize( 0 );

#if !AXIOM_SAFE_ONLY
			unsafe
#endif
			{
				var pVert = this.controlPointBuffer;
				for ( var i = 0; i < this.controlCount; i++ )
				{
					var pReal = ( pVert + ( ( i*vertSize ) + elem.Offset ) ).ToFloatPointer();
					this.controlPoints.Add( new Vector3( pReal[ 0 ], pReal[ 1 ], pReal[ 2 ] ) );
				}
			}
			this.side = visibleSide;

			// Determine max level
			// Initialize to 100% detail
			this.subdivisionFactor = 1.0f;

			if ( uMaxSubdivisionLevel == AUTO_LEVEL )
			{
				this.uLevel = this.maxULevel = GetAutoULevel();
			}
			else
			{
				this.uLevel = this.maxULevel = uMaxSubdivisionLevel;
			}

			if ( vMaxSubdivisionLevel == AUTO_LEVEL )
			{
				this.vLevel = this.maxVLevel = GetAutoVLevel();
			}
			else
			{
				this.vLevel = this.maxVLevel = vMaxSubdivisionLevel;
			}

			// Derive mesh width / height
			this.meshWidth = ( LevelWidth( this.maxULevel ) - 1 )*( ( this.controlWidth - 1 )/2 ) + 1;
			this.meshHeight = ( LevelWidth( this.maxVLevel ) - 1 )*( ( this.controlHeight - 1 )/2 ) + 1;

			// Calculate number of required vertices / indexes at max resolution
			this.requiredVertexCount = this.meshWidth*this.meshHeight;
			var iterations = ( this.side == VisibleSide.Both ) ? 2 : 1;
			this.requiredIndexCount = ( this.meshWidth - 1 )*( this.meshHeight - 1 )*2*iterations*3;

			// Calculate bounds based on control points
			var min = Vector3.Zero;
			var max = Vector3.Zero;
			var maxSqRadius = 0.0f;
			var first = true;

			for ( var i = 0; i < this.controlPoints.Count; i++ )
			{
				var vec = this.controlPoints[ i ];
				if ( first )
				{
					min = max = vec;
					maxSqRadius = vec.LengthSquared;
					first = false;
				}
				else
				{
					min.Floor( vec );
					max.Ceil( vec );
					maxSqRadius = Utility.Max( vec.LengthSquared, maxSqRadius );
				}
			}

			// set the bounds of the patch
			this.aabb.SetExtents( min, max );
			this.boundingSphereRadius = Utility.Sqrt( maxSqRadius );
		}
예제 #10
0
        /// <summary>
        ///     Sets up the surface by defining it's control points, type and initial subdivision level.
        /// </summary>
        /// <remarks>
        ///     This method initialises the surface by passing it a set of control points. The type of curves to be used
        ///     are also defined here, although the only supported option currently is a bezier patch. You can also
        ///     specify a global subdivision level here if you like, although it is recommended that the parameter
        ///     is left as AUTO_LEVEL, which means the system decides how much subdivision is required (based on the
        ///     curvature of the surface).
        /// </remarks>
        /// <param name="controlPoints">
        ///     A pointer to a buffer containing the vertex data which defines control points
        ///     of the curves rather than actual vertices. Note that you are expected to provide not
        ///     just position information, but potentially normals and texture coordinates too. The
        ///     format of the buffer is defined in the VertexDeclaration parameter.
        /// </param>
        /// <param name="decl">
        ///     VertexDeclaration describing the contents of the buffer.
        ///     Note this declaration must _only_ draw on buffer source 0!
        /// </param>
        /// <param name="width">Specifies the width of the patch in control points.</param>
        /// <param name="height">Specifies the height of the patch in control points.</param>
        /// <param name="type">The type of surface.</param>
        /// <param name="uMaxSubdivisionLevel">
        ///     If you want to manually set the top level of subdivision,
        ///     do it here, otherwise let the system decide.
        /// </param>
        /// <param name="vMaxSubdivisionLevel">
        ///     If you want to manually set the top level of subdivision,
        ///     do it here, otherwise let the system decide.
        /// </param>
        /// <param name="side">Determines which side of the patch (or both) triangles are generated for.</param>
        public unsafe void DefineSurface(System.Array controlPointBuffer, VertexDeclaration declaration, int width, int height,
                                         PatchSurfaceType type, int uMaxSubdivisionLevel, int vMaxSubdivisionLevel, VisibleSide visibleSide)
        {
            if (height == 0 || width == 0)
            {
                return; // Do nothing - garbage
            }

            this.type               = type;
            this.controlWidth       = width;
            this.controlHeight      = height;
            this.controlCount       = width * height;
            this.controlPointBuffer = controlPointBuffer;
            this.declaration        = declaration;

            // Copy positions into Vector3 vector
            controlPoints.Clear();
            VertexElement elem     = declaration.FindElementBySemantic(VertexElementSemantic.Position);
            int           vertSize = declaration.GetVertexSize(0);
            byte *        pVert    = (byte *)Marshal.UnsafeAddrOfPinnedArrayElement(controlPointBuffer, 0);
            float *       pReal    = null;

            for (int i = 0; i < controlCount; i++)
            {
                pReal = (float *)(pVert + elem.Offset);
                controlPoints.Add(new Vector3(pReal[0], pReal[1], pReal[2]));
                pVert += vertSize;
            }

            this.side = visibleSide;

            // Determine max level
            // Initialise to 100% detail
            subdivisionFactor = 1.0f;

            if (uMaxSubdivisionLevel == AUTO_LEVEL)
            {
                uLevel = maxULevel = GetAutoULevel();
            }
            else
            {
                uLevel = maxULevel = uMaxSubdivisionLevel;
            }

            if (vMaxSubdivisionLevel == AUTO_LEVEL)
            {
                vLevel = maxVLevel = GetAutoVLevel();
            }
            else
            {
                vLevel = maxVLevel = vMaxSubdivisionLevel;
            }

            // Derive mesh width / height
            meshWidth  = (LevelWidth(maxULevel) - 1) * ((controlWidth - 1) / 2) + 1;
            meshHeight = (LevelWidth(maxVLevel) - 1) * ((controlHeight - 1) / 2) + 1;

            // Calculate number of required vertices / indexes at max resolution
            requiredVertexCount = meshWidth * meshHeight;
            int iterations = (side == VisibleSide.Both)? 2 : 1;

            requiredIndexCount = (meshWidth - 1) * (meshHeight - 1) * 2 * iterations * 3;

            // Calculate bounds based on control points
            Vector3 min         = Vector3.Zero;
            Vector3 max         = Vector3.Zero;
            float   maxSqRadius = 0.0f;
            bool    first       = true;

            for (int i = 0; i < controlPoints.Count; i++)
            {
                Vector3 vec = controlPoints[i];
                if (first)
                {
                    min         = max = vec;
                    maxSqRadius = vec.LengthSquared;
                    first       = false;
                }
                else
                {
                    min.Floor(vec);
                    max.Ceil(vec);
                    maxSqRadius = MathUtil.Max(vec.LengthSquared, maxSqRadius);
                }
            }

            // set the bounds of the patch
            aabb.SetExtents(min, max);
            boundingSphereRadius = MathUtil.Sqrt(maxSqRadius);
        }
        /// <summary>
        ///     Creates a Bezier patch based on an array of control vertices.
        /// </summary>
        /// <param name="name"></param>
        /// <param name="controlPointBuffer"></param>
        /// <param name="declaration"></param>
        /// <param name="width"></param>
        /// <param name="height"></param>
        /// <param name="uMaxSubdivisionLevel"></param>
        /// <param name="vMaxSubdivisionLevel"></param>
        /// <param name="visibleSide"></param>
        /// <param name="vbUsage"></param>
        /// <param name="ibUsage"></param>
        /// <param name="vbUseShadow"></param>
        /// <param name="ibUseShadow"></param>
        /// <returns></returns>
        public PatchMesh CreateBezierPatch(string name, System.Array controlPointBuffer, VertexDeclaration declaration,
                                           int width, int height, int uMaxSubdivisionLevel, int vMaxSubdivisionLevel, VisibleSide visibleSide,
                                           BufferUsage vbUsage, BufferUsage ibUsage, bool vbUseShadow, bool ibUseShadow)
        {
            PatchMesh mesh = (PatchMesh)GetByName(name);

            if (mesh != null)
            {
                throw new AxiomException("A mesh with the name {0} already exists!", name);
            }

            mesh = new PatchMesh(name, controlPointBuffer, declaration, width, height,
                                 uMaxSubdivisionLevel, vMaxSubdivisionLevel, visibleSide, vbUsage, ibUsage, vbUseShadow, ibUseShadow);

            mesh.IsManuallyDefined = true;

            base.Load(mesh, 0);

            return(mesh);
        }