Ejemplo n.º 1
0
        public void AddGlyphPoints(List <PositionTextured> pointList, SizeF size, RectangleF position, RectangleF uv)
        {
            PositionTextured[] points = new PositionTextured[6];

            Vector3d ul = new Vector3d(position.Left + rect.Left, position.Top + rect.Top, .9f);
            Vector3d ur = new Vector3d(position.Right + rect.Left, position.Top + rect.Top, .9f);

            Vector3d ll = new Vector3d(position.Left + rect.Left, position.Bottom + rect.Top, .9f);
            Vector3d lr = new Vector3d(position.Right + rect.Left, position.Bottom + rect.Top, .9f);

            points[0].Position = ul;
            points[0].Tu       = uv.Left;
            points[0].Tv       = uv.Top;

            points[2].Tu       = uv.Left;
            points[2].Tv       = uv.Bottom;
            points[2].Position = ll;

            points[1].Tu       = uv.Right;
            points[1].Tv       = uv.Top;
            points[1].Position = ur;

            points[3].Tu       = uv.Right;
            points[3].Tv       = uv.Bottom;
            points[3].Position = lr;

            points[5].Tu       = uv.Right;
            points[5].Tv       = uv.Top;
            points[5].Position = ur;

            points[4].Tu       = uv.Left;
            points[4].Tv       = uv.Bottom;
            points[4].Position = ll;


            pointList.AddRange(points);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Construct a model class.
        /// </summary>
        /// <param name="sPath"></param>
        public SimpleModel(String sPath)
        {
            #region Material Sorted Mesh Import
            // Get the texture path.
            sPath = sPath.Replace('\\', '/');
            int iIndex = sPath.LastIndexOf("/");
            String sTexturePath = sPath.Substring(0, iIndex);
            Console.WriteLine("Texture Path = " + sTexturePath);

            // Import the file.
            Scene pScene = AssimpImporter.readFile(sPath, DefaultFlags);

            // If we had an error then throw an exception.
            if (pScene == null)
                throw new Exception(AssimpImporter.getErrorString());

            // Order the meshes into a material-mesh array table.
            Dictionary<String, List<Assimp.ManagedAssimp.Mesh>> dTable = new Dictionary<String, List<Assimp.ManagedAssimp.Mesh>>();

            // Sort the meshes into material (i.e. attribute order).
            int iVBufferSize = 0;
            int iIBufferSize = 0;
            foreach (Assimp.ManagedAssimp.Mesh pMesh in pScene.getMeshes())
            {
                // Check we have the appropriate data.
                //if (!(pMesh.hasPositions() & pMesh.hasNormals() & pMesh.hasTangentsAndBitangents() & pMesh.hasTextureCoords(0) & pMesh.hasFaces()))
                //    throw new Exception("Cannot import mesh. Required all, found: Positions=" + pMesh.hasPositions() + ", Normals=" + pMesh.hasNormals() + ", TangentsAndBitangents=" + pMesh.hasTangentsAndBitangents() + ", TextureCoords=" + pMesh.hasTextureCoords(0) + ", Faces=" + pMesh.hasFaces() + ".");

                // Convert the Assimp material to an Evolved material.
                Assimp.ManagedAssimp.Material pMat = pScene.getMaterial((int)pMesh.getMaterialIndex());
                String sMaterial = pMat.getStringProperty("$tex.file");
                if (sMaterial == null)
                    sMaterial += "UnboundMaterial_" + (iNextMaterial++);
                else
                    sMaterial = sTexturePath + "\\" + sMaterial;

                // Normalise the path address type.
                sMaterial = sMaterial.Replace('/', '\\');

                // If this is the first entry - add to the list.
                List<Assimp.ManagedAssimp.Mesh> lMeshes = null;
                if (!dTable.TryGetValue(sMaterial, out lMeshes))
                {
                    lMeshes = new List<Assimp.ManagedAssimp.Mesh>();
                    dTable[sMaterial] = lMeshes;
                }

                // Work out the max vertex and face count.
                iVBufferSize += (int)pMesh.getNumVertices();
                iIBufferSize += (int)pMesh.getNumFaces() * 3;

                // Insert the mesh under the appropriate material.
                lMeshes.Add(pMesh);
            }

            // Create the buffers and reset the stats.
            tVertex = new PositionTextured[iVBufferSize];
            tIndex = new UInt32[iIBufferSize];
            tAttibutes = new Attribute[dTable.Count];
            tMaterials = new String[dTable.Count];
            tTextures = new SlimDX.Direct3D9.Texture[dTable.Count];
            dTable.Keys.CopyTo(tMaterials, 0);

            Radius = 0f;

            // Monitor global poisition in the vertex, index and attribute buffers.
            int iAttribute = 0;
            int iBVertex = 0;
            int iBIndex = 0;

            // For each material.
            foreach (String sMaterial in dTable.Keys)
            {
                // Create a new attribute.
                Attribute pAttrib = new Attribute();
                tAttibutes[iAttribute] = pAttrib;

                // Store the buffer offsets into the attribute.
                pAttrib.iAttributeID = iAttribute;
                pAttrib.iVertexStart = iBVertex;
                pAttrib.iIndexStart = iBIndex;

                int iAVertex = 0;
                int iAFace = 0;

                // Copy the vertices and indicies of each mesh (updating the buffer counts).
                foreach (Assimp.ManagedAssimp.Mesh pMesh in dTable[sMaterial])
                {
                    // Copy verticies.
                    int iMeshVerts = (int)pMesh.getNumVertices();
                    for (int iVertex = 0; iVertex < iMeshVerts; ++iVertex)
                    {
                        // Create the vertex.
                        PositionTextured pVertex = new PositionTextured();

                        // Copy data.
                        pVertex.Position = toDX9(pMesh.getPosition(iVertex));
                        pVertex.UV = toDX9UV(pMesh.getTextureCoordinate(0, iVertex));

                        // Update the radius.
                        Radius = Math.Max(pVertex.Position.Length(), Radius);

                        // Store.
                        tVertex[iVertex + iBVertex] = pVertex;
                    }

                    // Increment the vertex count by the number of verticies we just looped over.
                    iAVertex += iMeshVerts;
                    iBVertex += iMeshVerts;

                    // Copy indicies.
                    int iMeshFaces = (int)pMesh.getNumFaces();
                    for (int iFace = 0; iFace < iMeshFaces; ++iFace)
                    {
                        uint[] tIndices = pMesh.getFace(iFace).getIndices();
                        if (tIndices.Length != 3)
                            throw new Exception("Cannot load a mesh which does not have only triangluar faces.");

                        tIndex[iBIndex++] = tIndices[0];
                        tIndex[iBIndex++] = tIndices[1];
                        tIndex[iBIndex++] = tIndices[2];
                    }

                    // Increment the face count by the number of faces we just looped over.
                    iAFace += iMeshFaces;
                }

                // Save the sizes.
                pAttrib.iFaceCount = iAFace;
                pAttrib.iVertexCount = iAVertex;

                // Increment the attribute counter.
                ++iAttribute;
            }
            #endregion
        }
Ejemplo n.º 3
0
        //创建资源
        private void LoadAssets()
        {
            //创建一个空的根签名
            var rootSignatureDesc = new RootSignatureDescription(
                RootSignatureFlags.AllowInputAssemblerInputLayout,
                //根常量
                new[] {
                new RootParameter(ShaderVisibility.All,    //指定可以访问根签名绑定的内容的着色器,这里设置为顶点着色器
                                  new DescriptorRange()
                {
                    RangeType          = DescriptorRangeType.ConstantBufferView, //指定描述符范围,这里的参数是CBV
                    BaseShaderRegister = 0,                                      //指定描述符范围内的基本着色器
                    OffsetInDescriptorsFromTableStart = int.MinValue,            //描述符从根签名开始的偏移量
                    DescriptorCount = 1                                          //描述符范围内的描述符数
                })
            });

            //表示该根签名需要一组顶点缓冲区来绑定
            rootSignature = device.CreateRootSignature(rootSignatureDesc.Serialize());

            //创建流水线状态,负责编译和加载着色器
#if DEBUG
            var vertexShader = new ShaderBytecode(SharpDX.D3DCompiler.ShaderBytecode.CompileFromFile("shaders.hlsl", "VS", "vs_5_0", SharpDX.D3DCompiler.ShaderFlags.Debug));
#else
            var vertexShader = new ShaderBytecode(SharpDX.D3DCompiler.ShaderBytecode.CompileFromFile("shaders.hlsl", "VS", "vs_5_0"));
#endif

//#if DEBUG
//            var pixelShader = new ShaderBytecode(SharpDX.D3DCompiler.ShaderBytecode.CompileFromFile("shaders.hlsl", "PS", "ps_5_0", SharpDX.D3DCompiler.ShaderFlags.Debug));
//#else
//            var pixelShader = new ShaderBytecode(SharpDX.D3DCompiler.ShaderBytecode.CompileFromFile("shaders.hlsl", "PS", "ps_5_0"));
//#endif

            //描述输入装配器阶段的输入元素,这里定义顶点输入布局
            var inputElementDescs = new[]
            {
                new InputElement("POSITION", 0, Format.R32G32B32_Float, 0, 0),
                new InputElement("TEXCOORD", 0, Format.R32G32_Float, 12, 0)
            };

            //创建流水线状态对象(PSO)
            var psoDesc = new GraphicsPipelineStateDescription()
            {
                InputLayout   = new InputLayoutDescription(inputElementDescs),  //描述输入缓冲器
                RootSignature = rootSignature,                                  //根签名
                VertexShader  = vertexShader,                                   //顶点着色器
                //PixelShader = pixelShader,//像素着色器
                RasterizerState       = RasterizerStateDescription.Default(),   //描述光栅器状态
                BlendState            = BlendStateDescription.Default(),        //描述混合状态
                DepthStencilFormat    = SharpDX.DXGI.Format.D32_Float,          //描述深度/模板格式(纹理资源)
                DepthStencilState     = DepthStencilStateDescription.Default(), //描述深度模板状态
                SampleMask            = int.MaxValue,                           //混合状态的样本掩码
                PrimitiveTopologyType = PrimitiveTopologyType.Triangle,         //定义该管道的几何或外壳着色器的输入类型,这里是三角
                RenderTargetCount     = 1,                                      //RTVFormat成员中的渲染目标格式数
                Flags             = PipelineStateFlags.None,                    //用于控制管道状态的标志,这里表示没有标志
                SampleDescription = new SampleDescription(1, 0),                //描述资源的多采样参数
                StreamOutput      = new StreamOutputDescription()               //描述输出缓冲器
            };
            psoDesc.RenderTargetFormats[0] = Format.R8G8B8A8_UNorm;             //描述渲染目标格式的数组

            //设置管道
            pipelineState = device.CreateGraphicsPipelineState(psoDesc);

            //创建命令列表
            commandList = device.CreateCommandList(
                CommandListType.Direct, //指定命令列表的创建类型,Direct命令列表不会继承任何GPU状态
                commandAllocator,       //指向设备创建的命令列表对象的指针
                pipelineState);         //指向(管道)内存块的指针

            commandList.Close();

            float aspectRatio = viewPort.Width / viewPort.Height;

            //定义待绘制图形的几何形状
            string bitmapPath = @"C:\Users\yulanli\Desktop\TerrainForm\heightMap.BMP";
            Bitmap bitmap     = new Bitmap(bitmapPath);
            xCount     = (bitmap.Width - 1) / 2;
            yCount     = (bitmap.Height - 1) / 2;
            cellWidth  = bitmap.Width / xCount;
            cellHeight = bitmap.Height / yCount;

            var vertices = new PositionTextured[(xCount + 1) * (yCount + 1)];//定义顶点
            for (int i = 0; i < yCount + 1; i++)
            {
                for (int j = 0; j < xCount + 1; j++)
                {
                    System.Drawing.Color color = bitmap.GetPixel((int)(j * cellWidth), (int)(i * cellHeight));
                    float height = float.Parse(color.R.ToString()) + float.Parse(color.G.ToString()) + float.Parse(color.B.ToString());
                    height /= 10;
                    vertices[j + i * (xCount + 1)].Position = new Vector3(j * cellWidth, height, i * cellHeight);
                    vertices[j + i * (xCount + 1)].Texcoord = new Vector2((float)j / (xCount + 1), (float)i / (yCount + 1));
                }
            }
            texture = TextureLoader.TextureLoader.CreateTextureFromDDS(device, @"C:\Users\yulanli\Desktop\TerrainForm\colorMapDDS.DDS");
            //创建待绘制图形的顶点索引
            indices = new int[6 * xCount * yCount];
            for (int i = 0; i < yCount; i++)
            {
                for (int j = 0; j < xCount; j++)
                {
                    indices[6 * (j + i * xCount)]     = j + i * (xCount + 1);
                    indices[6 * (j + i * xCount) + 1] = j + (i + 1) * (xCount + 1);
                    indices[6 * (j + i * xCount) + 2] = j + i * (xCount + 1) + 1;
                    indices[6 * (j + i * xCount) + 3] = j + i * (xCount + 1) + 1;
                    indices[6 * (j + i * xCount) + 4] = j + (i + 1) * (xCount + 1);
                    indices[6 * (j + i * xCount) + 5] = j + (i + 1) * (xCount + 1) + 1;
                }
            }
            //创建视锥体
            //创建摄像机
            CamTarget = new Vector3(bitmap.Width / 2, 0f, bitmap.Height / 2);
            view      = Matrix.LookAtLH(
                CamPostion,     //摄像机原点
                CamTarget,      //摄像机观察目标点
                Vector3.UnitY); //当前世界的向上方向的向量,通常为(0,1,0),即这里的UnitY参数
            proj = Matrix.Identity;
            proj = Matrix.PerspectiveFovLH(
                (float)Math.PI / 4.0f, //用弧度制表示垂直视场角,这里是45°角
                aspectRatio,           //纵横比
                0.3f,                  //到近平面的距离
                500.0f                 //到远平面的距离
                );
            var worldViewProj = Matrix.Multiply(proj, view);

            //使用上传堆来传递顶点缓冲区的数据

            /*--------------------------------------------------*
            * 不推荐使用上传堆来传递像顶点缓冲区这样的静态数据 *
            * 这里使用上载堆是为了代码的简洁性,并且还因为需要 *
            * 传递的资源很少                                   *
            *--------------------------------------------------*/
            var vertexBufferSize = Utilities.SizeOf(vertices);
            vertexBuffer = device.CreateCommittedResource(
                new HeapProperties(HeapType.Upload),
                HeapFlags.None,
                ResourceDescription.Buffer(vertexBufferSize),
                ResourceStates.GenericRead);

            //将顶点的数据复制到顶点缓冲区
            IntPtr pVertexDataBegin = vertexBuffer.Map(0);
            Utilities.Write(
                pVertexDataBegin,
                vertices,
                0,
                vertices.Length);
            vertexBuffer.Unmap(0);

            //初始化顶点缓冲区视图
            vertexBufferView = new VertexBufferView();
            vertexBufferView.BufferLocation = vertexBuffer.GPUVirtualAddress;
            vertexBufferView.StrideInBytes  = Utilities.SizeOf <PositionTextured>();
            vertexBufferView.SizeInBytes    = vertexBufferSize;


            //使用上传堆来传递索引缓冲区的数据
            int indexBufferSize = Utilities.SizeOf(indices);
            indexBuffer = device.CreateCommittedResource(
                new HeapProperties(HeapType.Upload),
                HeapFlags.None,
                ResourceDescription.Buffer(indexBufferSize),
                ResourceStates.GenericRead);

            //将索引的数据复制到索引缓冲区
            IntPtr pIndexDataBegin = indexBuffer.Map(0);
            Utilities.Write(
                pIndexDataBegin,
                indices,
                0,
                indices.Length);
            indexBuffer.Unmap(0);

            //初始化索引缓冲区视图
            indexBufferView = new IndexBufferView();
            indexBufferView.BufferLocation = indexBuffer.GPUVirtualAddress;
            indexBufferView.SizeInBytes    = indexBufferSize;
            indexBufferView.Format         = Format.R32_UInt;

            //创建bundle
            bundle = device.CreateCommandList(
                0,
                CommandListType.Bundle,
                bundleAllocator,
                pipelineState);
            bundle.SetGraphicsRootSignature(rootSignature);
            bundle.PrimitiveTopology = SharpDX.Direct3D.PrimitiveTopology.TriangleList;
            bundle.SetVertexBuffer(0, vertexBufferView);
            bundle.SetIndexBuffer(indexBufferView);

            //bundle.DrawInstanced(
            //   vertices.Length,//VertexCountPerInstance,要绘制的顶点数
            //    1,//InstanceCount,要绘制的实例数,这里是1个
            //    0,//StartVertexLocation,第一个顶点的索引,这里是0
            //    0);//StartInstanceLocation,在从顶点缓冲区读取每个实例数据之前添加到每个索引的值

            bundle.DrawIndexedInstanced(
                indices.Length, //IndexCountPerInstance,要绘制的索引数
                1,              //InstanceCount,要绘制的实例数,这里是1个
                0,              //StartIndexLocation,第一个顶点的索引,这里是0
                0,              //BaseVertexLocation,,从顶点缓冲区读取顶点之前添加到每个索引的值
                0);             //StartInstanceLocation,在从顶点缓冲区读取每个实例数据之前添加到每个索引的值
            bundle.Close();

            //使用上传堆来传递常量缓冲区的数据

            /*--------------------------------------------------*
            * 不推荐使用上传堆来传递像垂直缓冲区这样的静态数据 *
            * 这里使用上载堆是为了代码的简洁性,并且还因为需要 *
            * 传递的资源很少                                   *
            *--------------------------------------------------*/
            constantBuffer = device.CreateCommittedResource(
                new HeapProperties(HeapType.Upload),
                HeapFlags.None,
                ResourceDescription.Buffer(1024 * 64),
                ResourceStates.GenericRead);

            //创建SRV视图
            var srvDesc = new ShaderResourceViewDescription();
            srvDesc.Texture2D.MostDetailedMip     = 0;
            srvDesc.Texture2D.ResourceMinLODClamp = 0.0f;
            device.CreateShaderResourceView(texture, srvDesc, shaderRenderViewHeap.CPUDescriptorHandleForHeapStart);

            //创建常量缓冲区视图(CBV)
            var cbvDesc = new ConstantBufferViewDescription()
            {
                BufferLocation = constantBuffer.GPUVirtualAddress,
                SizeInBytes    = (Utilities.SizeOf <ConstantBuffer>() + 255) & ~255
            };
            device.CreateConstantBufferView(
                cbvDesc,
                constantBufferViewHeap.CPUDescriptorHandleForHeapStart);

            //初始化并映射常量缓冲区

            /*--------------------------------------------------*
            * 直到应用程序关闭,我们才会取消映射,因此在资源的 *
            * 生命周期中保持映射是可以的                       *
            *------------------------------------------------- */
            constantBufferPointer = constantBuffer.Map(0);
            Utilities.Write(constantBufferPointer, ref worldViewProj);

            //创建同步对象
            //创建围栏
            fence = device.CreateFence(
                0,                //围栏的初始值
                FenceFlags.None); //指定围栏的类型,None表示没有指定的类型
            fenceValue = 1;
            //创建用于帧同步的事件句柄
            fenceEvent = new AutoResetEvent(false);
        }
Ejemplo n.º 4
0
        public void AddGlyphPoints(List<PositionTextured> pointList, SizeF size, RectangleF position, RectangleF uv)
        {
            PositionTextured[] points = new PositionTextured[6];

            Vector3d ul = new Vector3d(position.Left+rect.Left, position.Top+rect.Top, .9f);
            Vector3d ur = new Vector3d(position.Right+rect.Left, position.Top+rect.Top, .9f);

            Vector3d ll = new Vector3d(position.Left+rect.Left, position.Bottom+rect.Top, .9f);
            Vector3d lr = new Vector3d(position.Right+rect.Left, position.Bottom+rect.Top, .9f);

            points[0].Position = ul;
            points[0].Tu = uv.Left;
            points[0].Tv = uv.Top;

            points[2].Tu = uv.Left;
            points[2].Tv = uv.Bottom;
            points[2].Position = ll;

            points[1].Tu = uv.Right;
            points[1].Tv = uv.Top;
            points[1].Position = ur;

            points[3].Tu = uv.Right;
            points[3].Tv = uv.Bottom;
            points[3].Position = lr;

            points[5].Tu = uv.Right;
            points[5].Tv = uv.Top;
            points[5].Position = ur;

            points[4].Tu = uv.Left;
            points[4].Tv = uv.Bottom;
            points[4].Position = ll;

            pointList.AddRange(points);
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Creates a model of a textured round disc with a hole in the middle.
        /// </summary>
        /// <param name="device">The <see cref="Device"/> to create the mesh in.</param>
        /// <param name="radiusInner">The radius of the inner circle of the ring.</param>
        /// <param name="radiusOuter">The radius of the outer circle of the ring.</param>
        /// <param name="height">The height of the ring.</param>
        /// <param name="segments">The number of segments the ring shall consist of.</param>
        public static Mesh Disc(Device device, float radiusInner, float radiusOuter, float height, int segments)
        {
            #region Sanity checks
            if (device == null)
            {
                throw new ArgumentNullException(nameof(device));
            }
            #endregion

            const float tuInner = 0, tuOuter = 1;

            Log.Info("Generate predefined model: Disc");
            var posInner = new Vector3(radiusInner, 0, 0);
            var posOuter = new Vector3(radiusOuter, 0, 0);

            #region Generate vertexes
            int vertCount = 0;
            var step      = (float)(Math.PI * 2 / segments);
            var vertexes  = new PositionTextured[segments * 4];

            for (int i = 0; i < segments; i++)
            {
                vertexes[vertCount++] = new PositionTextured(posInner.X, posInner.Y - height / 2, posInner.Z, tuInner, 0);
                vertexes[vertCount++] = new PositionTextured(posInner.X, posInner.Y + height / 2, posInner.Z, tuInner, 0);
                vertexes[vertCount++] = new PositionTextured(posOuter.X, posOuter.Y - height / 2, posOuter.Z, tuOuter, 0);
                vertexes[vertCount++] = new PositionTextured(posOuter.X, posOuter.Y + height / 2, posOuter.Z, tuOuter, 0);

                // Increment rotation
                posInner = Vector3.TransformCoordinate(posInner, Matrix.RotationY(step));
                posOuter = Vector3.TransformCoordinate(posOuter, Matrix.RotationY(step));
            }
            #endregion

            #region Generate indexes
            int indexCount = 0;
            var indexes    = new short[segments * 24];

            for (int i = 0; i < segments; i++)
            {
                short innerBottom1 = (short)(i * 4), innerTop1 = (short)(i * 4 + 1);
                short outerBottom1 = (short)(i * 4 + 2), outerTop1 = (short)(i * 4 + 3);
                short innerBottom2 = (short)(i * 4 + 4), innerTop2 = (short)(i * 4 + 5);
                short outerBottom2 = (short)(i * 4 + 6), outerTop2 = (short)(i * 4 + 7);

                if (innerBottom2 >= vertexes.Length)
                {
                    innerBottom2 -= (short)vertexes.Length;
                }
                if (innerTop2 >= vertexes.Length)
                {
                    innerTop2 -= (short)vertexes.Length;
                }
                if (outerBottom2 >= vertexes.Length)
                {
                    outerBottom2 -= (short)vertexes.Length;
                }
                if (outerTop2 >= vertexes.Length)
                {
                    outerTop2 -= (short)vertexes.Length;
                }

                // Bottom 2 triangles
                indexes[indexCount++] = innerBottom1;
                indexes[indexCount++] = innerBottom2;
                indexes[indexCount++] = outerBottom2;
                indexes[indexCount++] = innerBottom1;
                indexes[indexCount++] = outerBottom2;
                indexes[indexCount++] = outerBottom1;

                // Top 2 triangles
                indexes[indexCount++] = innerTop1;
                indexes[indexCount++] = outerTop2;
                indexes[indexCount++] = innerTop2;
                indexes[indexCount++] = innerTop1;
                indexes[indexCount++] = outerTop1;
                indexes[indexCount++] = outerTop2;

                // Inner 2 triangles
                indexes[indexCount++] = innerTop1;
                indexes[indexCount++] = innerBottom2;
                indexes[indexCount++] = innerBottom1;
                indexes[indexCount++] = innerTop1;
                indexes[indexCount++] = innerTop2;
                indexes[indexCount++] = innerBottom2;

                // Outer 2 triangles
                indexes[indexCount++] = outerBottom1;
                indexes[indexCount++] = outerBottom2;
                indexes[indexCount++] = outerTop1;
                indexes[indexCount++] = outerBottom2;
                indexes[indexCount++] = outerTop2;
                indexes[indexCount++] = outerTop1;
            }
            #endregion

            var mesh = new Mesh(device, indexes.Length / 3, vertexes.Length, MeshFlags.Managed, PositionTextured.Format);
            BufferHelper.WriteVertexBuffer(mesh, vertexes);
            BufferHelper.WriteIndexBuffer(mesh, indexes);
            MeshHelper.GenerateNormalsAndTangents(device, ref mesh, false);

            return(mesh);
        }