Example #1
0
            private void addLineCap(Vector2 origin, float theta, float thetaDiff, RectangleF texRect)
            {
                const float step = MathF.PI / MAX_RES;

                float dir = Math.Sign(thetaDiff);

                thetaDiff = dir * thetaDiff;

                int amountPoints = (int)Math.Ceiling(thetaDiff / step);

                if (dir < 0)
                {
                    theta += MathF.PI;
                }

                Vector2 current       = origin + pointOnCircle(theta) * radius;
                Color4  currentColour = colourAt(current);

                current = Vector2Extensions.Transform(current, DrawInfo.Matrix);

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

                for (int i = 1; i <= amountPoints; i++)
                {
                    // Center point
                    halfCircleBatch.Add(new TexturedVertex3D
                    {
                        Position        = new Vector3(screenOrigin.X, screenOrigin.Y, 1),
                        TexturePosition = new Vector2(texRect.Right, texRect.Centre.Y),
                        Colour          = originColour
                    });

                    // First outer point
                    halfCircleBatch.Add(new TexturedVertex3D
                    {
                        Position        = new Vector3(current.X, current.Y, 0),
                        TexturePosition = new Vector2(texRect.Left, texRect.Centre.Y),
                        Colour          = currentColour
                    });

                    float angularOffset = Math.Min(i * step, thetaDiff);
                    current       = origin + pointOnCircle(theta + dir * angularOffset) * radius;
                    currentColour = colourAt(current);
                    current       = Vector2Extensions.Transform(current, DrawInfo.Matrix);

                    // Second outer point
                    halfCircleBatch.Add(new TexturedVertex3D
                    {
                        Position        = new Vector3(current.X, current.Y, 0),
                        TexturePosition = new Vector2(texRect.Left, texRect.Centre.Y),
                        Colour          = currentColour
                    });
                }
            }
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) { }
        }
Example #3
0
 /// <summary>
 /// AddVertex is called to add another vertex to be rendered. To draw a point,
 /// AddVertex must be called once. for lines, twice, and for triangles 3 times.
 /// this function can only be called once begin has been called.
 /// </summary>
 /// <param name="pos">The position of the vertex.</param>
 /// <param name="colour">The colour of the vertex.</param>
 internal void AddVertex(Vector2 pos, Color colour)
 {
     vertexBatch.Add(new Vertex2d()
     {
         Position = pos, Colour = colour
     });
 }
Example #4
0
        private void HalfCircle(Vector2 pos, float radius, float startAngle, float arcLength, Color globalColour, bool shade, int res)
        {
            float da = arcLength / res;

            Color colour = shade ? new Color(globalColour.R, globalColour.G, globalColour.B, (byte)(Math.Max(0, globalColour.A - 30))) : globalColour;

            Vertex2d middleVertex = new Vertex2d()
            {
                Position = pos, Colour = colour
            };
            Vertex2d previousVertex = new Vertex2d();

            float endAngle = (float)(arcLength + startAngle);

            float a = startAngle;

            for (int i = 0; i <= res; ++i)
            {
                if (shade)
                {
                    double alpha = Math.Sin(Math.Abs(a - startAngle - Math.PI / 2));
                    colour = new Color(globalColour.R, globalColour.G, globalColour.B, (byte)(Math.Max(0, globalColour.A - 30 * (1.0 - alpha))));
                }

                Vector2  offset        = new Vector2((float)Math.Cos(a), (float)Math.Sin(a));
                Vertex2d currentVertex = new Vertex2d()
                {
                    Position = pos + offset * radius, Colour = colour
                };

                if (i > 0)
                {
                    triangleFanBatch.Add(middleVertex);
                    triangleFanBatch.Add(currentVertex);
                    triangleFanBatch.Add(previousVertex);
                }

                previousVertex = currentVertex;

                a += da;
                if (a > endAngle)
                {
                    a = endAngle;
                }
            }
        }
        /// <summary>
        /// Renders a half-circle using multiple triangles as approximation. Assuming discrete points along the half circle are sampled
        /// each triangle consists of 2 such neighboring points and the center point of the circle.
        /// </summary>
        /// <param name="count">The amount of discrete points to use for approximating the circle.</param>
        /// <param name="m">A transformation matrix used to obtain the actual positions of each vertex.</param>
        private void glDrawHalfCircle(int count, Matrix m)
        {
            Debug.Assert(count <= MAXRES);

            if (count == 0)
            {
                return;
            }

            Vector3 centerPoint  = Vector3.Transform(new Vector3(0, 0, 1.0f), m);
            Vector3 currentPoint = Vector3.Transform(vertices[0], m);

            for (int i = 0; i <= count - 1; i++)
            {
                // Center point
                halfCircleBatch.Add(new TexturedVertex3d()
                {
                    Position        = centerPoint,
                    TexturePosition = new Vector2(1.0f - 1.0f / (float)TextureSize.Width, 0),
                    Colour          = Color.White
                });

                // First outer point
                halfCircleBatch.Add(new TexturedVertex3d()
                {
                    Position        = currentPoint,
                    TexturePosition = new Vector2(0, 0),
                    Colour          = Color.White
                });

                currentPoint = Vector3.Transform(vertices[i + 1], m);

                // Second outer point
                halfCircleBatch.Add(new TexturedVertex3d()
                {
                    Position        = currentPoint,
                    TexturePosition = new Vector2(0, 0),
                    Colour          = Color.White
                });
            }
        }
        private void updateVertexBuffer()
        {
            const float start_angle = 0;
            const float step        = MathHelper.Pi / MAX_RES;

            float dir = Math.Sign(angle);

            int amountPoints = (int)Math.Ceiling(Math.Abs(angle) / step);

            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++)
            {
                // Clamps the angle so we don't overshoot.
                // dir is used so negative angles result in negative angularOffset.
                float angularOffset    = dir * Math.Min(i * step, dir * angle);
                float normalisedOffset = angularOffset / MathHelper.TwoPi;

                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;
            }
        }
        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 #8
0
        /// <summary>
        /// Render a gradient into a 256x1 texture.
        /// </summary>
        private TextureGl RenderSliderTexture(Color shadow, Color border, Color InnerColour, Color OuterColour, float aa_width)
        {
            using (RenderTarget2D target = new RenderTarget2D(TEX_WIDTH, 1))
            {
                target.Bind();

                GL.Disable(EnableCap.DepthTest);
                GL.Disable(EnableCap.Blend);

                GL.ClearColor(0.859f, 0.439f, 0.576f, 1.0f);
                GL.Clear(ClearBufferMask.ColorBufferBit);
                GL.ClearColor(0, 0, 0, 0);

                OsuGlControl.ColourShader2D.Properties[@"g_ProjMatrix"] = OpenTK.Matrix4.CreateOrthographicOffCenter(0.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f);
                OsuGlControl.ColourShader2D.Begin();

                lineBatch.Add(new Vertex2d()
                {
                    Position = new Vector2(-0.5f, 0.0f), Colour = Color.TransparentBlack
                });
                lineBatch.Add(new Vertex2d()
                {
                    Position = new Vector2(0.0f, 0.0f), Colour = Color.TransparentBlack
                });

                lineBatch.Add(new Vertex2d()
                {
                    Position = new Vector2(0.078125f - aa_width, 0.0f), Colour = shadow
                });

                lineBatch.Add(new Vertex2d()
                {
                    Position = new Vector2(0.078125f + aa_width, 0.0f), Colour = border
                });
                lineBatch.Add(new Vertex2d()
                {
                    Position = new Vector2(0.1875f - aa_width, 0.0f), Colour = border
                });

                lineBatch.Add(new Vertex2d()
                {
                    Position = new Vector2(0.1875f + aa_width, 0.0f), Colour = OuterColour
                });

                lineBatch.Add(new Vertex2d()
                {
                    Position = new Vector2(1.0f, 0.0f), Colour = InnerColour
                });
                lineBatch.Add(new Vertex2d()
                {
                    Position = new Vector2(1.5f, 0.0f), Colour = InnerColour
                });

                lineBatch.Draw();

                OsuGlControl.ColourShader2D.End();
                OsuGlControl.ColourShader2D.Properties[@"g_ProjMatrix"] = OsuGlControl.ProjectionMatrix;

                if (!OsuGlControl.CanUseFBO)
                {
                    //We must re-clear the backbuffer
                    target.Unbind();
                    GL.Clear(ClearBufferMask.ColorBufferBit);
                }

                GL.Enable(EnableCap.Blend);

                return(target.Texture);
            }
        }