【问题标题】:Drawing filled polygon with libGDX使用 libGDX 绘制填充多边形
【发布时间】:2013-03-31 19:15:34
【问题描述】:

我想用 libGDX 绘制一些(填充的)多边形。它不应该填充图形/纹理。我只有多边形的顶点(闭合路径)并尝试使用网格进行可视化,但在某些时候这不是最好的解决方案,我认为。

我的矩形代码是:

private Mesh mesh;

@Override
public void create() {
    if (mesh == null) {
        mesh = new Mesh(
            true, 4, 0, 
            new VertexAttribute(Usage.Position, 3, "a_position")
        );
        mesh.setVertices(new float[] { 
            -0.5f, -0.5f, 0
            0.5f, -0.5f, 0,
            -0.5f, 0.5f, 0,
            0.5f, 0.5f, 0 
        });     
    }
}

// ...

@Override
public void render() {
    Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
    mesh.render(GL10.GL_TRIANGLE_STRIP, 0, 4);
}

有什么功能可以更简单地绘制填充多边形吗?

【问题讨论】:

  • 我从 libgdx 中找到了 Polygon 类,但我不知道如何将它们添加到我的场景中......
  • 为什么如果我运行这段代码我什么也看不到

标签: java libgdx


【解决方案1】:

自从最近更新 LibGDX 以来,@Rus 答案正在使用已弃用的函数。但是,我将他/她的功劳归功于以下新的更新版本:

PolygonSprite poly;
PolygonSpriteBatch polyBatch = new PolygonSpriteBatch(); // To assign at the beginning
Texture textureSolid;

// Creating the color filling (but textures would work the same way)
Pixmap pix = new Pixmap(1, 1, Pixmap.Format.RGBA8888);
pix.setColor(0xDEADBEFF); // DE is red, AD is green and BE is blue.
pix.fill();
textureSolid = new Texture(pix);
PolygonRegion polyReg = new PolygonRegion(new TextureRegion(textureSolid),
  new float[] {      // Four vertices
    0, 0,            // Vertex 0         3--2
    100, 0,          // Vertex 1         | /|
    100, 100,        // Vertex 2         |/ |
    0, 100           // Vertex 3         0--1
}, new short[] {
    0, 1, 2,         // Two triangles using vertex indices.
    0, 2, 3          // Take care of the counter-clockwise direction. 
});
poly = new PolygonSprite(polyReg);
poly.setOrigin(a, b);
polyBatch = new PolygonSpriteBatch();

如果您的多边形不是凸面,则有关良好的三角剖分算法,请参阅 Toussaint (1991) 的几乎线性耳夹算法

Efficient triangulation of simple polygons, Godfried Toussaint, 1991

【讨论】:

【解决方案2】:

这是一个绘制二维凹多边形的 libGDX 示例。

PolygonSprite PolygonSpriteBatch定义类成员

PolygonSprite poly;
PolygonSpriteBatch polyBatch;
Texture textureSolid;

创建实例,使用红色像素作为解决方法的 1x1 大小纹理。一个坐标数组 (x, y) 用于多边形的初始化。

ctor() {
    textureSolid = makeTextureBox(1, 0xFFFF0000, 0, 0); 
    float a = 100;
    float b = 100;
    PolygonRegion polyReg = new PolygonRegion(new TextureRegion(textureSolid),
      new float[] {
        a*0, b*0,
        a*0, b*2,
        a*3, b*2,
        a*3, b*0,
        a*2, b*0,
        a*2, b*1,
        a*1, b*1,
        a*1, b*0,
    });
    poly = new PolygonSprite(polyReg);
    poly.setOrigin(a, b);
    polyBatch = new PolygonSpriteBatch();
}

绘制和旋转多边形

void draw() {
    super.draw();
    polyBatch.begin();
    poly.draw(polyBatch);
    polyBatch.end();
    poly.rotate(1.1f);
}

【讨论】:

【解决方案3】:

我相信ShapeRenderer 类现在具有用于顶点定义多边形的多边形方法:

ShapeRenderer.polygon()

【讨论】:

  • ShapeRenderer.polygon() 不适用于填充多边形(从 Libgdx 1.3.1 开始)。
【解决方案4】:

您可以使用 the ShapeRenderer API 使用 Libgdx 绘制简单的纯色形状。

您提供的代码也是绘制纯色多边形的合理方法。它比ShapeRenderer 灵活得多,但要复杂一些。您需要使用glColor4f 设置颜色,或为每个顶点添加Usage.Color 属性。有关第一种方法的详细信息,请参阅the SubMeshColorTest example,有关第二种方法的详细信息,请参阅the MeshColorTexture example

另一个需要考虑的选择是使用精灵纹理。如果您只对简单的纯色对象感兴趣,您可以使用非常简单的单一颜色的 1x1 纹理,并让系统将其拉伸到整个精灵。许多 Libgdx 和底层硬件都针对渲染纹理进行了优化,因此即使您没有真正利用纹理内容,您也会发现它更易于使用。 (您甚至可以使用 1x1 白色纹理,然后使用 SpriteBatchsetColordraw() 轻松绘制不同颜色的矩形。)

您也可以混合搭配各种方法。

【讨论】:

  • 感谢您的回答,这是一个选择。但我之前使用过three.js,并认为还有一个选项可以只绘制没有纹理的单色多边形。例如,我可以使用和可视化 Polygon 类吗?我认为那将是最好的方法。
  • Libgdx Polygon 不能直接绘制。对于任意多边形,我认为使用Mesh 是您从 Libgdx 获得的最佳支持。
  • 我想使用 Mesh 但是,我不知道在上面的示例中我应该设置什么变量而不是 GL10.GL_TRIANGLE_STRIP 来渲染多边形......我只能渲染三角形和正方形,但没有超过 4 个角的东西。
  • 听起来像是要问的新问题。本 OpenGL 教程涵盖了选项 naturewizard.com/tutorial0104.html(尽管 OpenGL ES 去掉了其中的一些,因此并非所有选项都可以通过 Libgdx 获得)。
  • 不幸的是,GL_POLYGON 变量在 mesh.render(...); 中不可用,只有 GL_POLYGON_OFFSET_FILLGL_POLYGON_SMOOTH_HINT 但如果我使用其中一个,它什么都不会显示..
【解决方案5】:

使用三角测量算法,然后将所有三角形绘制为 GL_TRIANGLE_STRIP http://www.personal.psu.edu/cxc11/AERSP560/DELAUNEY/13_Two_algorithms_Delauney.pdf

【讨论】:

【解决方案6】:

只是想与您分享我的相关解决方案,即使用scene2d实现和绘制walkZone。我基本上不得不把其他人帖子的不同建议放在一起:

1) 步行区:

import com.badlogic.gdx.graphics.Pixmap;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.PolygonRegion;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.math.EarClippingTriangulator;
import com.badlogic.gdx.math.Polygon;
import com.mygdx.game.MyGame;

public class WalkZone extends Polygon {
private PolygonRegion polygonRegion = null;
public WalkZone(float[] vertices) {
    super(vertices);
    if (MyGame.DEBUG) {
        Pixmap pix = new Pixmap(1, 1, Pixmap.Format.RGBA8888);
        pix.setColor(0x00FF00AA);
        pix.fill();
        polygonRegion = new PolygonRegion(new TextureRegion(new Texture(pix)),
                vertices, new EarClippingTriangulator().computeTriangles(vertices).toArray());
        }
    }

    public PolygonRegion getPolygonRegion() {
        return polygonRegion;
    }
}

2) Screen:

然后您可以在所需的Stage 中添加一个侦听器:

myStage.addListener(new InputListener() {
        @Override
        public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
            if (walkZone.contains(x, y)) player.walkTo(x, y);
            // or even directly: player.addAction(moveTo ...
            return super.touchDown(event, x, y, pointer, button);
        }
    });

3) 实施:

传递给 te WZ 构造函数的数组是一组 x,y,x,y... 点。如果你逆时针放置它们,它可以工作(我没有检查其他方式,也不知道它是如何工作的);例如,这会生成一个 100x100 的正方形:

yourScreen.walkZone = new WalkZone(new int[]{0, 0, 100, 0, 100, 100, 0, 100});

在我的项目中,它就像一个魅力,即使是非常复杂的多边形。希望对你有帮助!!

【讨论】:

    【解决方案7】:

    大多数答案都建议进行三角测量,这很好,但您也可以使用模板缓冲区来完成。它处理凸多边形和凹多边形。如果您的多边形变化很大,这可能是一个更好的解决方案,因为否则您必须每帧都进行三角测量。此外,此解决方案可以正确处理 EarClippingTriangulator 无法处理的自相交多边形。

    FloatArray vertices = ... // The polygon x,y pairs.
    Color color = ... // The color to draw the polygon.
    
    ShapeRenderer shapes = ...
    ImmediateModeRenderer renderer = shapes.getRenderer();
    
    Gdx.gl.glClearStencil(0);
    Gdx.gl.glClear(GL20.GL_STENCIL_BUFFER_BIT);
    Gdx.gl.glEnable(GL20.GL_STENCIL_TEST);
    Gdx.gl.glStencilFunc(GL20.GL_NEVER, 0, 1);
    Gdx.gl.glStencilOp(GL20.GL_INVERT, GL20.GL_INVERT, GL20.GL_INVERT);
    Gdx.gl.glColorMask(false, false, false, false);
    
    renderer.begin(shapes.getProjectionMatrix(), GL20.GL_TRIANGLE_FAN);
    renderer.vertex(vertices.get(0), vertices.get(1), 0);
    for (int i = 2, n = vertices.size; i < n; i += 2)
        renderer.vertex(vertices.get(i), vertices.get(i + 1), 0);
    renderer.end();
    
    Gdx.gl.glColorMask(true, true, true, true);
    Gdx.gl.glStencilOp(GL20.GL_ZERO, GL20.GL_ZERO, GL20.GL_ZERO);
    Gdx.gl.glStencilFunc(GL20.GL_EQUAL, 1, 1);
    
    Gdx.gl.glEnable(GL20.GL_BLEND);
    shapes.setColor(color);
    shapes.begin(ShapeType.Filled);
    shapes.rect(-9999999, -9999999, 9999999 * 2, 9999999 * 2);
    shapes.end();
    
    Gdx.gl.glDisable(GL20.GL_STENCIL_TEST);
    

    要使用模板缓冲区,您必须在应用启动时指定模板缓冲区的位数。例如,以下是使用 LWJGL2 后端的方法:

        LwjglApplicationConfiguration config = new LwjglApplicationConfiguration();
        config.stencil = 8;
        new LwjglApplication(new YourApp(), config);
    

    有关此技术的更多信息,请尝试以下链接之一:

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-09-10
      • 2011-01-04
      • 1970-01-01
      • 2011-11-29
      • 2015-01-12
      • 1970-01-01
      相关资源
      最近更新 更多