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 ); }
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); }
// ------------------------------------ // ------------------------------------ /// <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> 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); }
/// <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; }
/// <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); }
/// <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 ); }
/// <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); }