update object buffer with ATI VAO

How do I create/render more then one array object ?

more specifically, I created my array buffer by passing null to NewObjectBufferATI
and called glUpdateObjectBufferATI with my new data to create some array objects.

The problem is I dont understand how to call glDrawElementsArrayATI(). Can someone point to a good tutorial ?

this page: http://www.ati.com/developer/ATIVertexArrayObject.pdf does not explain how to draw more then one array object in the array buffer.

Unfortunately I seem to have done something wrong, and sometimes my program runs fine, sometimes it draws random triangles, and somtimes it does a mutli-color snow crash requiring a reboot!

Thanks,

Nitzan

I think you’re confusing glDrawElementsArrayATI ( part of the ATI_element_array extension ) and the ATI_vertex_array_object extension. In the later, you just setup your pointers using the glArrayObjectATI function, instead of the standard glXXXPointer functions; and you render with a normal glDrawElements call.

The specification is your best friend to understand the in & outs of this extension: http://oss.sgi.com/projects/ogl-sample/registry/ATI/vertex_array_object.txt

I’m not really sure to understand your question about having more than one array object. Why would you need more than one VAO at the same time ? What do you want to do ?

Here’s an example of setting up the pointers for vertex pos, tex coord 0 and normals:

struct s_vertex
{
float pos[3];
float normal[3];
float tex0[2];
};

glEnableClientState(GL_VERTEX_ARRAY);
glArrayObjectATI(GL_VERTEX_ARRAY, 3, GL_FLOAT, sizeof(s_vertex), m_vao, 0);
glEnableClientState(GL_NORMAL_ARRAY);
glArrayObjectATI(GL_NORMAL_ARRAY, 3, GL_FLOAT, sizeof(s_vertex), m_vao, sizeof(float) * 3);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glArrayObjectATI(GL_TEXTURE_COORD_ARRAY, 2, GL_FLOAT, sizeof(s_vertex), m_vao, sizeof(float) * (3 + 3));

glDrawElements(…)

glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);

Y.

[This message has been edited by Ysaneya (edited 12-11-2002).]

How can I render more then one object with one VAO ? Lets say I have two textured cubes, each one textured with a different texture. How do I draw both of them using vao’s ?

I tried creating a vao for each one (m_vao and m_vao2):

glArrayObjectATI(GL_VERTEX_ARRAY, 3, GL_FLOAT, sizeof(s_vertex), m_vao, 0);
glArrayObjectATI(GL_NORMAL_ARRAY, 3, GL_FLOAT, sizeof(s_vertex), m_vao, sizeof(float) * 3);
glArrayObjectATI(GL_TEXTURE_COORD_ARRAY, 2, GL_FLOAT, sizeof(s_vertex), m_vao, sizeof(float) * (3 + 3));
glDrawElements(…)

and

glArrayObjectATI(GL_VERTEX_ARRAY, 3, GL_FLOAT, sizeof(s_vertex), m_vao2, 0);
glArrayObjectATI(GL_NORMAL_ARRAY, 3, GL_FLOAT, sizeof(s_vertex), m_vao2, sizeof(float) * 3);
glArrayObjectATI(GL_TEXTURE_COORD_ARRAY, 2, GL_FLOAT, sizeof(s_vertex), m_vao2, sizeof(float) * (3 + 3));
glDrawElements(…)

But my program crashes. I figured it crashed becuase I need to pack the VAO’s into an Object buffer, like it says here: http://www.ati.com/developer/ATIVertexArrayObject.pdf

Do I not need to do this ?

Nitzan

Here’s the function I use for building a VAO for my 3DS models:

void TDS_BuildVAO(TDS_Model_t *Model)
{
int i, j;

for(i=0;iNumMesh;i++)
{
int index=0;
float *data=NULL;

  Model->Mesh[i].VAOID=glNewObjectBufferATI(sizeof(float)*Model->Mesh[i].NumVertex*14, NULL, GL_DYNAMIC_ATI);

  if(HasMOB)
  	data=(float *)glMapObjectBufferATI(Model->Mesh[i].VAOID);
  else
  	data=(float *)malloc(sizeof(float)*Model->Mesh[i].NumVertex*14);

  if(data==NULL)
  {
  	char temp[1024];

  	sprintf(temp, "VAO data buffer memory allocate/map failed for object: %s", Model->Mesh[i].Name);
  	MessageBox(NULL, temp, "OpenGL", MB_OK);

  	glFreeObjectBufferATI(Model->Mesh[i].VAOID);
  	Model->Mesh[i].VAOID=0;

  	break;
  }

  for(j=0;j<Model->Mesh[i].NumVertex;j++)
  {
  	data[index++]=Model->Mesh[i].Vertex[3*j];
  	data[index++]=Model->Mesh[i].Vertex[3*j+1];
  	data[index++]=Model->Mesh[i].Vertex[3*j+2];

  	data[index++]=Model->Mesh[i].UV[2*j];
  	data[index++]=Model->Mesh[i].UV[2*j+1];

  	data[index++]=Model->Mesh[i].Tangent[3*j];
  	data[index++]=Model->Mesh[i].Tangent[3*j+1];
  	data[index++]=Model->Mesh[i].Tangent[3*j+2];

  	data[index++]=Model->Mesh[i].Binormal[3*j];
  	data[index++]=Model->Mesh[i].Binormal[3*j+1];
  	data[index++]=Model->Mesh[i].Binormal[3*j+2];

  	data[index++]=Model->Mesh[i].Normal[3*j];
  	data[index++]=Model->Mesh[i].Normal[3*j+1];
  	data[index++]=Model->Mesh[i].Normal[3*j+2];
  }

  if(HasMOB)
  	glUnmapObjectBufferATI(Model->Mesh[i].VAOID);
  else
  {
  	glUpdateObjectBufferATI(Model->Mesh[i].VAOID, 0, sizeof(float)*index, data, GL_DISCARD_ATI);
  	FREE(data);
  }

}
}

And then I use this to render:

void TDS_DrawModel(TDS_Model_t *Model)
{
int i;

glColor3f(1.0f, 1.0f, 1.0f);

for(i=0;iNumMesh;i++)
{
int index=Model->Mesh[i].MaterialIndex;

  if(index>=Model->NumMaterial)
  {
  	glProgramEnvParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 1, Kd[0], Kd[1], Kd[2], 0.0f);
  	glProgramEnvParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 2, Ks[0], Ks[1], Ks[2], SpecularExpoent);
  	glProgramEnvParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 3, Ka[0], Ka[1], Ka[2], 0.0f);
  }
  else
  {
  	glProgramEnvParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 1, Model->Material[index].Diffuse[0], Model->Material[index].Diffuse[1], Model->Material[index].Diffuse[2], 0.0f);
  	glProgramEnvParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 2, Model->Material[index].Specular[0], Model->Material[index].Specular[1], Model->Material[index].Specular[2], Model->Material[index].Shininess*100.0f);
  	glProgramEnvParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 3, Model->Material[index].Ambient[0], Model->Material[index].Ambient[1], Model->Material[index].Ambient[2], 0.0f);

  	if(Model->Material[index].BaseTexID!=0)
  	{
  		glActiveTextureARB(GL_TEXTURE0_ARB);
  		glBindTexture(GL_TEXTURE_2D, Model->Material[index].BaseTexID);
  	}

  	if(Model->Material[index].BumpTexID!=0)
  	{
  		glActiveTextureARB(GL_TEXTURE1_ARB);
  		glBindTexture(GL_TEXTURE_2D, Model->Material[index].BumpTexID);
  	}
  }

  if(HasVAO&&Model->Mesh[i].VAOID)
  {
  	glArrayObjectATI(GL_VERTEX_ARRAY, 3, GL_FLOAT, sizeof(float)*14, Model->Mesh[i].VAOID, 0);
  	glEnableClientState(GL_VERTEX_ARRAY);

  	glClientActiveTextureARB(GL_TEXTURE0_ARB);
  	glArrayObjectATI(GL_TEXTURE_COORD_ARRAY, 2, GL_FLOAT, sizeof(float)*14, Model->Mesh[i].VAOID, sizeof(float)*3);
  	glEnableClientState(GL_TEXTURE_COORD_ARRAY);

  	glClientActiveTextureARB(GL_TEXTURE1_ARB);
  	glArrayObjectATI(GL_TEXTURE_COORD_ARRAY, 3, GL_FLOAT, sizeof(float)*14, Model->Mesh[i].VAOID, sizeof(float)*5);
  	glEnableClientState(GL_TEXTURE_COORD_ARRAY);

  	glClientActiveTextureARB(GL_TEXTURE2_ARB);
  	glArrayObjectATI(GL_TEXTURE_COORD_ARRAY, 3, GL_FLOAT, sizeof(float)*14, Model->Mesh[i].VAOID, sizeof(float)*8);
  	glEnableClientState(GL_TEXTURE_COORD_ARRAY);

  	glArrayObjectATI(GL_NORMAL_ARRAY, 3, GL_FLOAT, sizeof(float)*14, Model->Mesh[i].VAOID, sizeof(float)*11);
  	glEnableClientState(GL_NORMAL_ARRAY);
  }
  else
  {
  	glVertexPointer(3, GL_FLOAT, 0, Model->Mesh[i].Vertex);
  	glEnableClientState(GL_VERTEX_ARRAY);

  	glClientActiveTextureARB(GL_TEXTURE0_ARB);
  	glTexCoordPointer(2, GL_FLOAT, 0, Model->Mesh[i].UV);
  	glEnableClientState(GL_TEXTURE_COORD_ARRAY);

  	glClientActiveTextureARB(GL_TEXTURE1_ARB);
  	glTexCoordPointer(3, GL_FLOAT, 0, Model->Mesh[i].Tangent);
  	glEnableClientState(GL_TEXTURE_COORD_ARRAY);

  	glClientActiveTextureARB(GL_TEXTURE2_ARB);
  	glTexCoordPointer(3, GL_FLOAT, 0, Model->Mesh[i].Binormal);
  	glEnableClientState(GL_TEXTURE_COORD_ARRAY);

  	glNormalPointer(GL_FLOAT, 0, Model->Mesh[i].Normal);
  	glEnableClientState(GL_NORMAL_ARRAY);
  }

  glDrawElements(GL_TRIANGLES, Model->Mesh[i].NumFace*3, GL_UNSIGNED_SHORT, Model->Mesh[i].Face);

  glClientActiveTextureARB(GL_TEXTURE2_ARB);
  glDisableClientState(GL_TEXTURE_COORD_ARRAY);

  glClientActiveTextureARB(GL_TEXTURE1_ARB);
  glDisableClientState(GL_TEXTURE_COORD_ARRAY);

  glClientActiveTextureARB(GL_TEXTURE0_ARB);
  glDisableClientState(GL_TEXTURE_COORD_ARRAY);

  glDisableClientState(GL_NORMAL_ARRAY);
  glDisableClientState(GL_VERTEX_ARRAY);

}

glActiveTextureARB(GL_TEXTURE0_ARB);
}

HasVAO is a bool that tells the function weather or not the extension is supported, same with HasMOB only for the ATI_map_object_buffer extension. Everything else should be easy enough to figure out.

I create one object buffer per mesh in the model (one VAO ID per mesh).