1
votes

i am working on a program which draws polygons according to user inputs. I have problems with drawing triangles using GL_TRIANGLE. I used the same code below to draw square and it worked well. Hovewer, if i want to draw only one triangle it does not work.

Can anyone help me?

public class Triangle extends Shape{

private FloatBuffer vertexBuffer;
private FloatBuffer _colorBuffer;
private ShortBuffer indexBuffer;

private float vertices[] = {
        -0.5f, -0.5f, 0.5f, // 0
           0.5f, -0.5f, 0.5f, // 1
           0f, -0.5f, -0.5f, // 2

    }; 

private short[] indices = { 0, 2, 1 };

float[] colors = {1f, 1f, 0f, 1f };



public Triangle() {

    ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length * 4);
    vbb.order(ByteOrder.nativeOrder());
    vertexBuffer = vbb.asFloatBuffer();
    vertexBuffer.put(vertices);
    vertexBuffer.position(0);


    ByteBuffer ibb = ByteBuffer.allocateDirect(indices.length * 2);
    ibb.order(ByteOrder.nativeOrder());
    indexBuffer = ibb.asShortBuffer();
    indexBuffer.put(indices);
    indexBuffer.position(0);

    ByteBuffer cbb = ByteBuffer.allocateDirect(colors.length * 4);
    cbb.order(ByteOrder.nativeOrder());
    _colorBuffer = cbb.asFloatBuffer();
    _colorBuffer.put(colors);
    _colorBuffer.position(0);
}


public void draw(GL10 gl) {

    gl.glFrontFace(GL10.GL_CCW); 
    gl.glEnable(GL10.GL_CULL_FACE); 
    gl.glCullFace(GL10.GL_BACK); 


    gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
            gl.glEnableClientState(GL10.GL_COLOR_ARRAY);

    gl.glVertexPointer(3, GL10.GL_FLOAT, 0,  vertexBuffer);
    gl.glColorPointer(4, GL10.GL_FLOAT, 0, _colorBuffer);
    gl.glDrawElements(GL10.GL_TRIANGLES, indices.length,GL10.GL_UNSIGNED_SHORT, indexBuffer);

    gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
    gl.glDisable(GL10.GL_CULL_FACE); 
}

}

edit:

i call my Triangle class from here, maybe i have made mistake here

public class OpenGLRenderer implements Renderer { String name; ArrayList myArr ; private float angle, x,y,z;

public OpenGLRenderer(String nm ) {
      name =nm;
      myArr = new ArrayList<Shape>();
     x=0;
    y=0;
    z=-3;

}


@Override
public void onDrawFrame(GL10 gl) {
    //clear the screen and depth buffer

    gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
    gl.glLoadIdentity();

    gl.glTranslatef(x, y, z);

     for (Shape t : myArr)
     {
         if (t instanceof Rectangle)
     { 
            // gl.glTranslatef(0, 0, -4);

             ((Rectangle )t).draw(gl);
             }
         if (t instanceof Square)
         { //gl.glTranslatef(0, 1, 0);
             ((Square )t).draw(gl);}
         if (t instanceof Pyramid){
             ((Pyramid)t).draw(gl);

        if (t instanceof Triangle){
            ((Triangle)t).draw(gl);

        }
        if (t instanceof Line){
            ((Line)t).draw(gl);
        }
         }

     }//for

}

public String getName() {
    return name;
}


public void setName(String name) {
    this.name = name;
}


@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {


    gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
    gl.glEnableClientState(GL10.GL_COLOR_ARRAY);

    gl.glViewport(0, 0, width, height);
    gl.glMatrixMode(GL10.GL_PROJECTION);
    gl.glLoadIdentity(); //reset the projection matrix
    GLU.gluPerspective(gl, 45.0f, (float)width/(float)height,
            0.1f, 100.0f); //calculate the aspect ratio of window
    gl.glMatrixMode(GL10.GL_MODELVIEW);
    gl.glLoadIdentity();


}

@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
    //set the bg as black
    gl.glClearColor(0.0f, 0.0f, 0.0f, 0.5f);
    gl.glShadeModel(GL10.GL_SMOOTH);
    //depth buffer setup
    gl.glClearDepthf(1.0f);
    gl.glEnable(GL10.GL_DEPTH_TEST);
    gl.glDepthFunc(GL10.GL_LEQUAL);
    gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST); 


}

public void addshape(Shape s) {y=y+0.1f; myArr.add(s); } }

3
maybe to do with the way you are drawing it. try disabling the face culling and see if anything shows then? - Martyn
I checked my vertices and it looks right to me. - p.berna
I already disabled the face culling but nothing changed - p.berna
Don't forget to disableClientState on your color array also. Doubt that's the issue, but it's good practice for sure. - Geobits

3 Answers

1
votes

It looks to me like you don't have enough colors in your colors array. This might result in an invisible triangle depending on the initial garbage values in your _colorBuffer.

(Edit) try:

float[] colors = {
    1f, 1f, 0f, 1f,
    1f, 1f, 0f, 1f,
    1f, 1f, 0f, 1f
};
0
votes

First, Martin is correct about the colors array. It needs to have a color (4 values in your case) for every vertex (so 12 values at all).

Next, at the moment your triangle lies inside the x-z-plane and as you don't make any changes to the modelview matrix (except translating along the z-axis), you should just see a line, if any, (think of a sheet of paper viewed from the side).

But your real problem is your draw loop. I guess you're not only new to OpenGL, but also to Java and object oriented programming in general. This whole design is complete rubbish. That's what virtual functions are for in object oriented code. Just let each shape implement its correct draw method. So the only thing you need to do is

for (Shape t : myArr)
    t.draw(gl);

Given that Shape has an abstract draw method, that the other subclasses implement. But this is more of a design flaw. The actual error is, that the braces of the ifs are broken. At the moment the triangle is only drawn, if t is an instance of Pyramid and of Triangle, so draw is never called for triangles (and also for lines).

0
votes

here my triangle code from a project which works. Looks like your indices and colour arrays are different

package com.martynhaigh.Vortex;

import android.view.animation.Transformation;

import javax.microedition.khronos.opengles.GL10;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.ShortBuffer;

public class Triangle {

    private ShortBuffer _indexBuffer;
    private FloatBuffer _vertexBuffer;
    private FloatBuffer _colorBuffer;
    static float _xAngle, _yAngle;
    private int _nrOfVertices; 

    Triangle() {
        float[] coords = {
                -0.5f, -0.5f, 0f, // (x1, y1, z1)
                0.5f, -0.5f, 0f, // (x2, y2, z2)
                0f, 0.5f, 0f // (x3, y3, z3)
        }; // 9

        _nrOfVertices = coords.length / 3;

        float[] colors = {
                1f, 0f, 0f, 1f, // point 1
                0f, 1f, 0f, 1f, // point 2
                0f, 0f, 1f, 1f // point 3
        }; // 12

        short[] indices = {0, 1, 2}; // 3

        // float has 4 bytes, coordinate * 4 bytes
        ByteBuffer vbb = ByteBuffer.allocateDirect(coords.length * 4); //36
        vbb.order(ByteOrder.nativeOrder());
        _vertexBuffer = vbb.asFloatBuffer();

        // short has 2 bytes, indices * 2 bytes
        ByteBuffer ibb = ByteBuffer.allocateDirect(indices.length * 2); // 6
        ibb.order(ByteOrder.nativeOrder());
        _indexBuffer = ibb.asShortBuffer();

        // float has 4 bytes, colors (RGBA) * 4 bytes
        ByteBuffer cbb = ByteBuffer.allocateDirect(colors.length * 4); // 48
        cbb.order(ByteOrder.nativeOrder());
        _colorBuffer = cbb.asFloatBuffer();

        _vertexBuffer.put(coords);
        _indexBuffer.put(indices);
        _colorBuffer.put(colors);

        _vertexBuffer.position(0);
        _indexBuffer.position(0);
        _colorBuffer.position(0);
    }

    public void onDraw(GL10 gl) {
        // set rotation
        gl.glRotatef(_xAngle, 1f, 0f, 0f);
        gl.glRotatef(_yAngle, 0f, 1f, 0f);

        // set the color of our element
        //gl.glColor4f(0.5f, 0f, 0f, 0.5f);
        gl.glColorPointer(4, GL10.GL_FLOAT, 0, _colorBuffer);

        // define the vertices we want to draw
        gl.glVertexPointer(3, GL10.GL_FLOAT, 0, _vertexBuffer);

        // finally draw the vertices
        gl.glDrawElements(GL10.GL_TRIANGLES, _nrOfVertices, GL10.GL_UNSIGNED_SHORT, _indexBuffer);   
    }

    public void setXAngle(float angle) {
        _xAngle = angle;
    }

    public float getXAngle() {
        return _xAngle;
    }

    public void setYAngle(float angle) {
        _yAngle = angle;
    }

    public float getYAngle() {
        return _yAngle;
    }
}