Beispiel #1
0
        /// <summary>
        /// Sets the vertex data from an array source.
        /// </summary>
        /// <typeparam name="T">The type of data in the vertex buffer.</typeparam>
        /// <param name="data">Array that holds the vertex data</param>
        /// <param name="startIndex">Starting index of the element in the array at which to start copying from</param>
        /// <param name="elementCount">Number of elements to copy from the array</param>
        /// <param name="writeOptions">Writing options for the vertex buffer. None, discard, or no overwrite.</param>
        /// <exception cref="System.ArgumentNullException">Thrown if the data is null.</exception>
        /// <exception cref="Tesla.Core.TeslaException">Thrown if there is an error writing to the vertex buffer
        /// or arguments are invalid, check the inner exception for additional details.</exception>
        /// <remarks>See implementors for details on other exceptions that can be thrown.</remarks>
        public void SetData <T>(T[] data, int startIndex, int elementCount, DataWriteOptions writeOptions) where T : struct
        {
            if (data == null || data.Length == 0)
            {
                throw new ArgumentNullException("Data cannot be null.");
            }

            try {
                _impl.SetData <T>(data, startIndex, elementCount, 0, 0, writeOptions);
            } catch (Exception e) {
                throw new TeslaException("Error writing to vertex buffer: \n" + e.Message, e);
            }
        }
 /// <summary>
 /// Sets the vertex data from an array source.
 /// </summary>
 /// <typeparam name="T">The type of data in the vertex buffer.</typeparam>
 /// <param name="data">Array that holds the vertex data</param>
 /// <param name="startIndex">Starting index of the element in the array at which to start copying from</param>
 /// <param name="elementCount">Number of elements to copy from the array</param>
 /// <param name="offsetInBytes">Offset in bytes from the beginning of the vertex buffer to the data.</param>
 /// <param name="vertexStride">Size of an element in bytes.</param>
 /// <param name="writeOptions">Writing options for the vertex buffer. None, discard, or no overwrite.</param>
 /// <remarks>See implementors for exceptions that may occur.</remarks>
 public abstract void SetData <T>(T[] data, int startIndex, int elementCount, int offsetInBytes, int vertexStride, DataWriteOptions writeOptions) where T : struct;
Beispiel #3
0
        private void OnRenderBatch(Texture2D texture, Sprite[] sprites, int index, int numBatches)
        {
            float scaleWidth  = 1f / (float)texture.Width;
            float scaleHeight = 1f / (float)texture.Height;

            //Setup the vertices for all the batches. The vertexbuffer acts like a wrap around queue
            while (numBatches > 0)
            {
                DataWriteOptions writeOptions = DataWriteOptions.NoOverwrite;
                int actCount = numBatches;
                if (actCount > MaxBatchSize - _spriteVbPos)
                {
                    //Need to split up, so set actual count to the remaining space
                    actCount = MaxBatchSize - _spriteVbPos;
                    //Need to check if actually we've reached the end of the VB,
                    //if so we need to wrap around and set discard
                    if (_spriteVbPos % MaxBatchSize == 0)
                    {
                        writeOptions = DataWriteOptions.Discard;
                        _spriteVbPos = 0;
                        //Reset actual count to the maximum space available, either
                        //requested batch number, or max batch size - whichever is smallest
                        actCount = System.Math.Min(MaxBatchSize, numBatches);
                    }
                }

                //Loop through sprite array, create the geometry
                for (int i = index, j = 0; i < index + actCount; i++)
                {
                    Sprite sprite = sprites[i];
                    float  cos    = 1.0f;
                    float  sin    = 0.0f;
                    float  angle  = sprite.Angle;
                    if (angle != 0.0f)
                    {
                        cos = (float)System.Math.Cos(angle);
                        sin = (float)System.Math.Sin(angle);
                    }

                    Vector4 scOffsets = sprite.ScreenOffsets;
                    float   sx        = scOffsets.X;
                    float   sy        = scOffsets.Y;
                    float   sw        = scOffsets.Z;
                    float   sh        = scOffsets.W;

                    Vector4 texOffsets = sprite.TextureOffsets;
                    float   tu         = texOffsets.X * scaleWidth;
                    float   tv         = texOffsets.Y * scaleHeight;
                    float   tw         = texOffsets.Z * scaleWidth;
                    float   th         = texOffsets.W * scaleHeight;

                    Vector2 origin = sprite.Origin;
                    float   oriX   = origin.X / texOffsets.Z;
                    float   oriY   = origin.Y / texOffsets.W;

                    bool flipH = (sprite.FlipEffect & SpriteFlipEffect.FlipHorizontally) == SpriteFlipEffect.FlipHorizontally;
                    bool flipV = (sprite.FlipEffect & SpriteFlipEffect.FlipVertically) == SpriteFlipEffect.FlipVertically;

                    float z = sprite.OrthoOrder;

                    //Apply change of origin to screen width/height for rotations
                    float sw1 = -oriX * sw;
                    float sw2 = (1 - oriX) * sw;
                    float sh1 = -oriY * sh;
                    float sh2 = (1 - oriY) * sh;

                    //top-left
                    Vector3 v  = new Vector3((sx + (sw1 * cos)) - (sh1 * sin), (sy + (sw1 * sin)) + (sh1 * cos), z);
                    Vector2 uv = new Vector2(tu, tv);
                    if (flipH)
                    {
                        uv.X = 1.0f - uv.X;
                    }
                    if (flipV)
                    {
                        uv.Y = 1.0f - uv.Y;
                    }
                    _vertices[j++] = new VertexPositionColorTexture(
                        v,
                        sprite.Color,
                        uv
                        );

                    //lower-left
                    v  = new Vector3((sx + (sw1 * cos)) - (sh2 * sin), (sy + (sw1 * sin)) + (sh2 * cos), z);
                    uv = new Vector2(tu, tv + th);
                    if (flipH)
                    {
                        uv.X = 1.0f - uv.X;
                    }
                    if (flipV)
                    {
                        uv.Y = 1.0f - uv.Y;
                    }
                    _vertices[j++] = new VertexPositionColorTexture(
                        v,
                        sprite.Color,
                        uv
                        );

                    //lower-right
                    v  = new Vector3((sx + (sw2 * cos)) - (sh2 * sin), (sy + (sw2 * sin)) + (sh2 * cos), z);
                    uv = new Vector2(tu + tw, tv + th);
                    if (flipH)
                    {
                        uv.X = 1.0f - uv.X;
                    }
                    if (flipV)
                    {
                        uv.Y = 1.0f - uv.Y;
                    }
                    _vertices[j++] = new VertexPositionColorTexture(
                        v,
                        sprite.Color,
                        uv
                        );

                    //upper-right
                    v  = new Vector3((sx + (sw2 * cos)) - (sh1 * sin), (sy + (sw2 * sin)) + (sh1 * cos), z);
                    uv = new Vector2(tu + tw, tv);
                    if (flipH)
                    {
                        uv.X = 1.0f - uv.X;
                    }
                    if (flipV)
                    {
                        uv.Y = 1.0f - uv.Y;
                    }
                    _vertices[j++] = new VertexPositionColorTexture(
                        v,
                        sprite.Color,
                        uv
                        );
                }

                //Write to VB
                int stride = VertexPositionColorTexture.SizeInBytes;
                int offset = _spriteVbPos * stride * 4;
                _vertexBuffer.SetData <VertexPositionColorTexture>(_vertices, 0, actCount * 4, offset, stride, writeOptions);

                //Render
                _renderer.DrawIndexed(PrimitiveType.TriangleList, actCount * 6, _spriteVbPos * 6, 0);

                index        += actCount;
                _spriteVbPos += actCount;
                numBatches   -= actCount;
            }
        }
 public override void SetData <T>(T[] data, int startIndex, int elementCount, int offsetInBytes, DataWriteOptions writeOptions)
 {
     throw new NotImplementedException();
 }
Beispiel #5
0
        /// <summary>
        /// Writes data from the array to the index buffer.
        /// </summary>
        /// <typeparam name="T">The type of data in the index buffer - int or short.</typeparam>
        /// <param name="data">Array to copy the data from</param>
        /// <param name="startIndex">Starting index in the array at which to start copying from</param>
        /// <param name="elementCount">Number of indices to write</param>
        /// <param name="offsetInBytes">Offset from the start of the index buffer at which to start writing at</param>
        /// <param name="writeOptions">Write options, used only if this is a dynamic buffer. None, discard, no overwrite</param>
        /// <remarks>See implementors for exceptions that may occur.</remarks>
        public override void SetData <T>(T[] data, int startIndex, int elementCount, int offsetInBytes, DataWriteOptions writeOptions)
        {
            if (_buffer == null || _buffer.Disposed)
            {
                throw new ObjectDisposedException(GetType().Name);
            }

            //Throws null or out of range exception
            D3D10Helper.CheckArrayBounds(data, startIndex, elementCount);

            int numBytes = MemoryHelper.SizeOf <T>();

            int ibSize   = base.IndexCount * ((base.IndexFormat == IndexFormat.SixteenBits) ? 2 : 4);
            int dataSize = elementCount * numBytes;

            if (offsetInBytes < 0 || offsetInBytes > ibSize)
            {
                throw new ArgumentOutOfRangeException("offsetInBytes", "Byte offset is out of range.");
            }

            if ((offsetInBytes + dataSize) > ibSize)
            {
                throw new ArgumentOutOfRangeException("data", "Byte offset and the number of elements to write will cause a buffer overflow.");
            }

            bool usesStaging = false;

            if (base.BufferUsage == ResourceUsage.Static || writeOptions == DataWriteOptions.None)
            {
                CreateStaging();
                usesStaging = true;
            }

            try {
                if (usesStaging)
                {
                    using (SDX.DataStream ds = _staging.Map(D3D.MapMode.Write, D3D.MapFlags.None)) {
                        ds.Position = offsetInBytes;
                        ds.WriteRange <T>(data, startIndex, elementCount);
                        _staging.Unmap();

                        //If we're writing to the entire IB just copy the whole thing
                        if (offsetInBytes == 0 && startIndex == 0 && dataSize == ibSize)
                        {
                            _graphicsDevice.CopyResource(_staging, _buffer);
                        }
                        else
                        {
                            D3D.ResourceRegion region = new D3D.ResourceRegion();
                            region.Left  = offsetInBytes;
                            region.Right = offsetInBytes + dataSize;
                            region.Front = region.Top = 0;
                            region.Back  = region.Bottom = 1;
                            _graphicsDevice.CopySubresourceRegion(_staging, 0, region, _buffer, 0, offsetInBytes, 0, 0);
                        }
                    }
                }
                else
                {
                    D3D.MapMode mode = (writeOptions == DataWriteOptions.Discard) ? D3D.MapMode.WriteDiscard : D3D.MapMode.WriteNoOverwrite;
                    using (SDX.DataStream ds = _buffer.Map(mode, D3D.MapFlags.None)) {
                        ds.Position = offsetInBytes;
                        ds.WriteRange <T>(data, startIndex, elementCount);
                        _buffer.Unmap();
                    }
                }
            } catch (Exception e) {
                throw new TeslaException("Error writing to D3D10 Buffer.", e);
            }
        }
Beispiel #6
0
        /// <summary>
        /// Draws a portion of the mesh's tangent basis.
        /// </summary>
        /// <param name="mesh">Mesh to accumulate data from</param>
        /// <param name="renderer">The renderer</param>
        /// <param name="basisIndex">Specifies which lines to render: 0 for normals, 1 for tangents, 2 for binormals.</param>
        public void Draw(Mesh mesh, IRenderer renderer, int basisIndex)
        {
            //Check if we have the proper data
            MeshData md = mesh.MeshData;

            if (md == null)
            {
                return;
            }
            DataBuffer <Vector3> positions = md.Positions;
            DataBuffer <Vector3> normals   = null;

            switch (basisIndex)
            {
            case 0:
                normals = md.Normals;
                break;

            case 1:
                normals = md.Tangents;
                break;

            case 2:
                normals = md.Binormals;
                break;
            }
            if (positions == null || normals == null)
            {
                return;
            }

            bool       useIndices      = md.UseIndexedPrimitives;
            bool       useShortIndices = md.UsingShortIndices;
            DataBuffer indices         = md.Indices;

            //Setup scaling
            float scale = 1.0f;

            if (mesh.WorldBounding != null)
            {
                _measureBox.Set(mesh.WorldBounding);
                scale = _scaleRatio * (_measureBox.Extents.Length() / 6);
            }
            else
            {
                scale *= 5f;
            }

            //Apply material
            _material.ApplyMaterial(renderer, mesh);
            renderer.SetVertexBuffer(_vertexBuffer);

            //Setup batches + render
            int numBatches = (useIndices) ? md.IndexCount : md.VertexCount;
            int index      = 0;

            while (numBatches > 0)
            {
                DataWriteOptions options = DataWriteOptions.NoOverwrite;
                int actCount             = numBatches;
                //Check if we need to split up
                if (actCount > MaxBatchSize - _lineVbPos)
                {
                    //Need to split up, so get the available space
                    actCount = MaxBatchSize - _lineVbPos;
                    //Need to check if we've reached the end of the VB, if so
                    //must have write discard to not cause a pipeline stall
                    if (_lineVbPos % MaxBatchSize == 0)
                    {
                        options    = DataWriteOptions.Discard;
                        _lineVbPos = 0;
                        //Reset actual count to the maximum space available, either
                        //requested batch number, or max batch size - whichever is smallest
                        actCount = System.Math.Min(MaxBatchSize, numBatches);
                    }
                }

                if (useIndices)
                {
                    if (useShortIndices)
                    {
                        DataBuffer <short> shortIndices = (DataBuffer <short>)indices;
                        //Loop through mesh vertices and create the geometry
                        for (int i = index, j = 0; i < index + actCount; i++)
                        {
                            Vector3 position = positions.Get(shortIndices.Get(i));
                            Vector3 normal   = normals.Get(shortIndices.Get(i));
                            Vector3 position2;
                            Vector3.Multiply(ref normal, scale, out position2);
                            Vector3.Add(ref position, ref position2, out position2);

                            _vertices[j++] = new VertexPositionColor(position, _baseColor);
                            _vertices[j++] = new VertexPositionColor(position2, _tipColor);
                        }
                    }
                    else
                    {
                        DataBuffer <int> intIndices = (DataBuffer <int>)indices;
                        //Loop through mesh vertices and create the geometry
                        for (int i = index, j = 0; i < index + actCount; i++)
                        {
                            Vector3 position = positions.Get(intIndices.Get(i));
                            Vector3 normal   = normals.Get(intIndices.Get(i));
                            Vector3 position2;
                            Vector3.Multiply(ref normal, scale, out position2);
                            Vector3.Add(ref position, ref position2, out position2);

                            _vertices[j++] = new VertexPositionColor(position, _baseColor);
                            _vertices[j++] = new VertexPositionColor(position2, _tipColor);
                        }
                    }
                }
                else
                {
                    //Loop through mesh vertices and create the geometry
                    for (int i = index, j = 0; i < index + actCount; i++)
                    {
                        Vector3 position = positions.Get(i);
                        Vector3 normal   = normals.Get(i);
                        Vector3 position2;
                        Vector3.Multiply(ref normal, scale, out position2);
                        Vector3.Add(ref position, ref position2, out position2);

                        _vertices[j++] = new VertexPositionColor(position, _baseColor);
                        _vertices[j++] = new VertexPositionColor(position2, _tipColor);
                    }
                }

                //Write to VB
                int stride = VertexPositionColor.SizeInBytes;
                int offset = _lineVbPos * stride * 2;
                _vertexBuffer.SetData <VertexPositionColor>(_vertices, 0, actCount * 2, offset, stride, options);

                //Render
                for (int i = 0; i < _material.PassCount; i++)
                {
                    _material.ApplyPass(renderer, i);
                    renderer.Draw(PrimitiveType.LineList, actCount * 2, _lineVbPos * 2);
                }

                //Increment/decrement and prepare for the next iteration
                index      += actCount;
                _lineVbPos += actCount;
                numBatches -= actCount;
            }
        }
Beispiel #7
0
 /// <summary>
 /// Writes data from the array to the index buffer.
 /// </summary>
 /// <typeparam name="T">The type of data in the index buffer - int or short.</typeparam>
 /// <param name="data">Array to copy the data from</param>
 /// <param name="startIndex">Starting index in the array at which to start copying from</param>
 /// <param name="elementCount">Number of indices to write</param>
 /// <param name="offsetInBytes">Offset from the start of the index buffer at which to start writing at</param>
 /// <param name="writeOptions">Write options, used only if this is a dynamic buffer. None, discard, no overwrite</param>
 /// <remarks>See implementors for exceptions that may occur.</remarks>
 public override void SetData <T>(T[] data, int startIndex, int elementCount, int offsetInBytes, DataWriteOptions writeOptions)
 {
     if (base.BufferUsage == ResourceUsage.Static)
     {
         _indexBuffer.SetData <T>(offsetInBytes, data, startIndex, elementCount);
     }
     else
     {
         if (writeOptions == DataWriteOptions.None)
         {
             ((XFG.DynamicIndexBuffer)_indexBuffer).SetData <T>(offsetInBytes, data, startIndex, elementCount, XFG.SetDataOptions.None);
         }
         else
         {
             XFG.SetDataOptions mode = (writeOptions == DataWriteOptions.Discard) ? XFG.SetDataOptions.Discard : XFG.SetDataOptions.NoOverwrite;
             ((XFG.DynamicIndexBuffer)_indexBuffer).SetData <T>(offsetInBytes, data, startIndex, elementCount, mode);
         }
     }
 }
        /// <summary>
        /// Sets the vertex data from an array source.
        /// </summary>
        /// <typeparam name="T">The type of data in the vertex buffer.</typeparam>
        /// <param name="data">Array that holds the vertex data</param>
        /// <param name="startIndex">Starting index of the element in the array at which to start copying from</param>
        /// <param name="elementCount">Number of elements to copy from the array</param>
        /// <param name="offsetInBytes">Offset in bytes from the beginning of the vertex buffer to the data.</param>
        /// <param name="vertexStride">Size of an element in bytes.</param>
        /// <param name="writeOptions">Writing options for the vertex buffer. None, discard, or no overwrite.</param>
        /// <exception cref="System.ObjectDisposedException">Thrown if Dispose() has been called.</exception>
        /// <exception cref="System.InvalidOperationException">Thrown if the write options are incompatible with the resource usage of the buffer.</exception>
        /// <exception cref="System.ArgumentOutOfRangeException">Thrown if the data's vertex stride is too small, the offset in bytes is out of range,
        /// or the byte offset and number of elements to write will cause overflow.</exception>
        /// <exception cref="Tesla.Core.TeslaException">Thrown if there was an error writing to the buffer.</exception>
        public override void SetData <T>(T[] data, int startIndex, int elementCount, int offsetInBytes, int vertexStride, DataWriteOptions writeOptions)
        {
            if (_buffer == null || _buffer.Disposed)
            {
                throw new ObjectDisposedException(GetType().Name);
            }

            //Throw an error if an invalid write options is specified
            if (base.BufferUsage == ResourceUsage.Static && writeOptions != DataWriteOptions.None)
            {
                throw new InvalidOperationException("Can only specify write options other than DataWriteOptions.None for dynamic vertex buffers.");
            }

            //Check if array bounds are out of range
            D3D10Helper.CheckArrayBounds(data, startIndex, elementCount);

            VertexDeclaration vertexDecl = base.VertexDeclaration;
            int vertexCount = base.VertexCount;

            int vbSize     = vertexCount * vertexDecl.VertexStride;
            int elemSize   = MemoryHelper.SizeOf <T>();
            int dataSize   = elementCount * elemSize;
            int vertexStep = vertexStride;

            if (vertexStride != 0)
            {
                vertexStep -= elemSize;
                if (vertexStep < 0)
                {
                    throw new ArgumentOutOfRangeException("vertexStride", "Vertex stride is too small for requested data size.");
                }
                //If we get this far, we need to make sure the actual bytes we're going to look at matches up,
                //since we can grab specific parts of a vertex and not the whole thing
                if (elementCount > 1)
                {
                    dataSize = ((elementCount - 1) * vertexStep) + dataSize;
                }
            }

            //Prevent overflow out of range errors
            if ((offsetInBytes < 0) || (offsetInBytes > vbSize))
            {
                throw new ArgumentOutOfRangeException("offsetInbytes", "Byte offset is out of range.");
            }

            if ((offsetInBytes + dataSize) > vbSize)
            {
                throw new ArgumentOutOfRangeException("data", "Byte offset and elements to write will cause in buffer overflow.");
            }

            //Create scratch buffer, if it hasn't been created already
            bool usesStaging = false;

            if (base.BufferUsage == ResourceUsage.Static || writeOptions == DataWriteOptions.None)
            {
                CreateStaging();
                usesStaging = true;
            }

            try {
                if (usesStaging)
                {
                    //If we're not going to be writing the entire vertex structure, we need to first
                    //copy the contents of the affected vertex data into the staging buffer
                    if (vertexStep != vertexStride)
                    {
                        //If we're going to be working with all the verts, no need to copy a subresource region
                        if (offsetInBytes == 0 && startIndex == 0 && vertexCount == data.Length)
                        {
                            _graphicsDevice.CopyResource(_buffer, _staging);
                        }
                        else
                        {
                            D3D.ResourceRegion region = new D3D.ResourceRegion();
                            region.Left  = offsetInBytes;
                            region.Right = offsetInBytes + dataSize;
                            region.Front = region.Top = 0;
                            region.Back  = region.Bottom = 1;
                            _graphicsDevice.CopySubresourceRegion(_buffer, 0, region, _staging, 0, offsetInBytes, 0, 0);
                        }
                    }

                    using (SDX.DataStream ds = _staging.Map(D3D.MapMode.Read, D3D.MapFlags.None)) {
                        //If the step is zero, that means we're dealing with the entire vertex and not a subset of it
                        if (vertexStep == 0)
                        {
                            ds.Position = offsetInBytes;
                            ds.WriteRange <T>(data, startIndex, elementCount);
                        }
                        else
                        {
                            ds.Position = offsetInBytes;
                            int count = elementCount - 1;
                            int index = startIndex;
                            ds.Write <T>(data[index++]);
                            while (count > 0)
                            {
                                ds.Position += vertexStep;
                                ds.Write <T>(data[index]);
                                count--;
                                index++;
                            }
                        }
                        _staging.Unmap();

                        //If we're writing to the entire VB just copy the whole thing
                        if (offsetInBytes == 0 && startIndex == 0 && dataSize == vbSize)
                        {
                            _graphicsDevice.CopyResource(_staging, _buffer);
                        }
                        else
                        {
                            D3D.ResourceRegion region = new D3D.ResourceRegion();
                            region.Left  = offsetInBytes;
                            region.Right = offsetInBytes + dataSize;
                            region.Front = region.Top = 0;
                            region.Back  = region.Bottom = 1;
                            _graphicsDevice.CopySubresourceRegion(_staging, 0, region, _buffer, 0, offsetInBytes, 0, 0);
                        }
                    }
                    //Dynamic vertex buffers only
                }
                else
                {
                    D3D.MapMode mode = (writeOptions == DataWriteOptions.Discard) ? D3D.MapMode.WriteDiscard : D3D.MapMode.WriteNoOverwrite;
                    using (SDX.DataStream ds = _buffer.Map(mode, D3D.MapFlags.None)) {
                        //If the step is zero, that means we're dealing with the entire vertex and not a subset of it
                        if (vertexStep == 0)
                        {
                            ds.Position = offsetInBytes;
                            ds.WriteRange <T>(data, startIndex, elementCount);
                        }
                        else
                        {
                            ds.Position = offsetInBytes;
                            int count = elementCount - 1;
                            int index = startIndex;
                            ds.Write <T>(data[index++]);
                            while (count > 0)
                            {
                                ds.Position += vertexStep;
                                ds.Write <T>(data[index]);
                                count--;
                                index++;
                            }
                        }
                        _buffer.Unmap();
                    }
                }
            } catch (Exception e) {
                throw new TeslaException("Error reading from D3D10 Buffer.", e);
            }
        }