首页 文章

libgdx绘制弧形曲线

提问于
浏览
1

libgdx的弧函数而不是绘制弧形绘制一个饼图段(即有2条线连接到弧的原点)

shapeRenderer.begin(ShapeType.Line);
shapeRenderer.arc(x, y, radius, 30, 120);
shapeRenderer.end();

是否有解决此问题的方法,以便libgdx可以绘制类似于html5画布弧函数的弧形曲线?

4 回答

  • 1

    最后,我分了一个ShapeRenderer类

    public class Arc extends ShapeRenderer{
    
        private final ImmediateModeRenderer renderer;
        private final Color color = new Color(1, 1, 1, 1);
    
        public Arc(){
            renderer = super.getRenderer();
        }
    
        /** Draws an arc using {@link ShapeType#Line} or {@link ShapeType#Filled}. */
        public void arc (float x, float y, float radius, float start, float degrees) {
        int segments = (int)(6 * (float)Math.cbrt(radius) * (degrees / 360.0f));
    
        if (segments <= 0) throw new IllegalArgumentException("segments must be > 0.");
        float colorBits = color.toFloatBits();
        float theta = (2 * MathUtils.PI * (degrees / 360.0f)) / segments;
        float cos = MathUtils.cos(theta);
        float sin = MathUtils.sin(theta);
        float cx = radius * MathUtils.cos(start * MathUtils.degreesToRadians);
        float cy = radius * MathUtils.sin(start * MathUtils.degreesToRadians);
    
        for (int i = 0; i < segments; i++) {
            renderer.color(colorBits);
            renderer.vertex(x + cx, y + cy, 0);
            float temp = cx;
            cx = cos * cx - sin * cy;
            cy = sin * temp + cos * cy;
            renderer.color(colorBits);
            renderer.vertex(x + cx, y + cy, 0);
        }
      }
    }
    

    然后这样称呼它

    Arc a = new Arc();
        a.setProjectionMatrix(cam.combined);
        a.begin(ShapeType.Line);
        a.arc(10, 10, 10, 30, 120);
        a.end();
    

    角度是奇怪的,但不确定这是我的代码还是libGDX

  • 3

    阅读源代码,这似乎是内置行为:

    /** Draws an arc using {@link ShapeType#Line} or {@link ShapeType#Filled}. */
    public void arc (float x, float y, float radius, float start, float degrees, int segments) {
        if (segments <= 0) throw new IllegalArgumentException("segments must be > 0.");
        float colorBits = color.toFloatBits();
        float theta = (2 * MathUtils.PI * (degrees / 360.0f)) / segments;
        float cos = MathUtils.cos(theta);
        float sin = MathUtils.sin(theta);
        float cx = radius * MathUtils.cos(start * MathUtils.degreesToRadians);
        float cy = radius * MathUtils.sin(start * MathUtils.degreesToRadians);
    
        if (shapeType == ShapeType.Line) {
            check(ShapeType.Line, ShapeType.Filled, segments * 2 + 2);
    
            renderer.color(colorBits);
            renderer.vertex(x, y, 0);           <--- CENTER
            renderer.color(colorBits);
            renderer.vertex(x + cx, y + cy, 0); <--- LINE TO START POINT
            for (int i = 0; i < segments; i++) {
                renderer.color(colorBits);
                renderer.vertex(x + cx, y + cy, 0);
                float temp = cx;
                cx = cos * cx - sin * cy;
                cy = sin * temp + cos * cy;
                renderer.color(colorBits);
                renderer.vertex(x + cx, y + cy, 0);
            }
            renderer.color(colorBits);
            renderer.vertex(x + cx, y + cy, 0); <-- LINE TO END POINT
    ...
    

    最简单的可能是复制整个函数,并至少丢弃我标记的两条线: CENTERLINE TO END POINT ,以及每条线上面的 renderer.color(.. 线 .

    (您也可以删除 LINE TO START POINT - 它似乎设置曲线的起点,但's actually also done inside the loop, so it'是多余的 . )

    该函数有一个填充“弧”的第二部分(我同意,它应该被恰当地命名为“馅饼”或“楔形”),但你不需要它,因为它会完全相同 .

    如果你让它工作,你可以把它提交给libgdx的维护者,例如libgdx's Contributions Forum .

  • 1

    我认为您和其他响应者已经发布了当前最佳解决方案 . 任何人的替代“黑客”

    • 并不在乎性能

    • 具有静态背景

    将在用相同绘制的背景色线绘制的2条线上渲染,以便在之后覆盖它们 . 是的,它是蹩脚但又快速而肮脏的小代码解决方案 .

  • 1

    这是一个使用kotlin扩展的简单解决方案 .

    /** Draws an arc with 'stroke' of given width  */
    fun ShapeRenderer.strokeArc(strokeWidth: Float, x: Float, y: Float, radius: Float, start: Float, degrees: Float, sampling: Float = 2f, color: Color = Color.WHITE) {
        val segments = ((6 * Math.cbrt(radius.toDouble()) * (Math.abs(degrees) / 360.0f)) * sampling).toInt()
        val colorBits = color.toFloatBits()
    
        for (i in 0 until segments) {
            val x1 = radius * MathUtils.cosDeg(start + (degrees / segments) * i)
            val y1 = radius * MathUtils.sinDeg(start + (degrees / segments) * i)
    
            val x2 = (radius - strokeWidth) * MathUtils.cosDeg(start + (degrees / segments) * i)
            val y2 = (radius - strokeWidth) * MathUtils.sinDeg(start + (degrees / segments) * i)
    
            val x3 = radius * MathUtils.cosDeg(start + (degrees / segments) * (i + 1))
            val y3 = radius * MathUtils.sinDeg(start + (degrees / segments) * (i + 1))
    
            val x4 = (radius - strokeWidth) * MathUtils.cosDeg(start + (degrees / segments) * (i + 1))
            val y4 = (radius - strokeWidth) * MathUtils.sinDeg(start + (degrees / segments) * (i + 1))
    
            renderer.color(colorBits)
            renderer.vertex(x + x1, y + y1, 0f)
            renderer.color(colorBits)
            renderer.vertex(x + x3, y + y3, 0f)
            renderer.color(colorBits)
            renderer.vertex(x + x2, y + y2, 0f)
    
            renderer.color(colorBits)
            renderer.vertex(x + x3, y + y3, 0f)
            renderer.color(colorBits)
            renderer.vertex(x + x2, y + y2, 0f)
            renderer.color(colorBits)
            renderer.vertex(x + x4, y + y4, 0f)
        }
    }
    

    为了更好地理解这一点以及为什么内置解决方案能够做到这一点 . ShapeRenderer绘制三角形(就像OpenGL一样)所以你需要3个顶点来绘制一个三角形 . 这里我们一次绘制一个段 . 每个段是2个三角形,以形成一个矩形 . 足够的矩形开始看起来像一个光滑的圆圈 .

    内置的ShapeRenderer.arc绘制的方式就像一个派 . 如果你有足够的直边切片,它开始看起来像一个完整的馅饼,而不是一堆三角形到中心 .

    我希望这是有道理的,并允许其他人绘制自己的自定义形状,并学习未来!

相关问题