Question

I've been desperately searching for a solution on the internet... But I haven't gotten any further than the function glDrawArrays. I have no idea how to use it, or why it isn't working... I want to render the polygon lines (or vertex lines) of my model that I have loaded using ObjLoader. Instead, it keeps showing me the white border.

I'm using libgdx 1.0.0.

Here is my code:

public class Teapot extends ApplicationAdapter {
    ModelBatch batch;
    ModelInstance m;
    Camera cam;
    CameraInputController camController;
    Environment environment;

    @Override
    public void create () {
        batch = new ModelBatch();

        environment = new Environment();
        environment.set(new ColorAttribute(ColorAttribute.AmbientLight, 0.4f, 0.4f, 0.4f, 1f));
        environment.add(new DirectionalLight().set(0.8f, 0.8f, 0.8f, -1f, -0.8f, -0.2f));


        cam = new PerspectiveCamera(67, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
        cam.position.set(0, 0, 5f);
        cam.lookAt(0,0,0);
        cam.position.add(0, 2, 0);
        cam.near = 1f;
        cam.far = 100f;
        cam.update();

        camController = new CameraInputController(cam);
        Gdx.input.setInputProcessor(camController);


        Model model = new ObjLoader().loadModel(Gdx.files.internal("teapot.obj"), true);
        m = new ModelInstance(model);
    }

  @Override
  public void render () {
        Gdx.gl.glViewport(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT);
        Gdx.gl.glDrawArrays(GL20.GL_TRIANGLES, 0, 3);
    batch.begin(cam);
    batch.render(m);
    batch.end();
  }
}

The teapot.obj I'm using: http://groups.csail.mit.edu/graphics/classes/6.837/F03/models/teapot.obj

Was it helpful?

Solution

There are a few different ways you could do this. Basically, the issue is that the model that is loaded carries the info about what kind of model it is (triangles, not lines), and the ModelBatch looks at that info to decide how to draw it.

The most straight-forward way to do it would be to export the model in a format that specifies that it's lines, and then convert it to libgdx's native format (G3D) using fbx-conv. I don't think it's possible to specify .obj files as lines, so you would need something like FBX or maybe Collada.

Here's the simplest way I can think of getting quick and dirty results without fooling with the model file: Subclass ModelInstance and override the following method like this:

    public Renderable getRenderable(final Renderable out, final Node node, 
            final NodePart nodePart) {
        super.getRenderable(out, node, nodePart);
        out.primitiveType = GL20.GL_LINE_STRIP;
        return out;
    }

Then use this subclass instead of ModelInstance. This will tell the ModelBatch that the mesh is a line strip mesh to make it draw lines. The downside is that it will connect all the vertices in the order they are presented in the file, so you will have some unexpected extra lines that jump across the model in some places. You could use GL_LINES instead, but then you'll have a bunch of missing line segments.

OTHER TIPS

You can also use shader to set primitive type and then supply it to modelBatch instance:

    modelBatch = new ModelBatch(new DefaultShaderProvider() {
        @Override
        protected Shader createShader(Renderable renderable) {
            return new WireframeShader(renderable, config);
        }
    });

WireframeShader.java:

public class WireframeShader extends DefaultShader {

    public static final int PRIMITIVE_TYPE = GL20.GL_LINE_STRIP;
    private int mSavedPrimitiveType;

    public WireframeShader(Renderable renderable) {
        super(renderable);
    }

    public WireframeShader(Renderable renderable, Config config) {
        super(renderable, config);
    }

    public WireframeShader(Renderable renderable, Config config, String prefix) {
        super(renderable, config, prefix);
    }

    public WireframeShader(Renderable renderable, Config config, String prefix, String vertexShader, String fragmentShader) {
        super(renderable, config, prefix, vertexShader, fragmentShader);
    }

    public WireframeShader(Renderable renderable, Config config, ShaderProgram shaderProgram) {
        super(renderable, config, shaderProgram);
    }

    @Override
    public void render(Renderable renderable) {
        setPrimitiveType(renderable);
        super.render(renderable);
        restorePrimitiveType(renderable);
    }

    @Override
    public void render(Renderable renderable, Attributes combinedAttributes) {
        setPrimitiveType(renderable);
        super.render(renderable, combinedAttributes);
        restorePrimitiveType(renderable);
    }

    private void restorePrimitiveType(Renderable renderable) {
        renderable.primitiveType = mSavedPrimitiveType; // gdxVersion = '1.6.4'

        //consider using the following for newer gdx versions instead as per kami comment:
        //renderable.meshPart.primitiveType = mSavedPrimitiveType

    }

    private void setPrimitiveType(Renderable renderable) {
        mSavedPrimitiveType = renderable.primitiveType; //gdxVersion = '1.6.4'
        renderable.primitiveType = PRIMITIVE_TYPE; //gdxVersion = '1.6.4'


        //consider using the following for newer gdx versions instead as per kami comment:
        //mSavedPrimitiveType = renderable.meshPart.primitiveType;
        //renderable.meshPart.primitiveType = PRIMITIVE_TYPE;

    }
}

This will render models using lines instead of filled triangles

        modelBatch.begin(EnvironmentWrapper.single().getCamera());
        modelBatch.render(renderables);
        modelBatch.end();
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top