public MeshDeviceResources(Device device, SharpDX.WIC.ImagingFactory2 imagingFactory, Mesh mesh)
        {
            this.mesh = mesh;

            // create single vertex buffer
            var stream = new DataStream(mesh.vertices.Count * Mesh.VertexPositionNormalTexture.sizeInBytes, true, true);
            stream.WriteRange(mesh.vertices.ToArray());
            stream.Position = 0;

            var vertexBufferDesc = new BufferDescription()
            {
                BindFlags = BindFlags.VertexBuffer,
                CpuAccessFlags = CpuAccessFlags.None,
                Usage = ResourceUsage.Default,
                SizeInBytes = mesh.vertices.Count * Mesh.VertexPositionNormalTexture.sizeInBytes,
            };
            vertexBuffer = new SharpDX.Direct3D11.Buffer(device, stream, vertexBufferDesc);

            stream.Dispose();

            vertexBufferBinding = new VertexBufferBinding(vertexBuffer, Mesh.VertexPositionNormalTexture.sizeInBytes, 0);

            foreach (var subset in mesh.subsets)
            {
                if (subset.material.textureFilename != null)
                {
                    var decoder = new SharpDX.WIC.BitmapDecoder(imagingFactory, subset.material.textureFilename, SharpDX.WIC.DecodeOptions.CacheOnLoad);
                    var bitmapFrameDecode = decoder.GetFrame(0);

                    var stagingTextureDesc = new Texture2DDescription()
                    {
                        Width = bitmapFrameDecode.Size.Width,
                        Height = bitmapFrameDecode.Size.Height,
                        MipLevels = 1,
                        ArraySize = 1,
                        Format = SharpDX.DXGI.Format.B8G8R8A8_UNorm,
                        SampleDescription = new SharpDX.DXGI.SampleDescription(1, 0),
                        Usage = ResourceUsage.Dynamic,
                        BindFlags = BindFlags.ShaderResource,
                        CpuAccessFlags = CpuAccessFlags.Write
                    };
                    var stagingTexture = new Texture2D(device, stagingTextureDesc);

                    var textureDesc = new Texture2DDescription()
                    {
                        Width = bitmapFrameDecode.Size.Width,
                        Height = bitmapFrameDecode.Size.Height,
                        MipLevels = 0,
                        ArraySize = 1,
                        Format = SharpDX.DXGI.Format.B8G8R8A8_UNorm,
                        SampleDescription = new SharpDX.DXGI.SampleDescription(1, 0),
                        Usage = ResourceUsage.Default,
                        BindFlags = BindFlags.ShaderResource | BindFlags.RenderTarget,
                        CpuAccessFlags = CpuAccessFlags.None,
                        OptionFlags = ResourceOptionFlags.GenerateMipMaps
                    };
                    var texture = new Texture2D(device, textureDesc);

                    // convert to 32 bpp
                    var formatConverter = new FormatConverter(imagingFactory);
                    formatConverter.Initialize(bitmapFrameDecode, SharpDX.WIC.PixelFormat.Format32bppBGR);
                    var dataBox = device.ImmediateContext.MapSubresource(stagingTexture, 0, MapMode.WriteDiscard, SharpDX.Direct3D11.MapFlags.None);
                    formatConverter.CopyPixels(dataBox.RowPitch, dataBox.DataPointer, dataBox.RowPitch * bitmapFrameDecode.Size.Height);
                    device.ImmediateContext.UnmapSubresource(stagingTexture, 0);

                    var resourceRegion = new ResourceRegion()
                    {
                        Left = 0,
                        Top = 0,
                        Right = bitmapFrameDecode.Size.Width,
                        Bottom = bitmapFrameDecode.Size.Height,
                        Front = 0,
                        Back = 1,
                    };
                    device.ImmediateContext.CopySubresourceRegion(stagingTexture, 0, resourceRegion, texture, 0);
                    var textureRV = new ShaderResourceView(device, texture);
                    device.ImmediateContext.GenerateMips(textureRV);

                    decoder.Dispose();
                    formatConverter.Dispose();
                    bitmapFrameDecode.Dispose();

                    textureRVs[subset] = textureRV;
                }
            }
        }
 public static Mesh FromOBJFile(string filename)
 {
     var mesh = new Mesh();
     mesh.LoadFromOBJFile(filename);
     return mesh;
 }
        public unsafe void SetPixelShaderConstants(DeviceContext deviceContext, Mesh.Material material, PointLight light)
        {
            // hlsl matrices are default column order
            var constants = new PSConstantBuffer();
            for (int i = 0; i < 3; i++)
            {
                constants.Ka[i] = material.ambientColor[i];
                constants.Kd[i] = material.diffuseColor[i];
                constants.Ks[i] = material.specularColor[i];

                constants.Ia[i] = light.Ia[i];
                constants.Id[i] = light.Id[i];
                constants.Is[i] = light.Is[i];
            }
            constants.Ns = material.shininess;

            // TODO: add camera position

            DataStream dataStream;
            deviceContext.MapSubresource(pixelShaderConstantBuffer, MapMode.WriteDiscard, SharpDX.Direct3D11.MapFlags.None, out dataStream);
            dataStream.Write<PSConstantBuffer>(constants);
            deviceContext.UnmapSubresource(pixelShaderConstantBuffer, 0);
        }