PDA

View Full Version : Triangle Strip!



Golgoth
03-06-2006, 06:28 AM
Hi all!

Anyone know a good tutorial on triangle strip?

thx

jide
03-06-2006, 06:32 AM
http://www.codercorner.com/Strips.htm

Just google.

Golgoth
03-06-2006, 09:48 AM
thx for your post jide,

actualy, ill be interested in how the strips are pass to glDrawElements... one call per strip?

thx

jide
03-06-2006, 10:31 AM
one call per strip array.

Golgoth
03-06-2006, 09:44 PM
thx jide!

i m running into a wall with VOB maybe u can help me figure this out!

the way i proceed is that i pass to the renderer one primtive at the time... a primitive has one or many meshes... one mesh per strip array... the primtives hold the client pointers and the meshes hold the arrays... the thing is... for a single triangle... i create a mesh with one triangle and use GL_TRIANGLES instead of GL_TRIANGLE_STRIP... so im not sure i can do this... considering that each primitive has to shared one vob throught its meshes. so far it works without vob perfecly... and does work with vob but theres is some extra artefacts in the geometry... i must be really close... heres the code:


void OpenGL::Draw(Primitive *in_primitive)
{
Mesh *l_mesh = NULL;

GLuint l_offsetCount = 0;
GLuint l_offsetSize = 0;
GLuint l_count = 0;
GLuint l_size = 0;

GLuint l_maxSize = in_primitive->GetVertexCount() * sizeof(Vector3);

for (Int i = 0; i < in_primitive->GetMeshCount(); ++i)
{
l_mesh = in_primitive->GetMesh(i);

if (l_mesh == NULL)
continue;

const GLvoid *l_index = NULL;
GLenum &amp;l_type = gl_RenderType[l_mesh->GetRenderType()];

switch (l_type)
{
case (GL_TRIANGLES):
{
l_count = l_mesh->GetFaceCount();
l_size = l_mesh->GetFaceCount() * sizeof(Vector3);
l_index = l_mesh->GetFace();
break;
}

SNIP....
case (GL_TRIANGLE_STRIP):
{
l_count = l_mesh->GetIndexCount();
l_size = l_mesh->GetIndexCount() * sizeof(Int);
l_index = l_mesh->GetIndex();
break;
}
}

if (IsExtension(EXT_VERTEX_OBJECT_BUFFER))
{
GLuint &amp;l_buffer = in_primitive->GetBufferElement();

if (l_buffer == 0 &amp;&amp; i == 0)
glGenBuffers((GLsizei)1, &amp;l_buffer);

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, l_buffer);

if (in_primitive->IsResetBuffer())
{
if (i == 0)
glBufferData(GL_ELEMENT_ARRAY_BUFFER, l_maxSize, NULL, GL_DYNAMIC_DRAW);

glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, l_offsetSize, l_size, l_index);
}

glDrawRangeElements(l_type, l_offsetCount, l_count, l_size, GL_UNSIGNED_INT, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

l_offsetCount += l_count;
l_offsetSize += l_size;
}
else
glDrawRangeElements(l_type, 0, l_size, l_size, GL_UNSIGNED_INT, l_index);
}

if (IsExtension(EXT_VERTEX_OBJECT_BUFFER))
{
if (in_primitive->IsResetBuffer())
in_primitive->SetResetBufferEnable(false);

}
}this should probably be post in the advance section... however, it may be easy to fix!

maybe i should consider one VOB per mesh?

thx a bunch!

jide
03-07-2006, 02:52 AM
First of all, what is a VOB ? Do you mean VBO (Vertex Buffer Object) ? As far as I can remember it is an ARB extension now, not an EXT.

Second, a primitive is generally a triangle, a quad and so on.

Third, a VBO as its name says is a buffer, so you don't need to create a VBO each time you render, just once at start, then send the data each time they change if you use dynamic data, or just once if you use static data. the problem with what you're doing, if I understand your code correctly (and since I don't have the whole code), is that you create VBO for each new frame but never delete them, so you might fall with too much VBO created quiete quickly.

Fourth, I can't see any glVertexPointer at all. They are crucial whether you use VBO or just simple vertex arrays. Maybe you need more information about how vertex arrays work ?

I can't say more for the moment.

Golgoth
03-07-2006, 07:04 AM
Yes, you are absolutly right! its VBO not VOB! to use the right termes, in this case, it would be a EBO... for Element Object Buffer!

let me clean up some confusions...
the reason i did not post client states its because they are handled in a previous function... its better for versatility in my pipepline:


so you don't need to create a VBO each time you render, just once at start, then send the data each time they change if you use dynamic dataI ll make a simplified version of the loop:

first, all primitives are initialised with:

- in_primitive->IsResetBuffer() = true; <---- if true, set/reset buffer.

- in_primitive->GetBufferElement() = 0; <---- if 0, generate buffer.


now take a closer look and you will see that the buffer is generated only once:


for (Int i = 0; i < in_primitive->GetMeshCount(); ++i)
{
if (l_buffer == 0 &amp;&amp; i == 0)
glGenBuffers((GLsizei)1, &amp;l_buffer);

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, l_buffer);

if (in_primitive->IsResetBuffer())
{
if (i == 0)
glBufferData(GL_ELEMENT_ARRAY_BUFFER, l_maxSize, NULL, GL_DYNAMIC_DRAW);

glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, l_offsetSize, l_size, l_index);
}

glDrawRangeElements(l_type, l_offsetCount, l_offsetCount + l_count, l_maxSize, GL_UNSIGNED_INT, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}

if (in_primitive->IsResetBuffer())
in_primitive->SetResetBufferEnable(false);those thing cleared up... my problem here stands in having the right Count and Size Array pass to glBufferSubData and glDrawRangeElements... im pretty sure glBufferSubData is fine... it may be something in my calculations and/or glDrawRangeElements is not receiving the right data type/size...

hope it helps helping me!

jide
03-07-2006, 10:14 AM
Okay, didn't read your code correctly (I don't really like to read code from other people...).

From within glDrawRangeElements, anythings seem fine, but l_offsetCount which I don't know how it is calculated.

I also have several things I don't understand: why do you use index arrays if you use triangle strips ?
Also, putting all the arrays in the VBO should be best.

If things you've done work well without VBO, you must have done mistakes whether when calling BufferData/BufferSubData, IndexPointer or DrawRangeElements.

Hope that could help.

Golgoth
03-07-2006, 12:07 PM
thx for your time jide!


(I don't really like to read code from other people...)its a bit of ironic :)


why do you use index arrays if you use triangle strips ?my understanding of the Trip Strip index is that the last 2 vertices of a face are the first 2 vertices of the next face. exept for the first face:

to draw a strip with 2 faces you need only 4 indices, and for each subsequent face you add one index. right?

here is the revised version of the sequence:


void OpenGL::Draw(Primitive *in_primitive)
{
Mesh *l_mesh = NULL;
const GLvoid *l_index = NULL;

GLuint l_size;
GLuint l_count;
GLuint l_offsetCount = 0;
GLuint l_offsetSize = 0;

GLuint l_maxSize;
l_maxSize = in_primitive->GetQuadCount() * sizeof(Quad);
l_maxSize += in_primitive->GetFaceCount() * sizeof(Face);
l_maxSize += in_primitive->GetEdgeCount() * sizeof(Edge);
l_maxSize += in_primitive->GetIndexCount() * sizeof(Int);

for (Int i = 0; i < in_primitive->GetMeshCount(); ++i)
{
l_mesh = in_primitive->GetMesh(i);

if (l_mesh == NULL)
continue;

GLenum &amp;l_type = gl_RenderType[l_mesh->GetRenderType()];

switch (l_type)
{
case (GL_QUADS):
{
l_size = l_mesh->GetQuadCount() * sizeof(Quad);
l_count = l_mesh->GetQuadCount() * 4;
l_index = l_mesh->GetQuad();
break;
}
case (GL_TRIANGLES):
{
l_size = l_mesh->GetFaceCount() * sizeof(Face);
l_count = l_mesh->GetFaceCount() * 3;
l_index = l_mesh->GetFace();
break;
}
case (GL_TRIANGLE_STRIP):
{
l_size = l_mesh->GetIndexCount() * sizeof(Int);
l_count = l_mesh->GetIndexCount();
l_index = l_mesh->GetIndex();
break;
}
}

if (IsExtension(EXT_BUFFER_OBJECT))
{
GLuint &amp;l_buffer = in_primitive->GetBufferElement();

if (l_buffer == 0 &amp;&amp; i == 0)
glGenBuffers((GLsizei)1, &amp;l_buffer);

if (i == 0)
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, l_buffer);

if (in_primitive->IsResetBuffer())
{
if (i == 0)
glBufferData(GL_ELEMENT_ARRAY_BUFFER, l_maxSize, NULL, GL_DYNAMIC_DRAW);

glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, l_offsetSize, l_size, l_index);
}

glDrawRangeElements(l_type, l_offsetCount, l_offsetCount + l_count, l_size, GL_UNSIGNED_INT, NULL);

l_offsetCount += l_count;
l_offsetSize += l_size;
}
else
glDrawRangeElements(l_type, l_offsetCount, l_offsetCount + l_count, l_count, GL_UNSIGNED_INT, l_index);
}

if (IsExtension(EXT_BUFFER_OBJECT))
{
if (in_primitive->IsResetBuffer())
in_primitive->SetResetBufferEnable(false);

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}
}im working on it!

if anyone have a clue on what im doing wrong... and perhaps everything is fine... and i didnt read the xsi tristrip data carefully!

thx

jide
03-07-2006, 12:32 PM
What you might need to know is that triangle strips are generated like this:

v0,v1,v2 for the first triangle,
v2,v1,v3 for the second one,
v2,v3,v4 for the third one,
v4,v3,v5 for the fourth...

so one time over two GL is reversing two vertices.

I really don't know if the problem is there or elsewhere. Did you really ensure everything is drawing fine without VBO ?

Also can you show me how is looking an array of indices for a triangle strip mesh ? It really should look like this if I'm not wrong (since I never used indices with strips): 1,2,3,4,5,6,7...

Golgoth
03-07-2006, 01:00 PM
here is what i get from a grid with one subdivision in the dotxsi format!

http://www.hymedia.ca/ax6/temp/sc_030706_165230.JPG

here is the data:

- 2 faces
- 1 strip


SI_Mesh MSH-grid {
SI_Shape SHP-grid-ORG {
9, // vertex count
"POSITION",
-4.000000,0.000000,-4.000000,
-4.000000,0.000000,0.000000,
-4.000000,0.000000,4.000000,
0.000000,0.000000,-4.000000,
0.000000,0.000000,0.000000,
0.000000,0.000000,4.000000,
4.000000,0.000000,-4.000000,
4.000000,0.000000,0.000000,
4.000000,0.000000,4.000000,
}

SI_TriangleList grid {
2, // face count
0,4,3,
1,2,5,
}

SI_TriStripList grid {
SI_TriStrip {
10 // the xsi doc says vertices count here
0,1,4,
5
4
8
4
7
3
6
}
}with this, a create 1 primitive:
and this primitive has 2 meshes...
one for the Triangle list and another for the TriStrip list!

and yes it does look ok without vbo!

Golgoth
03-07-2006, 01:25 PM
I ve highlight the triangles:
http://www.hymedia.ca/ax6/temp/sc_030706_171600.jpg

looks like the start and the end of the strip is connecting...

Golgoth
03-07-2006, 02:47 PM
In the same fashion as the array pointer calls, if glDrawElements() or glDrawRangeElements() is called while a buffer object is bound to GL_ELEMENT_ARRAY_BUFFER_ARB, the indices argument to these calls is interpreted as an offset into the buffer object, rather than a pointer to index data in application memory. http://techpubs.sgi.com/library/tpl/cgi-..._html/ch07.html (http://techpubs.sgi.com/library/tpl/cgi-bin/getdoc.cgi?coll=0650&db=bks&srch=&fname=/SGI_Developer/OpenGLonSGI/sgi_html/ch07.html)

jide
03-08-2006, 03:18 AM
Sorry but I don't see what is the error. Check the offsets in your VBO. If everything is fine when not using VBO, the error is forcelly there. Also, ensure using the right types for specifying the offset (check the VBO extension for that).

Golgoth
03-08-2006, 06:14 AM
alright i nailed it down! tristrip is in the house!!!

thx again!