You know there will be more normals than points right? And you know that you cannot simply use the same point indices for normal indices right? This just exapands everything out to use a flattened array of data and then glDrawArrays. If you wish to use glDrawElements, then you will have to generate entirely new data arrays and new indices for the vertices.
void Obj::rearrangeData(vector<float>& outputVertexBuffer)
{
for (int i = 0; i < faces.size(); i++) {
for (int j = 0; j < 3; j++) {
int iP = ((ObjFace)faces[i]).v[j].indexP - 1;
int iN = ((ObjFace)faces[i]).v[j].indexN - 1;
int iUV = ((ObjFace)faces[i]).v[j].indexUV - 1;
outputVertexBuffer.push_back( pos[ iP*3 + 0 ] );
outputVertexBuffer.push_back( pos[ iP*3 + 1 ] );
outputVertexBuffer.push_back( pos[ iP*3 + 2 ] );
outputVertexBuffer.push_back( normal[ iN*3 + 0 ] );
outputVertexBuffer.push_back( normal[ iN*3 + 1 ] );
outputVertexBuffer.push_back( normal[ iN*3 + 2 ] );
outputVertexBuffer.push_back( uv[ iUV*2 + 0 ] );
outputVertexBuffer.push_back( uv[ iUV*2 + 1 ] );
}
}
}
Obj someObj;
// load stuff
vector<float> outputVertexBuffer
Obj.rearrangeData(outputVertexBuffer);
glVertexPointer(3,GL_FLOAT,8*sizeof(float),&(outputVertexBuffer[0]));
glNormalPointer(GL_FLOAT,8*sizeof(float),&(outputVertexBuffer[3]));
glTexCoordPointer(2,GL_FLOAT,8*sizeof(float),&(outputVertexBuffer[6]));
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glDrawArrays(GL_TRIANGLES,0,outputVertexBuffer.size()/8);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
To do an indexed set of elems you’ll have to generate the new indices, ie :
struct VInf
{
int n;
int t;
int index;
VInf(int _n,int _t,int _index) : n(_n), t(_t), index(_index) {}
VInf(const VInf& vi) : n(vi.n), t(vi.t), index(vi.index) {}
};
typedef std::vector<VInf> VInfArray;
class VInfMap : public std::vector<VInfArray>
{
int maxindex;
public:
VInfMap() : std::vector<VInfArray>(), maxindex(0) {}
int insert_elem(int v,int n,int t)
{
VInfArray& element_info = (*this)[v];
for(int i=0;i!=element_info.size();++i)
{
if( n == element_info[i].n && t == element_info[i].t )
{
return element_info[i].index;
}
}
element_info.push_back( VInf(n,t,maxindex) );
return maxindex++;
}
}
void Obj::rearrangeData(vector<float>& outputVertexBuffer,vector<int>& outputIndexBuffer)
{
VInfMap temp;
outputIndexBuffer.resize( faces.size()*3 );
temp.resize(pos.size()/3);
vector<int>::iterator index = outputIndexBuffer.begin();
for (int i = 0; i < faces.size(); i++) {
for (int j = 0; j < 3; j++) {
int iP = ((ObjFace)faces[i]).v[j].indexP - 1;
int iN = ((ObjFace)faces[i]).v[j].indexN - 1;
int iUV = ((ObjFace)faces[i]).v[j].indexUV - 1;
*index = temp.insert_elem( iP, iN, iUV );
if((*index)>=(outputVertexBuffer.size()/8))
{
outputVertexBuffer.push_back( pos[ iP*3 + 0 ] );
outputVertexBuffer.push_back( pos[ iP*3 + 1 ] );
outputVertexBuffer.push_back( pos[ iP*3 + 2 ] );
outputVertexBuffer.push_back( normal[ iN*3 + 0 ] );
outputVertexBuffer.push_back( normal[ iN*3 + 1 ] );
outputVertexBuffer.push_back( normal[ iN*3 + 2 ] );
outputVertexBuffer.push_back( uv[ iUV*2 + 0 ] );
outputVertexBuffer.push_back( uv[ iUV*2 + 1 ] );
}
}
}
}
Obj someObj;
// load stuff
vector<float> outputVertexBuffer
vector<int> outputIndexBuffer
Obj.rearrangeData(outputVertexBuffer,outputIndexBuffer);
glVertexPointer(3,GL_FLOAT,8*sizeof(float),&(outputVertexBuffer[0]));
glNormalPointer(GL_FLOAT,8*sizeof(float),&(outputVertexBuffer[3]));
glTexCoordPointer(2,GL_FLOAT,8*sizeof(float),&(outputVertexBuffer[6]));
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glDrawElements(GL_TRIANGLES,0,outputIndexBuffer.size()/3,&(outputIndexBuffer[0]));
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);