glDrawElements with TRIANGLE_STRIP

classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

glDrawElements with TRIANGLE_STRIP

millerni456
This post was updated on .
Problem Solved: Skip to last post for answer.


Hello, I was working with glDrawElements and seem to have run into a problem and I was looking for assistance.
It would also help to clear things up on glDrawElements, because I haven't found a solid definition out there yet.

glDrawElements takes these parameters as far as I know.....

the mode (GL_TRAIGLE_STRIP),

the number of indices

the size in bytes of the indices

and the index buffer.

So, when I fill in the paramters I don't quite get want I expect.
Im looking to create a sort of truncated cone that looks like this. (looking down z axis).

Image of the shape.

Here's how I set up my vertices:

Note that the height and radius are specified by the program.
RadialX and Z is talking about coordinate locations. (Distance along those axes).
Also the loop iterates 20 times incrementing the angle by 18 degrees per iteration. (Thus a whole circle).
Since I'm making a triangle strip, the vertices alternate from the bottom of the cone to the top.

float[] data = new float[120]; //20 vertices on top and bottom, * 3 per xyz component.
               
                double h1 = .333 * height;
                                         
                int k = 0;
                for(int i = 0; i<data.length; i+=6)//iterates 20 times.
                {
                        double cos = Math.cos(Math.toRadians(k*18));
                        double sin = Math.sin(Math.toRadians(k*18));
                        System.out.println(k*18);
                        double radialX = radius * cos;//-1 to 1
                        double radialZ = radius * sin;//-1 to 1
                        System.out.println(k*36);
                       
                        /**BOTTOM or cylinder**/
                        //gl.glTexCoord2d(1, 1);
                        data[i] = (float) (radialX * .5);
                        data[i+1] = (float) (h1);
                        data[i+2] = (float) (radialZ * .5);
                       
                        /**TOP of ylinder**/
                        //gl.glTexCoord2d(1, 0);
                        data[i+3] = (float) (radialX);
                        data[i+4] = (float) (height);
                        data[i+5] = (float) (radialZ);
                        k++;
                }

So this should set up the vertices correctly (which it does, I've tested with GL_POINTS).
Reply | Threaded
Open this post in threaded view
|

Re: glDrawElements with TRIANGLE_STRIP

millerni456
The next step is to set up my indices:

short[] indices = new short[vertices.length/3]; //vertices is actually 3 * the number of vertices because each vertex has xyz components. So this should be the equivalent to the number of triangles times 3 for each point.

                int k = 0; //aids in specifying indices.
                for(int i = 0; i<indices.length-1; i+=3)
                {
                        indices[i] = (short)k;
                        indices[i+1] = (short) (k+1);
                        indices[i+2] = (short) (k+2);
                        k++;
                }

This simple loop should place similar values into a short array:
{0, 1, 2,       1, 2, 3,         2, 3, 4             3, 4, 5,        4, 5, 6,         5, 6, 7.....}
And do this until it reaches the end of the number of vertices. This is also the same order
for triangle strip:

http://www.codesampler.com/d3dbook/chapter_05/chapter_05_files/image007.jpg

So I load my buffers like such:
Note that vertexBuffer is a FloatBuffer and that indexBuffer is a ShortBuffer.

//create buffers.
ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length * 4);
vbb.order(ByteOrder.nativeOrder());
vertexBuffer = vbb.asFloatBuffer();
               
ByteBuffer ibb = ByteBuffer.allocateDirect(vertices.length/3 * 2);
ibb.order(ByteOrder.nativeOrder());
ndexBuffer = ibb.asShortBuffer();

//fill them
vertexBuffer.put(vertices); //this uses the data from earlier
vertexBuffer.position(0);  

indexBuffer.put(indices); //this also uses the data from earlier
indexBuffer.position(0);

____________________________________________________________________________
So all set up code is done. Now I have to draw them:
this uses the buffers and data mentioned above.
GL10 because this is for android. (This is a GLES)
Also am using UNSIGNED_SHORT because I have a short array for indices.

gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
                 
                 // Point to our vertex buffer
                 gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
               
                 // Draw the vertices as triangle strip
                 gl.glDrawElements(GL10.GL_TRIANGLE_STRIP, indices.length, GL10.GL_UNSIGNED_SHORT, indexBuffer);
                         
                 //Disable the client state before leaving
 gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);


So I should get truncated cone that is 3D, without any cuts (meaning that the cone makes a complete circle).
The top and bottom should be empty but the walls of the cone should appear. At least that's what I thought. For some reason not even half of the cone is rendering.

Any help is greatly appreciated, sorry if this is confusing. I was trying to say all there was fast and concise.
Let me know if you have any questions.

-Nick.
Reply | Threaded
Open this post in threaded view
|

Re: glDrawElements with TRIANGLE_STRIP

gouessej
Administrator
Hi

You should rather use the class Buffers to create your buffers, it is less error prone than doing almost the same thing with your own code. Best regards.
Julien Gouesse | Personal blog | Website
Reply | Threaded
Open this post in threaded view
|

Re: glDrawElements with TRIANGLE_STRIP

millerni456
Unfortunately I am unsure what you mean by this.
When I switch to the "Buffer" object, I can no longer fill it with data.

So I tried switching to "ByteBuffer" to fill them as such:

for(int i = 0; i<vertices.length; i++)
{
    vertexBuffer.put( (byte) vertices[i] ); //casts the float vertex to a byte.
}

However, my geometry will not render at all if I do this.
Reply | Threaded
Open this post in threaded view
|

Re: glDrawElements with TRIANGLE_STRIP

millerni456
So... I've had some good luck.

First I changed it to use VBO's

which means in the  glVertexPoint() and glDrawElements() the last parameters were changed to 0 because the buffers were bound by the VBO.

Also I had to change my index loop something like this:

for(int i = 0; i<indices.length; i++)
{
     indices[i] = (short) i; //0, 1, 2, 3, 4, 5, 6, 7....37, 38, 39, 40.
}

Event though I changed this, first off the the logic behind the indices doesn't make sense. Also when rendering, I'm missing 1-2 triangles in the strip. So it is not a closed figure. (I tried tinkering with the indices.length and have not solved the problem).

Any help again is greatly appreciated.
Reply | Threaded
Open this post in threaded view
|

Re: glDrawElements with TRIANGLE_STRIP

millerni456
Problem solved!

It was a logic error:
I was not creating enough vertices/indices to make the triangle strip loop. I only created enough vertices to go to the 20th points (on the top and bottom). But in fact I needed to reconnect this to the 1st vertex.

Indices and Vertices make much more sense now ;)