예제 #1
0
        // TODO: Render with effect

        /// <summary>Compute a bounding sphere for this mesh</summary>
        public float ComputeBoundingSphere(out Vector3 center)
        {
            if (systemMemoryMesh == null)
            {
                throw new InvalidOperationException("There is no system memory mesh.  Nothing to do here.");
            }

            // Get the object declaration
            int strideSize = VertexInformation.GetFormatSize(systemMemoryMesh.VertexFormat);

            // Lock the vertex buffer
            GraphicsStream data = null;

            try
            {
                data = systemMemoryMesh.LockVertexBuffer(LockFlags.ReadOnly);
                // Now compute the bounding sphere
                return(Geometry.ComputeBoundingSphere(data, systemMemoryMesh.NumberVertices,
                                                      systemMemoryMesh.VertexFormat, out center));
            }
            finally
            {
                // Make sure to unlock the vertex buffer
                if (data != null)
                {
                    systemMemoryMesh.UnlockVertexBuffer();
                }
            }
        }
예제 #2
0
        /// <summary>
        /// Called once per frame, the call is the entry point for 3d rendering. This
        /// function sets up render states, clears the viewport, and renders the scene.
        /// </summary>
        protected override void Render()
        {
            //Clear the backbuffer to a black color
            device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.Black, 1.0f, 0);
            //Begin the scene
            device.BeginScene();

            device.VertexFormat = CustomVertex.PositionNormalColored.Format;

            // set the vertexbuffer stream source
            device.SetStreamSource(0, vertexBuffer, 0, VertexInformation.GetFormatSize(CustomVertex.PositionNormalColored.Format));
            // set fill mode
            device.RenderState.FillMode = FillMode.Solid;
            // set the indices
            device.Indices = indexBuffer;
            //use the indices buffer
            device.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, bufferSize * bufferSize, 0, vert_size / 3);

            // Output statistics
            drawingFont.DrawText(2, 1, System.Drawing.Color.Yellow, frameStats);
            drawingFont.DrawText(2, 20, System.Drawing.Color.Yellow, deviceStats);
            drawingFont.DrawText(2, 40, System.Drawing.Color.White, "Hit 'F' to generate new fractal.");

            device.EndScene();
        }
예제 #3
0
파일: Renderer.cs 프로젝트: vsugrob/Q3Bot
        private void DrawEnvironment()
        {
            /*if ( RteEnabled ) {
             *      if ( envPolysIndices [0] == null ) {
             *              for ( int i = 0 ; i < 6 ; i++ )
             *                      CreatePoly ( out envPolysIndices [0], out envPolysVertices [0] );
             *      }
             *
             *      lastTextureId = -1;
             *      lastLightmapId = -1;
             *      ibNeedSet = true;
             *      bezierIbNeedSet = true;
             *
             *      d3dDevice.SetTextureStageState ( 0, TextureStageStates.TextureCoordinateIndex, ( int ) TextureCoordinateIndex.PassThru );
             *      d3dDevice.SetTextureStageState ( 1, TextureStageStates.ColorOperation, ( int ) TextureOperation.Disable );
             *      d3dDevice.SetTransform ( TransformType.View , fpsCamera.ViewMatrix );
             *      d3dDevice.SetTransform ( TransformType.Projection, fpsCamera.ProjMatrix );
             *
             *      for ( int i = 0 ; i < 1 ; i++ ) {
             *              d3dDevice.SetTransform ( TransformType.World, Matrix.Translation ( fpsCamera.Position + fpsCamera.Look * 5 + fpsCamera.Right * 2 - fpsCamera.Up ) );
             *              d3dDevice.DrawIndexedPrimitives ( PrimitiveType.TriangleList, 0, 0, 4, 0, 2 );
             *      }
             * }*/

            if (RteEnabled)
            {
                using (Mesh teapot = Mesh.Sphere(d3dDevice, 2.0f, 16, 16)) {
                    lastTextureId  = -1;
                    lastLightmapId = -1;
                    d3dDevice.SetTexture(0, cubeTexture);
                    d3dDevice.SetTextureStageState(0, TextureStageStates.TextureCoordinateIndex, ( int )TextureCoordinateIndex.SphereMap);
                    d3dDevice.SetTextureStageState(0, TextureStageStates.ColorOperation, ( int )TextureOperation.SelectArg1);
                    d3dDevice.SetTextureStageState(0, TextureStageStates.ColorArgument1, ( int )TextureArgument.TextureColor);

                    /*d3dDevice.SetTextureStageState ( 0, TextureStageStates.TextureTransform, ( int ) TextureTransform.Count3 );
                     * d3dDevice.SamplerState [0].AddressU = TextureAddress.Clamp;
                     * d3dDevice.SamplerState [0].AddressV = TextureAddress.Clamp;
                     * d3dDevice.SamplerState [0].AddressW = TextureAddress.Clamp;*/
                    d3dDevice.SetTextureStageState(1, TextureStageStates.ColorOperation, ( int )TextureOperation.Disable);

                    d3dDevice.Transform.World      = Matrix.Scaling(10.0f, 10.0f, 10.0f) * Matrix.Translation(teapotPos);
                    d3dDevice.Transform.View       = fpsCamera.ViewMatrix;
                    d3dDevice.Transform.Projection = fpsCamera.ProjMatrix;

                    using (VertexBuffer vb = teapot.VertexBuffer) {
                        using (IndexBuffer ib = teapot.IndexBuffer) {
                            ibNeedSet              = true;
                            bezierIbNeedSet        = true;
                            d3dDevice.VertexFormat = teapot.VertexFormat;
                            d3dDevice.SetStreamSource(0, vb, 0, VertexInformation.GetFormatSize(teapot.VertexFormat));
                            d3dDevice.Indices = ib;
                            d3dDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, teapot.NumberVertices, 0, teapot.NumberFaces);
                            //teapot.DrawSubset ( 0 );
                        }
                    }
                }
            }
        }
예제 #4
0
    /// <summary>
    /// Renders 3D text
    /// </summary>
    public void Render3DText(string text, RenderFlags flags)
    {
        if (device == null)
        {
            throw new System.ArgumentNullException();
        }

        // Set up renderstate
        savedStateBlock.Capture();
        drawTextStateBlock.Apply();
        device.VertexFormat = CustomVertex.PositionNormalTextured.Format;
        device.PixelShader  = null;
        device.SetStreamSource(0, vertexBuffer, 0, VertexInformation.GetFormatSize(CustomVertex.PositionNormalTextured.Format));

        // Set filter states
        if ((flags & RenderFlags.Filtered) != 0)
        {
            samplerState0.MinFilter = TextureFilter.Linear;
            samplerState0.MagFilter = TextureFilter.Linear;
        }

        // Position for each text element
        float x = 0.0f;
        float y = 0.0f;

        // Center the text block at the origin
        if ((flags & RenderFlags.Centered) != 0)
        {
            System.Drawing.SizeF sz = GetTextExtent(text);
            x = -(((float)sz.Width) / 10.0f) / 2.0f;
            y = -(((float)sz.Height) / 10.0f) / 2.0f;
        }

        // Turn off culling for two-sided text
        if ((flags & RenderFlags.TwoSided) != 0)
        {
            renderState.CullMode = Cull.None;
        }

        // Adjust for character spacing
        x -= spacingPerChar / 10.0f;
        float fStartX = x;

        // Fill vertex buffer
        GraphicsStream strm         = vertexBuffer.Lock(0, 0, LockFlags.Discard);
        int            numTriangles = 0;

        foreach (char c in text)
        {
            if (c == '\n')
            {
                x  = fStartX;
                y -= (textureCoords[0, 3] - textureCoords[0, 1]) * textureHeight / 10.0f;
            }

            if ((c - 32) < 0 || (c - 32) >= 128 - 32)
            {
                continue;
            }

            float tx1 = textureCoords[c - 32, 0];
            float ty1 = textureCoords[c - 32, 1];
            float tx2 = textureCoords[c - 32, 2];
            float ty2 = textureCoords[c - 32, 3];

            float w = (tx2 - tx1) * textureWidth / (10.0f * textureScale);
            float h = (ty2 - ty1) * textureHeight / (10.0f * textureScale);

            if (c != ' ')
            {
                strm.Write(new CustomVertex.PositionNormalTextured(new Vector3(x + 0, y + 0, 0), new Vector3(0, 0, -1), tx1, ty2));
                strm.Write(new CustomVertex.PositionNormalTextured(new Vector3(x + 0, y + h, 0), new Vector3(0, 0, -1), tx1, ty1));
                strm.Write(new CustomVertex.PositionNormalTextured(new Vector3(x + w, y + 0, 0), new Vector3(0, 0, -1), tx2, ty2));
                strm.Write(new CustomVertex.PositionNormalTextured(new Vector3(x + w, y + h, 0), new Vector3(0, 0, -1), tx2, ty1));
                strm.Write(new CustomVertex.PositionNormalTextured(new Vector3(x + w, y + 0, 0), new Vector3(0, 0, -1), tx2, ty2));
                strm.Write(new CustomVertex.PositionNormalTextured(new Vector3(x + 0, y + h, 0), new Vector3(0, 0, -1), tx1, ty1));
                numTriangles += 2;

                if (numTriangles * 3 > (MaxNumfontVertices - 6))
                {
                    // Unlock, render, and relock the vertex buffer
                    vertexBuffer.Unlock();
                    device.DrawPrimitives(PrimitiveType.TriangleList, 0, numTriangles);
                    strm         = vertexBuffer.Lock(0, 0, LockFlags.Discard);
                    numTriangles = 0;
                }
            }

            x += w - (2 * spacingPerChar) / 10.0f;
        }

        // Unlock and render the vertex buffer
        vertexBuffer.Unlock();
        if (numTriangles > 0)
        {
            device.DrawPrimitives(PrimitiveType.TriangleList, 0, numTriangles);
        }

        // Restore the modified renderstates
        savedStateBlock.Apply();
    }
예제 #5
0
        /// <summary>
        /// Saves a mesh to the custom serialized format
        /// </summary>
        /// <param name="stream">The stream to which to serialize</param>
        /// <param name="mesh">The mesh to be serialized</param>
        /// <param name="materials">The materials for subparts of the mesh
        /// </param>
        /// <param name="textures">The filenames for the textures on
        /// subparts of the mesh</param>
        public static void SaveMesh(Stream stream, Mesh mesh,
                                    Material [] materials, string [] textures)
        {
            int flexibleVertexFormat;
            int numberVertices;

            byte [] vertices;
            int     numberIndices;

            byte []           indices;
            AttributeRange [] attributeRanges;
            VertexFormats     sourceVertexFormat;
            VertexFormats     sourceFormat;

            IDisposable tempMesh;

            tempMesh = null;

            try
            {
                // Managed Direct3D mobile uses different Fvf defines than
                // managed Direct3D for the desktop
                // when this code is linked against the desktop version
                // this will convert the Fvf to match MD3DM constants
                // when this code is linked against MD3DM this section will
                // not have changed anything.

                // determine the necessary Fvf
                sourceVertexFormat = mesh.VertexFormat;
                int textureCount;
                sourceFormat         = VertexFormats.Position;
                flexibleVertexFormat = 0;

                if ((sourceVertexFormat & VertexFormats.Normal) != 0)
                {
                    flexibleVertexFormat |= md3dmFvfNormal;
                    sourceFormat         |= VertexFormats.Normal;
                }

                if ((sourceVertexFormat & VertexFormats.Diffuse) != 0)
                {
                    flexibleVertexFormat |= md3dmFvfDiffuse;
                    sourceFormat         |= VertexFormats.Diffuse;
                }

                if ((sourceVertexFormat & VertexFormats.Specular) != 0)
                {
                    flexibleVertexFormat |= md3dmFvfDiffuse;
                    sourceFormat         |= VertexFormats.Specular;
                }

                // determine number of textures
                textureCount = (int)(sourceVertexFormat &
                                     VertexFormats.TextureCountMask) >>
                               (int)VertexFormats.TextureCountShift;

                //limit to 4 textures
                if (textureCount > 4)
                {
                    textureCount = 4;
                }

                // continue setting up necessary fvf
                sourceFormat |= (VertexFormats)(textureCount <<
                                                (int)VertexFormats.TextureCountShift);
                flexibleVertexFormat |=
                    (textureCount << md3dmFvfTextureCountShift);

                if (sourceFormat != sourceVertexFormat)
                {
                    mesh = mesh.Clone(mesh.Options.Value, sourceFormat,
                                      mesh.Device);
                    tempMesh = (IDisposable)mesh;
                }

                attributeRanges = mesh.GetAttributeTable();

                if (attributeRanges == null)
                {
                    throw new MeshSerializationException(
                              "No Attribute table present");
                }

                // determine number of vertices and create buffer
                numberVertices = mesh.NumberVertices;
                vertices       = new byte[numberVertices *
                                          VertexInformation.GetFormatSize(sourceFormat)];

                // copy vertices to buffer
                mesh.VertexBuffer.Lock(0, vertices.Length,
                                       LockFlags.None).Read(vertices, 0, vertices.Length);
                mesh.VertexBuffer.Unlock();

                // determine number of indices
                numberIndices = mesh.NumberFaces * 3;

                // create index data buffer
                indices = new byte[numberIndices *
                                   (mesh.Options.Use32Bit ? 4 : 2)];

                // fill index data into buffer
                mesh.IndexBuffer.Lock(0, indices.Length,
                                      LockFlags.None).Read(indices, 0, indices.Length);
                mesh.IndexBuffer.Unlock();

                // write the data out to file
                MeshLoader.SaveMeshData(stream, flexibleVertexFormat,
                                        numberVertices, vertices,
                                        numberIndices, indices, attributeRanges, materials,
                                        textures);
            }
            finally
            {
                if (tempMesh != null)
                {
                    tempMesh.Dispose();
                }
            }
        }
예제 #6
0
        /// <summary>
        /// Loads a mesh from the given stream
        /// </summary>
        /// <param name="device">A d3d mobile device which will be displaying
        /// the mesh</param>
        /// <param name="stream">The stream containing serialized mesh data
        /// </param>
        /// <param name="flags">Option flags</param>
        /// <param name="materials">Output array is filled with any needed
        /// materials</param>
        /// <param name="textures">Output array is filled with the filenames
        /// of any needed textures</param>
        /// <returns></returns>
        public static Mesh LoadMesh(Device device, Stream stream,
                                    MeshFlags flags, out Material [] materials,
                                    out string [] textures)
        {
            if (device == null)
            {
                throw new ArgumentException("Argument device was invalid");
            }
            if (stream == null)
            {
                throw new ArgumentException("Argument stream was invalid");
            }

            byte []      rgb;
            byte []      rgbIb;
            byte []      rgbVb;
            Mesh         meshRet;
            VertexBuffer vb;
            IndexBuffer  ib;

            int           fileMagicNumber;
            int           fileVersion;
            VertexFormats flexibleVertexFormat;
            int           numberVertices;
            int           numberIndices;
            int           is16BitIndices;
            int           numberMaterials;
            int           numberAttrRanges;
            int           offsetVertex;
            int           offsetIndices;
            int           offsetAttrRange;
            int           offsetMaterial;
            int           bytesMaterials;
            int           bytesIndices;


            int []            attributeTable;
            AttributeRange [] attributeRanges;

            rgb = new byte [512];

            stream.Seek(0, SeekOrigin.Begin);

            // Read header, any errors will be propagated up
            stream.Read(rgb, 0, sizeofHeader);

            // read and verify magic number
            fileMagicNumber = BitConverter.ToInt32(rgb, 0);
            if (fileMagicNumber != magicNumber)
            {
                throw new MeshSerializationException(
                          "The serialized data does not represent a mesh");
            }

            // read and verify version
            fileVersion = BitConverter.ToInt32(rgb, 4);
            if (fileVersion != versionNumber)
            {
                throw new MeshSerializationException(
                          "The format version was not recognized");
            }

            flexibleVertexFormat = (VertexFormats)
                                   BitConverter.ToInt32(rgb, 8);
            numberVertices   = BitConverter.ToInt32(rgb, 12);
            numberIndices    = BitConverter.ToInt32(rgb, 16);
            is16BitIndices   = BitConverter.ToInt32(rgb, 20);
            numberMaterials  = BitConverter.ToInt32(rgb, 24);
            numberAttrRanges = BitConverter.ToInt32(rgb, 28);
            offsetVertex     = BitConverter.ToInt32(rgb, 32);
            offsetIndices    = BitConverter.ToInt32(rgb, 36);
            offsetAttrRange  = BitConverter.ToInt32(rgb, 40);
            offsetMaterial   = BitConverter.ToInt32(rgb, 44);
            bytesMaterials   = BitConverter.ToInt32(rgb, 48);

            // verify number of vertices
            if (numberVertices < 0)
            {
                throw new MeshSerializationException(
                          String.Format(CultureInfo.InvariantCulture,
                                        "Invalid number of  vertices: {0}", numberVertices));
            }

            // verify number of indices
            if (numberIndices < 0 || numberIndices % 3 != 0)
            {
                throw new MeshSerializationException(
                          String.Format(CultureInfo.InvariantCulture,
                                        "Invalid number of indices: {0}", numberIndices));
            }

            // verify number of materials
            if (numberMaterials < 0)
            {
                throw new MeshSerializationException(
                          String.Format(CultureInfo.InvariantCulture,
                                        "Invalid number of materials: {0}", numberMaterials));
            }

            // verify number of attribute ranges
            if (numberAttrRanges < 0)
            {
                throw new MeshSerializationException(
                          String.Format(CultureInfo.InvariantCulture,
                                        "Invalid number of attribute ranges: {0}",
                                        numberAttrRanges));
            }

            // determine number of index bytes and verify Is16BitIndices
            if (is16BitIndices == 1)
            {
                bytesIndices = numberIndices * 2;
            }
            else if (is16BitIndices == 0)
            {
                bytesIndices = numberIndices * 4;
            }
            else
            {
                throw new MeshSerializationException(
                          String.Format(CultureInfo.InvariantCulture,
                                        "Invalid value for is16BitIndices: {0}",
                                        is16BitIndices));
            }

            // Managed Direct3D mobile uses different Fvf defines than
            // managed Direct3D for the desktop
            // when this code is linked against the desktop version
            // this will convert the Fvf to match MD3DM constants
            // when this code is linked against MD3DM this section will
            // not have changed anything.

            // determine the necessary Fvf
            int sourceFormat = (int)flexibleVertexFormat;
            int textureCount;

            flexibleVertexFormat = VertexFormats.Position;

            if ((sourceFormat & md3dmFvfNormal) != 0)
            {
                flexibleVertexFormat |= VertexFormats.Normal;
            }

            if ((sourceFormat & md3dmFvfDiffuse) != 0)
            {
                flexibleVertexFormat |= VertexFormats.Diffuse;
            }

            if ((sourceFormat & md3dmFvfSpecular) != 0)
            {
                flexibleVertexFormat |= VertexFormats.Specular;
            }

            // determine number of textures
            textureCount = (sourceFormat &
                            (int)VertexFormats.TextureCountMask)
                           >> (int)md3dmFvfTextureCountShift;

            //limit to 4 textures
            if (textureCount > 4)
            {
                textureCount = 4;
            }

            // continue setting up necessary Fvf
            flexibleVertexFormat |= (VertexFormats)(
                textureCount << (int)VertexFormats.TextureCountShift);

            int bytesVertices =
                VertexInformation.GetFormatSize(flexibleVertexFormat) *
                numberVertices;

            // Verify none of the data regions overlap
            // the material section is variable size so we can't check
            // that one yet
            if (!((offsetVertex >= sizeofHeader) &&
                  (offsetIndices >= offsetVertex + bytesVertices) &&
                  (offsetAttrRange >= offsetIndices + bytesIndices) &&
                  (offsetMaterial >= offsetAttrRange + numberAttrRanges *
                   sizeofAttributeRange) &&
                  (stream.Length >= offsetMaterial + bytesMaterials)))
            {
                throw new MeshSerializationException(
                          "The data regions are not " +
                          "within the stream or overlap");
            }

            // create our data tables
            materials       = new Material[numberMaterials];
            textures        = new string[numberMaterials];
            attributeRanges = new AttributeRange[numberAttrRanges];
            attributeTable  = new int[numberIndices / 3];

            // move to the attribute range section, propagate up
            // any exception
            stream.Seek(offsetAttrRange, SeekOrigin.Begin);

            // parse attribute ranges
            for (int i = 0; i < numberAttrRanges; i++)
            {
                int attribId;
                int faceStart;
                int faceCount;
                int vertexStart;
                int vertexCount;

                // read in the attribute range data
                stream.Read(rgb, 0, sizeofAttributeRange);
                attribId    = BitConverter.ToInt32(rgb, 0);
                faceStart   = BitConverter.ToInt32(rgb, 4);
                faceCount   = BitConverter.ToInt32(rgb, 8);
                vertexStart = BitConverter.ToInt32(rgb, 12);
                vertexCount = BitConverter.ToInt32(rgb, 16);


                // verify the data
                if ((vertexStart < 0 || vertexCount < 0 ||
                     vertexStart + vertexCount > numberVertices) ||
                    (faceStart < 0 || faceCount < 0 ||
                     (faceStart + faceCount) * 3 > numberIndices))
                {
                    throw new ApplicationException(
                              "Invalid attribute range");
                }

                // store the validated data
                attributeRanges[i].AttributeId = attribId;
                attributeRanges[i].FaceStart   = faceStart;
                attributeRanges[i].FaceCount   = faceCount;
                attributeRanges[i].VertexStart = vertexStart;
                attributeRanges[i].VertexCount = vertexCount;
                for (int j = faceStart; j < faceStart + faceCount; j++)
                {
                    attributeTable[j] = attribId;
                }
            }

            // move to the material section
            stream.Seek(offsetMaterial, SeekOrigin.Begin);

            // parse materials
            for (int i = 0; i < numberMaterials; i++)
            {
                int cbTexture;

                // verify that we aren't reading past the end of the stream
                // its possible an invalid filename length the
                if (stream.Position + sizeofMaterial > stream.Length)
                {
                    throw new MeshSerializationException(
                              "Material data region is" +
                              " corrupt");
                }

                // read  in the material color data
                stream.Read(rgb, 0, sizeofMaterial);
                materials[i].DiffuseColor = new ColorValue(
                    BitConverter.ToSingle(rgb, 0),
                    BitConverter.ToSingle(rgb, 4),
                    BitConverter.ToSingle(rgb, 8),
                    BitConverter.ToSingle(rgb, 12));

                materials[i].AmbientColor = new ColorValue(
                    BitConverter.ToSingle(rgb, 16),
                    BitConverter.ToSingle(rgb, 20),
                    BitConverter.ToSingle(rgb, 24),
                    BitConverter.ToSingle(rgb, 28));

                materials[i].SpecularColor = new ColorValue(
                    BitConverter.ToSingle(rgb, 32),
                    BitConverter.ToSingle(rgb, 36),
                    BitConverter.ToSingle(rgb, 40),
                    BitConverter.ToSingle(rgb, 44));

                materials[i].SpecularSharpness =
                    BitConverter.ToSingle(rgb, 48);

                // read in the size of the texture filename
                cbTexture = BitConverter.ToInt32(rgb, 52);

                // verify that the texture filename has a valid length
                if (cbTexture < 0 || stream.Position + cbTexture >
                    stream.Length)
                {
                    throw new MeshSerializationException(
                              "Material data region is corrupt");
                }

                // read the texture filename
                if (cbTexture > 0)
                {
                    stream.Read(rgb, 0, cbTexture);
                    textures[i] = Encoding.Unicode.GetString(rgb, 0,
                                                             cbTexture);
                }
            }

            // create data buffers
            rgbIb = new byte[bytesIndices];
            rgbVb = new byte[bytesVertices];

            // read in the index data
            stream.Seek(offsetIndices, SeekOrigin.Begin);
            stream.Read(rgbIb, 0, rgbIb.Length);

            // read in the vertex data
            stream.Seek(offsetVertex, SeekOrigin.Begin);
            stream.Read(rgbVb, 0, rgbVb.Length);

            // set the use 32 bit flag appropriately
            flags = (flags & ~(MeshFlags.Use32Bit)) |
                    ((is16BitIndices == 0) ? MeshFlags.Use32Bit : 0);

            // create a new empty mesh
            meshRet = new Mesh(numberIndices / 3, numberVertices,
                               flags, flexibleVertexFormat, device);

            try
            {
                // create the index and vertex buffer
                vb = meshRet.VertexBuffer;
                ib = meshRet.IndexBuffer;

                // write the vertex data
                vb.Lock(0, bytesVertices, LockFlags.None).Write(rgbVb, 0,
                                                                bytesVertices);
                vb.Unlock();

                // write the index data
                ib.Lock(0, rgbIb.Length, LockFlags.None).Write(rgbIb, 0,
                                                               rgbIb.Length);
                ib.Unlock();

                // set the attributes
                meshRet.LockAttributeBuffer(LockFlags.None);
                meshRet.UnlockAttributeBuffer(attributeTable);
                meshRet.SetAttributeTable(attributeRanges);
            }
            catch (DirectXException e)
            {
                // release the mesh if anything went wrong
                meshRet.Dispose();
                meshRet = null;
                throw e;
            }

            return(meshRet);
        }