Пример #1
0
            private IEnumerator <object> SendResponseTask(Stream source, int?count)
            {
                var length = Math.Min(
                    (int)source.Length,
                    count.GetValueOrDefault(int.MaxValue)
                    );

                ContentLength = length;

                if (!HeadersSent)
                {
                    HeadersSent = true;
                    yield return(SendHeadersTask());
                }

                ResponseSent = true;

                const int blockSize = 1024 * 128;
                var       bytesLeft = length;

                using (var sda = new StreamDataAdapter(source, false))
                    using (var buffer = BufferPool <byte> .Allocate(blockSize))
                        while (bytesLeft > 0)
                        {
                            var readSize = Math.Min(blockSize, bytesLeft);
                            var fBlock   = sda.Read(buffer.Data, 0, blockSize);
                            yield return(fBlock);

                            bytesLeft -= fBlock.Result;

                            yield return(Adapter.Write(buffer.Data, 0, fBlock.Result));
                        }
            }
Пример #2
0
        public Buffer GetBuffer(bool writable)
        {
            if (writable)
            {
                EnsureList();
            }

            if (_HasList)
            {
                return new Buffer {
                           IsTemporary = false,
                           Data        = Items.GetBuffer(),
                           Count       = Items.Count
                }
            }
            ;
            else
            {
                var alloc = BufferPool <T> .Allocate(4);

                var buf = alloc.Data;
                buf[0] = Item1;
                buf[1] = Item2;
                buf[2] = Item3;
                buf[3] = Item4;
                return(new Buffer {
                    IsTemporary = true,
                    Data = buf,
                    BufferPoolAllocation = alloc,
                    Count = _Count
                });
            }
        }
Пример #3
0
        public static bool DoPolygonsIntersect(Polygon polygonA, Polygon polygonB)
        {
            var offset = ComputeComparisonOffset(polygonA, polygonB);

            using (var axisBuffer = BufferPool <Vector2> .Allocate(polygonA.Count + polygonB.Count)) {
                int axisCount = 0;
                GetPolygonAxes(axisBuffer.Data, ref axisCount, polygonA);
                GetPolygonAxes(axisBuffer.Data, ref axisCount, polygonB);

                for (int i = 0; i < axisCount; i++)
                {
                    var axis = axisBuffer.Data[i];

                    var intervalA = ProjectOntoAxis(axis, polygonA, offset);
                    var intervalB = ProjectOntoAxis(axis, polygonB, offset);

                    bool intersects = intervalA.Intersects(intervalB, Geometry.IntersectionEpsilon);

                    if (!intersects)
                    {
                        return(false);
                    }
                }
            }

            return(true);
        }
            public LinesForLightSource(LightSource lightSource, DeltaLineWriter lineWriter)
            {
                LightSource = lightSource;
                Buffer      = BufferPool <DeltaLine> .Allocate(lineWriter.Lines.Count);

                lineWriter.CopyTo(Buffer.Data, 0, lineWriter.Lines.Count);
                Lines = new ArraySegment <DeltaLine>(Buffer.Data, 0, lineWriter.Lines.Count);
            }
        public void Update(bool parallelUpdate)
        {
            /*
             * if (IntersectionTestsLastFrame > 0)
             *  Debug.WriteLine("{0} intersection tests last frame", IntersectionTestsLastFrame);
             */

            IntersectionTestsLastFrame = 0;

            var options = new ParallelOptions();

            if (!parallelUpdate)
            {
                options.MaxDegreeOfParallelism = 1;
            }

            _ObstructionsByLight.Clear();
#if SDL2
            // Parallel is Satan -flibit
            foreach (LightSource ls in Environment.LightSources)
            {
                LineGeneratorContext ctx = new LineGeneratorContext(Environment.Obstructions.Count * 2);
                GenerateLinesForLightSource(ref ctx, ls);
                lock (_ObstructionsByLight)
                {
                    foreach (var kvp in ctx.Queue)
                    {
                        _ObstructionsByLight.Add(kvp.LightSource, kvp.Lines);
                    }
                }
                ctx.Dispose();
            }
#else
            using (var buffer = BufferPool <LightSource> .Allocate(Environment.LightSources.Count)) {
                Environment.LightSources.CopyTo(buffer.Data);

                Parallel.For(
                    0, Environment.LightSources.Count,
                    options,
                    () => new LineGeneratorContext(Environment.Obstructions.Count * 2),
                    (idx, pls, ctx) => {
                    var ls = buffer.Data[idx];
                    GenerateLinesForLightSource(ref ctx, ls);
                    return(ctx);
                },
                    (ctx) => {
                    lock (_ObstructionsByLight)
                        foreach (var kvp in ctx.Queue)
                        {
                            _ObstructionsByLight.Add(kvp.LightSource, kvp.Lines);
                        }

                    ctx.Dispose();
                }
                    );
            }
#endif
        }
Пример #6
0
        public void PrepareMany <T> (DenseList <T> batches, Batch.PrepareContext context)
            where T : IBatch
        {
            int totalAdded = 0;

            const int blockSize = 128;

            using (var buffer = BufferPool <Task> .Allocate(blockSize)) {
                var task = new Task(null, context);
                int j = 0, c = batches.Count;

                T batch;
                for (int i = 0; i < c; i++)
                {
                    batches.GetItem(i, out batch);
                    if (batch == null)
                    {
                        continue;
                    }

                    ValidateBatch(batch, true);
                    task.Batch = batch;

                    if (context.Async)
                    {
                        buffer.Data[j++] = task;
                        totalAdded      += 1;

                        if (j == (blockSize - 1))
                        {
                            Queue.EnqueueMany(new ArraySegment <Task>(buffer.Data, 0, j));
                            j = 0;
                        }
                    }
                    else
                    {
                        task.Execute();
                    }
                }

                if (context.Async && (j > 0))
                {
                    Queue.EnqueueMany(new ArraySegment <Task>(buffer.Data, 0, j));
                }
            }

            if (context.Async)
            {
                Group.NotifyQueuesChanged();
            }
        }
Пример #7
0
            public BufferPool <ItemInfo> .Buffer GetAsBuffer(out int count)
            {
                var result = BufferPool <ItemInfo> .Allocate(_Collection.Count);

                int i = 0;

                while (MoveNext())
                {
                    result.Data[i++] = _Current;
                }

                count = i;

                return(result);
            }
Пример #8
0
        private void DrawPerformanceStats(ref ImperativeRenderer ir)
        {
            const float scale = 1f;
            var         text  = PerformanceStats.GetText(this);

            using (var buffer = BufferPool <BitmapDrawCall> .Allocate(text.Length)) {
                var layout     = Font.LayoutString(text, buffer, scale: scale);
                var layoutSize = layout.Size;
                var position   = new Vector2(30f, 30f);
                var dc         = layout.DrawCalls;

                ir.FillRectangle(
                    Bounds.FromPositionAndSize(position, layoutSize),
                    Color.Black
                    );
                ir.Layer += 1;
                ir.DrawMultiple(dc, position);
            }
        }
Пример #9
0
        public void DrawString(
            SpriteFont font, string text,
            Vector2 position, Color?color = null, float scale     = 1, float?sortKey = null,
            int characterSkipCount        = 0, int characterLimit = int.MaxValue,
            int?layer             = null, bool?worldSpace = null,
            BlendState blendState = null, SamplerState samplerState = null
            )
        {
            using (var buffer = BufferPool <BitmapDrawCall> .Allocate(text.Length)) {
                var layout = font.LayoutString(
                    text, new ArraySegment <BitmapDrawCall>(buffer.Data),
                    position, color, scale, sortKey.GetValueOrDefault(NextSortKey),
                    characterSkipCount, characterLimit, alignToPixels: true
                    );

                DrawMultiple(
                    layout,
                    layer: layer, worldSpace: worldSpace, blendState: blendState, samplerState: samplerState
                    );
            }
        }
        /// <summary>
        /// Renders all light sources into the target batch container on the specified layer.
        /// </summary>
        /// <param name="frame">Necessary for bookkeeping.</param>
        /// <param name="container">The batch container to render lighting into.</param>
        /// <param name="layer">The layer to render lighting into.</param>
        /// <param name="intensityScale">A factor to scale the intensity of all light sources. You can use this to rescale the intensity of light values for HDR.</param>
        public void RenderLighting(Frame frame, IBatchContainer container, int layer, float intensityScale = 1.0f)
        {
            // FIXME
            var pointLightVertexCount = Environment.LightSources.Count * 4;
            var pointLightIndexCount  = Environment.LightSources.Count * 6;

            if (PointLightVertices.Length < pointLightVertexCount)
            {
                PointLightVertices = new PointLightVertex[1 << (int)Math.Ceiling(Math.Log(pointLightVertexCount, 2))];
            }

            if ((PointLightIndices == null) || (PointLightIndices.Length < pointLightIndexCount))
            {
                PointLightIndices = new short[pointLightIndexCount];

                int i = 0, j = 0;
                while (i < pointLightIndexCount)
                {
                    PointLightIndices[i++] = (short)(j + 0);
                    PointLightIndices[i++] = (short)(j + 1);
                    PointLightIndices[i++] = (short)(j + 3);
                    PointLightIndices[i++] = (short)(j + 1);
                    PointLightIndices[i++] = (short)(j + 2);
                    PointLightIndices[i++] = (short)(j + 3);

                    j += 4;
                }
            }

            var         needStencilClear = true;
            int         vertexOffset = 0, indexOffset = 0;
            LightSource batchFirstLightSource = null;
            BatchGroup  currentLightGroup     = null;

            int layerIndex = 0;

            using (var sortedLights = BufferPool <LightSource> .Allocate(Environment.LightSources.Count))
                using (var resultGroup = BatchGroup.New(container, layer, before: StoreScissorRect, after: RestoreScissorRect)) {
                    if (Render.Tracing.RenderTrace.EnableTracing)
                    {
                        Render.Tracing.RenderTrace.Marker(resultGroup, -9999, "Frame {0:0000} : LightingRenderer {1:X4} : Begin", frame.Index, this.GetHashCode());
                    }

                    int i          = 0;
                    var lightCount = Environment.LightSources.Count;

                    foreach (var lightSource in Environment.LightSources)
                    {
                        sortedLights.Data[i++] = lightSource;
                    }

                    Array.Sort(sortedLights.Data, 0, lightCount, LightSourceComparerInstance);

                    int lightGroupIndex = 1;

                    for (i = 0; i < lightCount; i++)
                    {
                        var lightSource = sortedLights.Data[i];

                        if (lightSource.Opacity <= 0)
                        {
                            continue;
                        }

                        if (batchFirstLightSource != null)
                        {
                            var needFlush =
                                (needStencilClear) ||
                                (batchFirstLightSource.ClipRegion.HasValue != lightSource.ClipRegion.HasValue) ||
                                (batchFirstLightSource.NeutralColor != lightSource.NeutralColor) ||
                                (batchFirstLightSource.Mode != lightSource.Mode) ||
                                (batchFirstLightSource.RampMode != lightSource.RampMode) ||
                                (batchFirstLightSource.RampTexture != lightSource.RampTexture) ||
                                (batchFirstLightSource.RampTextureFilter != lightSource.RampTextureFilter);

                            if (needFlush)
                            {
                                if (Render.Tracing.RenderTrace.EnableTracing)
                                {
                                    Render.Tracing.RenderTrace.Marker(currentLightGroup, layerIndex++, "Frame {0:0000} : LightingRenderer {1:X4} : Point Light Flush ({2} point(s))", frame.Index, this.GetHashCode(), PointLightBatchBuffer.Count);
                                }
                                FlushPointLightBatch(ref currentLightGroup, ref batchFirstLightSource, ref layerIndex);
                                indexOffset = 0;
                            }
                        }

                        if (batchFirstLightSource == null)
                        {
                            batchFirstLightSource = lightSource;
                        }
                        if (currentLightGroup == null)
                        {
                            currentLightGroup = BatchGroup.New(resultGroup, lightGroupIndex++, before: RestoreScissorRect);
                        }

                        var lightBounds = new Bounds(lightSource.Position - new Vector2(lightSource.RampEnd), lightSource.Position + new Vector2(lightSource.RampEnd));

                        Bounds clippedLightBounds;
                        if (lightSource.ClipRegion.HasValue)
                        {
                            var clipBounds = lightSource.ClipRegion.Value;
                            if (!lightBounds.Intersection(ref lightBounds, ref clipBounds, out clippedLightBounds))
                            {
                                continue;
                            }
                        }
                        else
                        {
                            clippedLightBounds = lightBounds;
                        }

                        if (needStencilClear)
                        {
                            if (Render.Tracing.RenderTrace.EnableTracing)
                            {
                                Render.Tracing.RenderTrace.Marker(currentLightGroup, layerIndex++, "Frame {0:0000} : LightingRenderer {1:X4} : Stencil Clear", frame.Index, this.GetHashCode());
                            }
                            ClearBatch.AddNew(currentLightGroup, layerIndex++, IlluminantMaterials.ClearStencil, clearStencil: StencilFalse);
                            needStencilClear = false;
                        }

                        NativeBatch stencilBatch = null;
                        SpatialCollection <LightObstructionBase> .Sector currentSector;
                        using (var e = Environment.Obstructions.GetSectorsFromBounds(lightBounds))
                            while (e.GetNext(out currentSector))
                            {
                                var cachedSector = GetCachedSector(frame, currentSector.Index);
                                if (cachedSector.VertexCount <= 0)
                                {
                                    continue;
                                }

                                if (stencilBatch == null)
                                {
                                    if (Render.Tracing.RenderTrace.EnableTracing)
                                    {
                                        Render.Tracing.RenderTrace.Marker(currentLightGroup, layerIndex++, "Frame {0:0000} : LightingRenderer {1:X4} : Begin Stencil Shadow Batch", frame.Index, this.GetHashCode());
                                    }

                                    stencilBatch = NativeBatch.New(currentLightGroup, layerIndex++, IlluminantMaterials.Shadow, ShadowBatchSetup, lightSource);
                                    stencilBatch.Dispose();
                                    needStencilClear = true;

                                    if (Render.Tracing.RenderTrace.EnableTracing)
                                    {
                                        Render.Tracing.RenderTrace.Marker(currentLightGroup, layerIndex++, "Frame {0:0000} : LightingRenderer {1:X4} : End Stencil Shadow Batch", frame.Index, this.GetHashCode());
                                    }
                                }

                                stencilBatch.Add(new NativeDrawCall(
                                                     PrimitiveType.TriangleList, cachedSector.ObstructionVertexBuffer, 0, cachedSector.ObstructionIndexBuffer, 0, 0, cachedSector.VertexCount, 0, cachedSector.PrimitiveCount
                                                     ));
                            }

                        PointLightVertex vertex;

                        vertex.LightCenter = lightSource.Position;
                        vertex.Color       = lightSource.Color;
                        vertex.Color.W    *= (lightSource.Opacity * intensityScale);
                        vertex.Ramp        = new Vector2(lightSource.RampStart, lightSource.RampEnd);

                        vertex.Position = clippedLightBounds.TopLeft;
                        PointLightVertices[vertexOffset++] = vertex;

                        vertex.Position = clippedLightBounds.TopRight;
                        PointLightVertices[vertexOffset++] = vertex;

                        vertex.Position = clippedLightBounds.BottomRight;
                        PointLightVertices[vertexOffset++] = vertex;

                        vertex.Position = clippedLightBounds.BottomLeft;
                        PointLightVertices[vertexOffset++] = vertex;

                        var newRecord = new PointLightRecord {
                            VertexOffset = vertexOffset - 4,
                            IndexOffset  = indexOffset,
                            VertexCount  = 4,
                            IndexCount   = 6
                        };

                        if (PointLightBatchBuffer.Count > 0)
                        {
                            var oldRecord = PointLightBatchBuffer[PointLightBatchBuffer.Count - 1];

                            if (
                                (newRecord.VertexOffset == oldRecord.VertexOffset + oldRecord.VertexCount) &&
                                (newRecord.IndexOffset == oldRecord.IndexOffset + oldRecord.IndexCount)
                                )
                            {
                                oldRecord.VertexCount += newRecord.VertexCount;
                                oldRecord.IndexCount  += newRecord.IndexCount;
                                PointLightBatchBuffer[PointLightBatchBuffer.Count - 1] = oldRecord;
                            }
                            else
                            {
                                PointLightBatchBuffer.Add(newRecord);
                            }
                        }
                        else
                        {
                            PointLightBatchBuffer.Add(newRecord);
                        }

                        indexOffset += 6;
                    }

                    if (PointLightBatchBuffer.Count > 0)
                    {
                        if (Render.Tracing.RenderTrace.EnableTracing)
                        {
                            Render.Tracing.RenderTrace.Marker(currentLightGroup, layerIndex++, "Frame {0:0000} : LightingRenderer {1:X4} : Point Light Flush ({2} point(s))", frame.Index, this.GetHashCode(), PointLightBatchBuffer.Count);
                        }

                        FlushPointLightBatch(ref currentLightGroup, ref batchFirstLightSource, ref layerIndex);
                    }

                    if (Render.Tracing.RenderTrace.EnableTracing)
                    {
                        Render.Tracing.RenderTrace.Marker(resultGroup, 9999, "Frame {0:0000} : LightingRenderer {1:X4} : End", frame.Index, this.GetHashCode());
                    }
                }
        }
        private CachedSector GetCachedSector(Frame frame, Pair <int> sectorIndex)
        {
            CachedSector result;

            if (!SectorCache.TryGetValue(sectorIndex, out result))
            {
                SectorCache.Add(sectorIndex, result = new CachedSector {
                    SectorIndex = sectorIndex
                });
            }

            if (result.FrameIndex == frame.Index)
            {
                return(result);
            }

            var sector = Environment.Obstructions[sectorIndex];

            int lineCount = 0;

            foreach (var item in sector)
            {
                lineCount += item.Item.LineCount;
            }

            result.PrimitiveCount = lineCount * 2;
            result.VertexCount    = lineCount * 4;
            result.IndexCount     = lineCount * 6;

            if ((result.ObstructionVertexBuffer != null) && (result.ObstructionVertexBuffer.VertexCount < result.VertexCount))
            {
                lock (Coordinator.CreateResourceLock)
                    result.ObstructionVertexBuffer.Dispose();

                result.ObstructionVertexBuffer = null;
            }

            if ((result.ObstructionIndexBuffer != null) && (result.ObstructionIndexBuffer.IndexCount < result.IndexCount))
            {
                lock (Coordinator.CreateResourceLock)
                    result.ObstructionIndexBuffer.Dispose();

                result.ObstructionIndexBuffer = null;
            }

            if (result.ObstructionVertexBuffer == null)
            {
                lock (Coordinator.CreateResourceLock)
                    result.ObstructionVertexBuffer = new DynamicVertexBuffer(frame.RenderManager.DeviceManager.Device, (new ShadowVertex().VertexDeclaration), result.VertexCount, BufferUsage.WriteOnly);
            }

            if (result.ObstructionIndexBuffer == null)
            {
                lock (Coordinator.CreateResourceLock)
                    result.ObstructionIndexBuffer = new DynamicIndexBuffer(frame.RenderManager.DeviceManager.Device, IndexElementSize.SixteenBits, result.IndexCount, BufferUsage.WriteOnly);
            }

            using (var va = BufferPool <ShadowVertex> .Allocate(result.VertexCount))
                using (var ia = BufferPool <short> .Allocate(result.IndexCount)) {
                    var vb = va.Data;
                    var ib = ia.Data;

                    ArrayLineWriterInstance.SetOutput(vb, ib);

                    foreach (var itemInfo in sector)
                    {
                        itemInfo.Item.GenerateLines(ArrayLineWriterInstance);
                    }

                    var linesWritten = ArrayLineWriterInstance.Finish();
                    if (linesWritten != lineCount)
                    {
                        throw new InvalidDataException("GenerateLines didn't generate enough lines based on LineCount");
                    }

                    lock (Coordinator.UseResourceLock) {
                        result.ObstructionVertexBuffer.SetData(vb, 0, result.VertexCount, SetDataOptions.Discard);
                        result.ObstructionIndexBuffer.SetData(ib, 0, result.IndexCount, SetDataOptions.Discard);
                    }
                }

            result.FrameIndex = frame.Index;

            return(result);
        }
Пример #12
0
        public static unsafe void WriteImage(
            byte *data, int dataLength, int width, int height,
            SurfaceFormat sourceFormat, Stream stream,
            ImageWriteFormat format = ImageWriteFormat.PNG, int jpegQuality = 75
            )
        {
            int numComponents;
            var bytesPerPixel = Evil.TextureUtils.GetBytesPerPixelAndComponents(sourceFormat, out numComponents);

            if (dataLength < (bytesPerPixel * width * height))
            {
                throw new ArgumentException("buffer");
            }

            using (var scratch = BufferPool <byte> .Allocate(1024 * 64))
                fixed(byte *_pScratch = scratch.Data)
                {
                    Native.WriteCallback callback = (pScratch, pData, count) => {
                        int offset = 0;
                        while (count > 0)
                        {
                            var copySize = Math.Min(count, scratch.Data.Length);
                            Buffer.MemoryCopy(pData + offset, pScratch, copySize, copySize);
                            stream.Write(scratch.Data, 0, copySize);
                            count  -= copySize;
                            offset += copySize;
                        }
                    };

                    switch (format)
                    {
                    case ImageWriteFormat.HDR:
                        if (bytesPerPixel != 16)
                        {
                            throw new NotImplementedException("Non-vector4");
                        }
                        Native.API.stbi_write_hdr_to_func(callback, _pScratch, width, height, numComponents, (float *)(void *)data);
                        break;

                    case ImageWriteFormat.PNG:
                        if (bytesPerPixel != 4)
                        {
                            throw new NotImplementedException("Non-rgba32");
                        }
                        Native.API.stbi_write_png_to_func(callback, _pScratch, width, height, numComponents, data, width * bytesPerPixel);
                        break;

                    case ImageWriteFormat.BMP:
                        if (bytesPerPixel != 4)
                        {
                            throw new NotImplementedException("Non-rgba32");
                        }
                        Native.API.stbi_write_bmp_to_func(callback, _pScratch, width, height, numComponents, data);
                        break;

                    case ImageWriteFormat.TGA:
                        if (bytesPerPixel != 4)
                        {
                            throw new NotImplementedException("Non-rgba32");
                        }
                        Native.API.stbi_write_tga_to_func(callback, _pScratch, width, height, numComponents, data);
                        break;

                    case ImageWriteFormat.JPEG:
                        if (bytesPerPixel != 4)
                        {
                            throw new NotImplementedException("Non-rgba32");
                        }
                        Native.API.stbi_write_jpg_to_func(callback, _pScratch, width, height, numComponents, data, jpegQuality);
                        break;

                    default:
                        throw new ArgumentOutOfRangeException("format");
                    }
                }
        }
Пример #13
0
        protected void BroadcastToSubscribers(object source, string type, object arguments)
        {
            EventInfo           info = null;
            EventSubscriberList subscribers;
            EventFilter         filter;
            EventCategoryToken  categoryToken = null;
            string categoryName = null;

            IEventSource iSource = source as IEventSource;

            if (iSource != null)
            {
                categoryName  = iSource.CategoryName;
                categoryToken = GetCategory(categoryName);
            }

            for (int i = 0; i < 6; i++)
            {
                string typeFilter = (i & 1) == 1 ? type : AnyType;
                object sourceFilter;

                switch (i)
                {
                case 0:
                case 1:
                    sourceFilter = AnySource;
                    break;

                case 2:
                case 3:
                    sourceFilter = categoryToken;
                    break;

                default:
                    sourceFilter = source;
                    break;
                }

                if ((sourceFilter == null) || (typeFilter == null))
                {
                    continue;
                }

                CreateFilter(
                    sourceFilter,
                    typeFilter,
                    out filter,
                    false
                    );

                if (!_Subscribers.TryGetValue(filter, out subscribers))
                {
                    continue;
                }

                int count = subscribers.Count;
                if (count <= 0)
                {
                    continue;
                }

                if (info == null)
                {
                    info = new EventInfo(this, source, categoryToken, categoryName, type, arguments);
                }

                using (var b = BufferPool <EventSubscriber> .Allocate(count)) {
                    var temp = b.Data;
                    subscribers.CopyTo(temp);

                    for (int j = count - 1; j >= 0; j--)
                    {
                        temp[j](info);

                        if (info.IsConsumed)
                        {
                            return;
                        }
                    }

                    b.Clear();
                }
            }
        }
Пример #14
0
        public static ResolvedMotion ResolvePolygonMotion(Polygon polygonA, Polygon polygonB, Vector2 velocityA)
        {
            var offset = ComputeComparisonOffset(polygonA, polygonB);

            var result = new ResolvedMotion();

            result.AreIntersecting      = true;
            result.WouldHaveIntersected = true;
            result.WillBeIntersecting   = true;

            float velocityProjection;
            var   velocityDistance = velocityA.Length();
            var   velocityAxis     = Vector2.Normalize(velocityA);

            Interval intervalA, intervalB, newIntervalA;
            float    minDistance = float.MaxValue;

            int bufferSize = polygonA.Count + polygonB.Count + 4;

            using (var axisBuffer = BufferPool <Vector2> .Allocate(bufferSize)) {
                int axisCount = 0;

                if (velocityA.LengthSquared() > 0)
                {
                    axisCount         += 4;
                    axisBuffer.Data[0] = Vector2.Normalize(velocityA);
                    axisBuffer.Data[1] = new Vector2(-axisBuffer.Data[0].X, axisBuffer.Data[0].Y);
                    axisBuffer.Data[2] = new Vector2(axisBuffer.Data[0].X, -axisBuffer.Data[0].Y);
                    axisBuffer.Data[3] = new Vector2(-axisBuffer.Data[0].X, -axisBuffer.Data[0].Y);
                }

                GetPolygonAxes(axisBuffer.Data, ref axisCount, polygonA);
                GetPolygonAxes(axisBuffer.Data, ref axisCount, polygonB);

                for (int i = 0; i < axisCount; i++)
                {
                    var axis = axisBuffer.Data[i];

                    intervalA = ProjectOntoAxis(axis, polygonA, offset);
                    intervalB = ProjectOntoAxis(axis, polygonB, offset);

                    bool intersects = intervalA.Intersects(intervalB, Geometry.IntersectionEpsilon);
                    if (!intersects)
                    {
                        result.AreIntersecting = false;
                    }

                    velocityProjection = axis.Dot(ref velocityA);

                    newIntervalA      = intervalA;
                    newIntervalA.Min += velocityProjection;
                    newIntervalA.Max += velocityProjection;

                    var intersectionDistance = newIntervalA.GetDistance(intervalB);
                    intersects = intersectionDistance < 0;
                    if (!intersects)
                    {
                        result.WouldHaveIntersected = false;
                    }

                    if (result.WouldHaveIntersected == false)
                    {
                        result.WillBeIntersecting = false;
                        result.ResultVelocity     = velocityA;
                        break;
                    }

                    if ((velocityDistance > 0) && (intersectionDistance < minDistance))
                    {
                        var minVect     = axis * intersectionDistance;
                        var newVelocity = velocityA + minVect;
                        var newLength   = Vector2.Dot(velocityAxis, newVelocity);
                        newVelocity = velocityAxis * newLength;

                        if (newVelocity.LengthSquared() > velocityA.LengthSquared())
                        {
                            continue;
                        }
                        if (Vector2.Dot(velocityA, newVelocity) < 0.0f)
                        {
                            newVelocity = Vector2.Zero;
                        }

                        velocityProjection   = axis.Dot(ref newVelocity);
                        newIntervalA.Min     = (intervalA.Min + velocityProjection);
                        newIntervalA.Max     = (intervalA.Max + velocityProjection);
                        intersectionDistance = newIntervalA.GetDistance(intervalB);

                        if (intersectionDistance < -IntersectionEpsilon)
                        {
                            continue;
                        }

                        result.ResultVelocity     = newVelocity;
                        result.WillBeIntersecting = false;
                        minDistance = intersectionDistance;
                    }
                }
            }

            return(result);
        }
Пример #15
0
        private IEnumerator <object> RequestTask(ListenerContext context, SocketDataAdapter adapter)
        {
            var  startedWhen = DateTime.UtcNow;
            bool successful  = false;

            try {
                const int    headerBufferSize   = 1024 * 32;
                const int    bodyBufferSize     = 1024 * 128;
                const double requestLineTimeout = 5;

                // RFC2616:
                // Words of *TEXT MAY contain characters from character sets other than ISO-8859-1 [22]
                //  only when encoded according to the rules of RFC 2047 [14].
                Encoding headerEncoding;
                try {
                    headerEncoding = Encoding.GetEncoding("ISO-8859-1");
                } catch {
                    headerEncoding = Encoding.ASCII;
                }

                Request          request;
                RequestBody      body;
                HeaderCollection headers;
                long             bodyBytesRead      = 0;
                long?            expectedBodyLength = null;

                var    reader = new AsyncTextReader(adapter, headerEncoding, headerBufferSize, false);
                string requestLineText;

                while (true)
                {
                    var fRequestLine      = reader.ReadLine();
                    var fRequestOrTimeout = Scheduler.Start(new WaitWithTimeout(fRequestLine, requestLineTimeout));

                    yield return(fRequestOrTimeout);

                    if (fRequestOrTimeout.Failed)
                    {
                        if (!(fRequestOrTimeout.Error is TimeoutException))
                        {
                            OnRequestError(fRequestOrTimeout.Error);
                        }

                        yield break;
                    }

                    if (fRequestLine.Failed)
                    {
                        if (!(fRequestLine.Error is SocketDisconnectedException))
                        {
                            OnRequestError(fRequestLine.Error);
                        }

                        yield break;
                    }

                    requestLineText = fRequestLine.Result;

                    // RFC2616:
                    // In the interest of robustness, servers SHOULD ignore any empty line(s) received where a
                    //  Request-Line is expected. In other words, if the server is reading the protocol stream
                    //   at the beginning of a message and receives a CRLF first, it should ignore the CRLF.
                    if ((requestLineText != null) && (requestLineText.Trim().Length == 0))
                    {
                        continue;
                    }

                    break;
                }

                var requestLineParsed = DateTime.UtcNow;

                headers = new HeaderCollection();
                while (true)
                {
                    var fHeaderLine = reader.ReadLine();
                    yield return(fHeaderLine);

                    if (String.IsNullOrWhiteSpace(fHeaderLine.Result))
                    {
                        break;
                    }

                    headers.Add(new Header(fHeaderLine.Result));
                }

                var headersParsed = DateTime.UtcNow;

                var expectHeader    = (headers.GetValue("Expect") ?? "").ToLowerInvariant();
                var expectsContinue = expectHeader.Contains("100-continue");

                string hostName;
                if (headers.Contains("Host"))
                {
                    hostName = String.Format("http://{0}", headers["Host"].Value);
                }
                else
                {
                    var lep = (IPEndPoint)adapter.Socket.LocalEndPoint;
                    hostName = String.Format("http://{0}:{1}", lep.Address, lep.Port);
                }

                var requestLine = new RequestLine(hostName, requestLineText);

                var remainingBytes = reader.DisposeAndGetRemainingBytes();
                bodyBytesRead += remainingBytes.Count;

                var connectionHeader = (headers.GetValue("Connection") ?? "").ToLowerInvariant();
                var shouldKeepAlive  =
                    ((requestLine.Version == "1.1") || connectionHeader.Contains("keep-alive")) &&
                    !connectionHeader.Contains("close");

                if (headers.Contains("Content-Length"))
                {
                    expectedBodyLength = long.Parse(headers["Content-Length"].Value);
                }

                body = new RequestBody(remainingBytes, expectedBodyLength);

                if (expectsContinue)
                {
                    yield return(adapter.Write(Continue100, 0, Continue100.Length));
                }

                request = new Request(
                    this, adapter, shouldKeepAlive,
                    requestLine, headers, body
                    );

                IncomingRequests.Enqueue(request);

                var      requestEnqueued = DateTime.UtcNow;
                DateTime?requestBodyRead = null;

                // FIXME: I think it's technically accepted to send a body without a content-length, but
                //  it seems to be impossible to make that work right.
                if (expectedBodyLength.HasValue)
                {
                    using (var bodyBuffer = BufferPool <byte> .Allocate(bodyBufferSize))
                        while (bodyBytesRead < expectedBodyLength.Value)
                        {
                            long bytesToRead = Math.Min(expectedBodyLength.Value - bodyBytesRead, bodyBufferSize);

                            if (bytesToRead <= 0)
                            {
                                break;
                            }

                            var fBytesRead = adapter.Read(bodyBuffer.Data, 0, (int)bytesToRead);
                            yield return(fBytesRead);

                            if (fBytesRead.Failed)
                            {
                                if (fBytesRead.Error is SocketDisconnectedException)
                                {
                                    break;
                                }

                                body.Failed(fBytesRead.Error);
                                OnRequestError(fBytesRead.Error);
                                yield break;
                            }

                            var bytesRead = fBytesRead.Result;

                            bodyBytesRead += bytesRead;
                            body.Append(bodyBuffer.Data, 0, bytesRead);
                        }

                    requestBodyRead = DateTime.UtcNow;
                }

                body.Finish();
                successful = true;

                request.Timing = new Request.TimingData {
                    Line    = (requestLineParsed - startedWhen),
                    Headers = (headersParsed - requestLineParsed),
                    Queue   = (requestEnqueued - headersParsed),
                    Body    = (requestBodyRead - requestEnqueued)
                };
            } finally {
                if (!successful)
                {
                    adapter.Dispose();
                }
            }
        }