Example #1
0
        static TextureGLSingle()
        {
            QuadBatch <TexturedVertex2D> quadBatch = new QuadBatch <TexturedVertex2D>(512, 128);

            default_quad_action = quadBatch.AddAction;

            // We multiply the size param by 3 such that the amount of vertices is a multiple of the amount of vertices
            // per primitive (triangles in this case). Otherwise overflowing the batch will result in wrong
            // grouping of vertices into primitives.
            LinearBatch <TexturedVertex2D> triangleBatch = new LinearBatch <TexturedVertex2D>(512 * 3, 128, PrimitiveType.Triangles);

            default_triangle_action = triangleBatch.AddAction;
        }
Example #2
0
        public override void Draw()
        {
            if (Alpha <= 0 || Progress == 0) return;

            Progress = (float)Math.Min(Progress, 1.0);

            try
            {
                float endAngle = (float)(Progress * (2 * Math.PI) + startAngle);

                float scaledRadius = Radius * GameBase.WindowManager.Ratio;
                Vector2 scaledPosition = Position * GameBase.WindowManager.Ratio;

                float angle1, angle2;
                if (endAngle < startAngle)
                {
                    angle1 = endAngle;
                    angle2 = startAngle;
                }
                else
                {
                    angle1 = startAngle;
                    angle2 = endAngle;
                }

                if (angle2 > angle1)
                {
                    OsuGlControl.ColourShader2D.Begin();

                    if (vertexBatch == null)
                        vertexBatch = new LinearBatch<Vertex2d>(amountPoints + 2, 1, BeginMode.TriangleFan);

                    vertexBatch.Add(new Vertex2d() { Position = scaledPosition, Colour = this.Colour });

                    Vector2 offset;
                    for (float a = angle1; a < angle2; a += da)
                    {
                        offset = new Vector2((float)Math.Cos(a), (float)Math.Sin(a)) * scaledRadius;
                        vertexBatch.Add(new Vertex2d() { Position = scaledPosition + offset, Colour = this.Colour });
                    }

                    offset = new Vector2((float)Math.Cos(angle2), (float)Math.Sin(angle2)) * scaledRadius;
                    vertexBatch.Add(new Vertex2d() { Position = scaledPosition + offset, Colour = this.Colour });

                    vertexBatch.Draw();

                    OsuGlControl.ColourShader2D.End();
                }
            }
            catch (InvalidOperationException) { }
        }
            private void updateTriangleBatch()
            {
                if (Children == null)
                {
                    return;
                }

                // This logic got roughly copied from the old osu! code base. These constants seem to have worked well so far.
                int clampedAmountChildren = MathHelper.Clamp(Children.Count, 1, 1000);

                if (mayHaveOwnVertexBatch(clampedAmountChildren) && (triangleBatch == null || triangleBatch.Size < clampedAmountChildren))
                {
                    // The same general idea as updateQuadBatch(), except that each child draws up to 3 vertices * 6 triangles after quad-quad intersection
                    triangleBatch = new LinearBatch <TexturedVertex2D>(clampedAmountChildren * 2 * 3, 500, PrimitiveType.Triangles);
                }
            }
Example #4
0
        public override void DrawTriangle(Triangle vertexTriangle, RectangleF?textureRect, ColourInfo drawColour, Action <TexturedVertex2D> vertexAction = null, Vector2?inflationPercentage = null)
        {
            Debug.Assert(!isDisposed);

            RectangleF texRect = GetTextureRect(textureRect);

            if (inflationPercentage.HasValue)
            {
                texRect = texRect.Inflate(new Vector2(inflationPercentage.Value.X * texRect.Width, inflationPercentage.Value.Y * texRect.Height));
            }

            if (vertexAction == null)
            {
                if (triangleBatch == null)
                {
                    // We multiply the size param by 3 such that the amount of vertices is a multiple of the amount of vertices
                    // per primitive (triangles in this case). Otherwise overflowing the batch will result in wrong
                    // grouping of vertices into primitives.
                    triangleBatch = new LinearBatch <TexturedVertex2D>(512 * 3, 128, PrimitiveType.Triangles);
                }
                vertexAction = triangleBatch.Add;
            }

            vertexAction(new TexturedVertex2D
            {
                Position        = vertexTriangle.P0,
                TexturePosition = new Vector2((texRect.Left + texRect.Right) / 2, texRect.Top),
                Colour          = drawColour.TopLeft.Linear,
            });
            vertexAction(new TexturedVertex2D
            {
                Position        = vertexTriangle.P1,
                TexturePosition = new Vector2(texRect.Left, texRect.Bottom),
                Colour          = drawColour.BottomLeft.Linear,
            });
            vertexAction(new TexturedVertex2D
            {
                Position        = vertexTriangle.P2,
                TexturePosition = new Vector2(texRect.Right, texRect.Bottom),
                Colour          = drawColour.BottomRight.Linear,
            });

            FrameStatistics.Increment(StatisticsCounterType.KiloPixels, (long)vertexTriangle.ConservativeArea);
        }
Example #5
0
        public override void DrawTriangle(Triangle vertexTriangle, RectangleF?textureRect, ColourInfo drawColour, Action <TexturedVertex2D> vertexAction = null, Vector2?inflationPercentage = null)
        {
            Debug.Assert(!isDisposed);

            RectangleF texRect = GetTextureRect(textureRect);

            if (inflationPercentage.HasValue)
            {
                texRect = texRect.Inflate(new Vector2(inflationPercentage.Value.X * texRect.Width, inflationPercentage.Value.Y * texRect.Height));
            }

            if (vertexAction == null)
            {
                if (triangleBatch == null)
                {
                    triangleBatch = new LinearBatch <TexturedVertex2D>(512, 128, PrimitiveType.Triangles);
                }
                vertexAction = triangleBatch.Add;
            }

            vertexAction(new TexturedVertex2D
            {
                Position        = vertexTriangle.P0,
                TexturePosition = new Vector2((texRect.Left + texRect.Right) / 2, texRect.Top),
                Colour          = drawColour.TopLeft.Linear,
            });
            vertexAction(new TexturedVertex2D
            {
                Position        = vertexTriangle.P1,
                TexturePosition = new Vector2(texRect.Left, texRect.Bottom),
                Colour          = drawColour.BottomLeft.Linear,
            });
            vertexAction(new TexturedVertex2D
            {
                Position        = vertexTriangle.P2,
                TexturePosition = new Vector2(texRect.Right, texRect.Bottom),
                Colour          = drawColour.BottomRight.Linear,
            });

            FrameStatistics.Increment(StatisticsCounterType.KiloPixels, (long)vertexTriangle.ConservativeArea);
        }
        private void updateVertexBuffer()
        {
            const float start_angle = 0;

            float dir    = Math.Sign(angle);
            float radius = Math.Max(drawSize.X, drawSize.Y);

            // The amount of points are selected such that discrete curvature is smaller than the provided tolerance.
            // The exact angle required to meet the tolerance is: 2 * Math.Acos(1 - TOLERANCE / r)
            // The special case is for extremely small circles where the radius is smaller than the tolerance.
            int amountPoints = 2 * radius <= arc_tolerance ? 2 : Math.Max(2, (int)Math.Ceiling(Math.PI / Math.Acos(1 - arc_tolerance / radius)));

            if (halfCircleBatch == null || halfCircleBatch.Size < amountPoints * 2)
            {
                halfCircleBatch?.Dispose();

                // Amount of points is multiplied by 2 to account for each part requiring two vertices.
                halfCircleBatch = new LinearBatch <TexturedVertex2D>(amountPoints * 2, 1, PrimitiveType.TriangleStrip);
            }

            Matrix3 transformationMatrix = DrawInfo.Matrix;

            MatrixExtensions.ScaleFromLeft(ref transformationMatrix, drawSize);

            Vector2 current       = origin + pointOnCircle(start_angle) * 0.5f;
            Color4  currentColour = colourAt(current);

            current = Vector2Extensions.Transform(current, transformationMatrix);

            Vector2 screenOrigin = Vector2Extensions.Transform(origin, transformationMatrix);
            Color4  originColour = colourAt(origin);

            // Offset by 0.5 pixels inwards to ensure we never sample texels outside the bounds
            RectangleF texRect = texture.GetTextureRect(new RectangleF(0.5f, 0.5f, texture.Width - 1, texture.Height - 1));

            float prevOffset = dir >= 0 ? 0 : 1;

            // First center point
            halfCircleBatch.Add(new TexturedVertex2D
            {
                Position        = Vector2.Lerp(current, screenOrigin, innerRadius),
                TexturePosition = new Vector2(dir >= 0 ? texRect.Left : texRect.Right, texRect.Top),
                Colour          = originColour
            });

            // First outer point.
            halfCircleBatch.Add(new TexturedVertex2D
            {
                Position        = new Vector2(current.X, current.Y),
                TexturePosition = new Vector2(dir >= 0 ? texRect.Left : texRect.Right, texRect.Bottom),
                Colour          = currentColour
            });

            for (int i = 1; i < amountPoints; i++)
            {
                float fract = (float)i / (amountPoints - 1);

                // Clamps the angle so we don't overshoot.
                // dir is used so negative angles result in negative angularOffset.
                float angularOffset    = Math.Min(fract * two_pi, dir * angle);
                float normalisedOffset = angularOffset / two_pi;

                if (dir < 0)
                {
                    normalisedOffset += 1.0f;
                }

                // Update `current`
                current       = origin + pointOnCircle(start_angle + angularOffset) * 0.5f;
                currentColour = colourAt(current);
                current       = Vector2Extensions.Transform(current, transformationMatrix);

                // current center point
                halfCircleBatch.Add(new TexturedVertex2D
                {
                    Position        = Vector2.Lerp(current, screenOrigin, innerRadius),
                    TexturePosition = new Vector2(texRect.Left + (normalisedOffset + prevOffset) / 2 * texRect.Width, texRect.Top),
                    Colour          = originColour
                });

                // current outer point
                halfCircleBatch.Add(new TexturedVertex2D
                {
                    Position        = new Vector2(current.X, current.Y),
                    TexturePosition = new Vector2(texRect.Left + normalisedOffset * texRect.Width, texRect.Bottom),
                    Colour          = currentColour
                });

                prevOffset = normalisedOffset;
            }
        }
Example #7
0
        public override void DrawTriangle(Triangle vertexTriangle, RectangleF?textureRect, ColourInfo drawColour, Action <TexturedVertex2D> vertexAction = null, Vector2?inflationPercentage = null)
        {
            Debug.Assert(!IsDisposed);

            RectangleF texRect         = GetTextureRect(textureRect);
            Vector2    inflationAmount = inflationPercentage.HasValue ? new Vector2(inflationPercentage.Value.X * texRect.Width, inflationPercentage.Value.Y * texRect.Height) : Vector2.Zero;
            RectangleF inflatedTexRect = texRect.Inflate(inflationAmount);

            if (vertexAction == null)
            {
                if (triangleBatch == null)
                {
                    // We multiply the size param by 3 such that the amount of vertices is a multiple of the amount of vertices
                    // per primitive (triangles in this case). Otherwise overflowing the batch will result in wrong
                    // grouping of vertices into primitives.
                    triangleBatch = new LinearBatch <TexturedVertex2D>(512 * 3, 128, PrimitiveType.Triangles);
                }
                vertexAction = triangleBatch.Add;
            }

            // We split the triangle into two, such that we can obtain smooth edges with our
            // texture coordinate trick. We might want to revert this to drawing a single
            // triangle in case we ever need proper texturing, or if the additional vertices
            // end up becoming an overhead (unlikely).
            SRGBColour topColour    = (drawColour.TopLeft + drawColour.TopRight) / 2;
            SRGBColour bottomColour = (drawColour.BottomLeft + drawColour.BottomRight) / 2;

            // Left triangle half
            vertexAction(new TexturedVertex2D
            {
                Position        = vertexTriangle.P0,
                TexturePosition = new Vector2(inflatedTexRect.Left, inflatedTexRect.Top),
                TextureRect     = new Vector4(texRect.Left, texRect.Top, texRect.Right, texRect.Bottom),
                BlendRange      = inflationAmount,
                Colour          = topColour.Linear,
            });
            vertexAction(new TexturedVertex2D
            {
                Position        = vertexTriangle.P1,
                TexturePosition = new Vector2(inflatedTexRect.Left, inflatedTexRect.Bottom),
                TextureRect     = new Vector4(texRect.Left, texRect.Top, texRect.Right, texRect.Bottom),
                BlendRange      = inflationAmount,
                Colour          = drawColour.BottomLeft.Linear,
            });
            vertexAction(new TexturedVertex2D
            {
                Position        = (vertexTriangle.P1 + vertexTriangle.P2) / 2,
                TexturePosition = new Vector2((inflatedTexRect.Left + inflatedTexRect.Right) / 2, inflatedTexRect.Bottom),
                TextureRect     = new Vector4(texRect.Left, texRect.Top, texRect.Right, texRect.Bottom),
                BlendRange      = inflationAmount,
                Colour          = bottomColour.Linear,
            });

            // Right triangle half
            vertexAction(new TexturedVertex2D
            {
                Position        = vertexTriangle.P0,
                TexturePosition = new Vector2(inflatedTexRect.Right, inflatedTexRect.Top),
                TextureRect     = new Vector4(texRect.Left, texRect.Top, texRect.Right, texRect.Bottom),
                BlendRange      = inflationAmount,
                Colour          = topColour.Linear,
            });
            vertexAction(new TexturedVertex2D
            {
                Position        = (vertexTriangle.P1 + vertexTriangle.P2) / 2,
                TexturePosition = new Vector2((inflatedTexRect.Left + inflatedTexRect.Right) / 2, inflatedTexRect.Bottom),
                TextureRect     = new Vector4(texRect.Left, texRect.Top, texRect.Right, texRect.Bottom),
                BlendRange      = inflationAmount,
                Colour          = bottomColour.Linear,
            });
            vertexAction(new TexturedVertex2D
            {
                Position        = vertexTriangle.P2,
                TexturePosition = new Vector2(inflatedTexRect.Right, inflatedTexRect.Bottom),
                TextureRect     = new Vector4(texRect.Left, texRect.Top, texRect.Right, texRect.Bottom),
                BlendRange      = inflationAmount,
                Colour          = drawColour.BottomRight.Linear,
            });

            FrameStatistics.Increment(StatisticsCounterType.KiloPixels, (long)vertexTriangle.ConservativeArea);
        }
Example #8
0
 internal PrimitiveBatch(BeginMode type)
 {
     vertexBatch = new LinearBatch <Vertex2d>(4000, 1, type);
 }