   Trouble using indexed VBOs
  As the title suggests, I'm having issues getting VBOs to work.  First, some code snippets.Setting up the VBO:void Model::add_triangles(std::vector<point3> new_vertices, std::vector<unsigned int> new_indexes){vertices.push_back(new_vertices);indexes.push_back(new_indexes);GLuint dummy;VBO_vertex_ids.push_back(dummy);VBO_index_ids.push_back(dummy);glGenBuffersARB(1, &VBO_vertex_ids.back());glGenBuffersARB(1, &VBO_index_ids.back());glBindBufferARB(GL_ARRAY_BUFFER_ARB, VBO_vertex_ids.back());glBufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(point3)*(vertices.back().size()), &vertices.back(), GL_STREAM_DRAW_ARB);glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, VBO_index_ids.back());glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, sizeof(unsigned int)*(indexes.back().size()), &indexes.back(), GL_STREAM_DRAW_ARB);glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);}Rendering:void Model::render_model(float r, float g, float b){for(int n = 0; n < indexes.size(); n++){glPushMatrix();// indexedglTranslatef(center.x, center.y, center.z);glColor3f(r, g, b);glEnableClientState(GL_VERTEX_ARRAY);glBindBufferARB(GL_ARRAY_BUFFER_ARB, VBO_vertex_ids[n]);glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, VBO_index_ids[n]);glVertexPointer(3, GL_FLOAT, 0, 0);glDrawElements(GL_TRIANGLES, indexes[n].size(), GL_UNSIGNED_INT, 0);glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);glDisableClientState(GL_VERTEX_ARRAY);glPopMatrix();}}What happens when I run this is that I get pieces of cubes rotating into and out of view.  Normally I would assume this meant my camera was wonky, but if I replace the rendering code with the following it works perfectly:// immediate modeglBegin(GL_TRIANGLES);for(int m = 0; m < indexes.at(n).size(); m++){unsigned int point = indexes.at(n).at(m);glNormal3f(normals.at(n).at(m).x, normals.at(n).at(m).y, normals.at(n).at(m).z);glVertex3f(vertices.at(n).at(point).x, vertices.at(n).at(point).y, vertices.at(n).at(point).z);}glEnd();On a related note, how does one go about using normals with VBOs when they're in a different array/vector than the vertices?  Would I bind the vertex buffer and call glVertexPointer, then bind the normal buffer and call glNormalPointer, then finally render with glDrawElements?[Edited by - imyourfoot on June 1, 2010 4:23:35 PM]
  Are you missing a PopMatrix() at the end of your loop?Quote:On a related note, how does one go about using normals with VBOs when they're in a different array/vector than the vertices? Would I bind the vertex buffer and call glVertexPointer, then bind the normal buffer and call glNormalPointer, then finally render with glDrawElements?Yes that is correct.;Quote:Original post by karwostsAre you missing a PopMatrix() at the end of your loop?Unfortunately no, I just accidentally omitted it from the code snippet.Quote:Quote:On a related note, how does one go about using normals with VBOs when they're in a different array/vector than the vertices? Would I bind the vertex buffer and call glVertexPointer, then bind the normal buffer and call glNormalPointer, then finally render with glDrawElements?Yes that is correct.Cool, thank you.   ;  In that case I'm not sure, your code looks fine to me. Is this exactly what you're using or are you just splicing together different sections? There might be something else you're doing that you're not showing.Can you get it to work with just a single triangle or cube or something?Also your description of the problem is a little confusing, can you elaborate? Is it supposed to be rotating at all or should it be static?   ;  I didn't want to overload anyone with code, but I suppose too much is more helpful than too little.I have a cube class that derives from the model class; I make 5000 of the cubes and have them rotate around random axis at random speeds.Cube.h: #include <vector> #include <GLUT/glut.h> #include "point3.h" #include "vector3.h" #include "spring.h"class Cube: public Model{public:Cube(vector3 cube_up, GLfloat initial_rotation_angle, GLfloat angle_delta_per_second, std::vector<GLfloat> cube_color, point3 model_center);void render_model(float r, float g, float b, float frame_time);private:vector3 up_vector;GLfloat current_rotation_angle;GLfloat delta_per_second;std::vector<GLfloat> color;vector3 transform_rotation_axis; // the Axis used to rotate the cube so that default up vector goes to up_vectorGLfloat transform_rotation_angle;};Cube.cpp:#include "Cube.h"Cube::Cube(vector3 cube_up, GLfloat initial_rotation_angle, GLfloat angle_delta_per_second, const std::vector<GLfloat> cube_color, point3 model_center): Model(model_center), up_vector(up), current_rotation_angle(initial_rotation_angle), delta_per_second(angle_delta_per_second),color(cube_color){transform_rotation_axis = up.cross(cube_up).normalize();transform_rotation_angle = 180.0*acos(up.dot(cube_up))/PI;/*std::cout << "up: " << up << std::endl;std::cout << "cube_up: " << cube_up << std::endl;std::cout << "up.dot(cube_up): " << up.dot(cube_up) << std::endl;std::cout << "transform_rotation_axis: " << transform_rotation_axis << std::endl;std::cout << "transform_rotation_angle: " << transform_rotation_angle << std::endl; */}void Cube::render_model(float r, float g, float b, float frame_time){current_rotation_angle += frame_time * delta_per_second;glPushMatrix();glTranslatef(center.x, center.y, center.z);glRotatef(transform_rotation_angle, transform_rotation_axis.x, transform_rotation_axis.y, transform_rotation_axis.z);glRotatef(current_rotation_angle, up_vector.x, up_vector.y, up_vector.z);glTranslatef(-center.x, -center.y, -center.z);Model::render_model(color[0], color[1], color[2]);glPopMatrix();}Model.h: #include <vector> #include <GLUT/glut.h> #include "point3.h" #include "vector3.h" #include "spring.h"class Model{public:Model(point3 model_center);void add_triangles(std::vector<point3> vertices, std::vector<unsigned int> vert_indexes);void add_spring(spring new_spring);std::vector<std::vector<point3> > get_vertices();std::vector<spring> get_springs();void render_model(float r, float g, float b);protected:std::vector<vector3> calculate_forces();std::vector<std::vector<point3> > vertices;std::vector<std::vector<unsigned int> > indexes;std::vector<std::vector<vector3> > normals;std::vector<spring> springs;point3 center;std::vector<GLuint> VBO_vertex_ids, VBO_index_ids, VBO_normal_ids;};Complete Model.cpp:#include "Model.h"Model::Model(point3 model_center){center = model_center;}void Model::add_triangles(std::vector<point3> new_vertices, std::vector<unsigned int> new_indexes){vertices.push_back(new_vertices);indexes.push_back(new_indexes);std::vector<vector3> norms;if(new_vertices.size() > 2) {for(int m = 0; m < new_indexes.size()/3; m++){vector3 normal = vector3(new_vertices.at(new_indexes.at(3*m + 1)).x - new_vertices.at(new_indexes.at(3*m)).x, new_vertices.at(new_indexes.at(3*m + 1)).y - new_vertices.at(new_indexes.at(3*m)).y,new_vertices.at(new_indexes.at(3*m + 1)).z - new_vertices.at(new_indexes.at(3*m)).z).cross(vector3(new_vertices.at(new_indexes.at(3*m + 2)).x - new_vertices.at(new_indexes.at(3*m + 1)).x, new_vertices.at(new_indexes.at(3*m + 2)).y - new_vertices.at(new_indexes.at(3*m + 1)).y,new_vertices.at(new_indexes.at(3*m + 2)).z - new_vertices.at(new_indexes.at(3*m + 1)).z));for(int n = 0; n < 3; n++){//std::cout << new_vertices.at(new_indexes.at(3*m + n)) << " " << normal << std::endl;norms.push_back(normal);}}while(norms.size() < new_vertices.size()) // in case there's any extra vertices{norms.push_back(vector3(0.0, 0.0, 0.0));std::cout << "Pushing back 0 vector! (new_indexes.size()%3 != 0)" << std::endl;}}else{for(int n = 0; n < new_vertices.size(); n++){norms.push_back(vector3(0.0, 0.0, 0.0));std::cout << "Pushing back 0 vector! (vertices.size() <= 2)" << std::endl;}}normals.push_back(norms);// BUG: Don't think this will work when there's more than one vector in containersGLuint dummy;VBO_vertex_ids.push_back(dummy);//VBO_normal_ids.push_back(dummy);VBO_index_ids.push_back(dummy);glGenBuffersARB(1, &VBO_vertex_ids.back());glGenBuffersARB(1, &VBO_index_ids.back());std::cout << "&VBO_vertex_ids.back(): " << VBO_vertex_ids.back() << std::endl;std::cout << "&VBO_index_ids.back(): " << VBO_index_ids.back() << std::endl;glBindBufferARB(GL_ARRAY_BUFFER_ARB, VBO_vertex_ids.back());glBufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(point3)*(vertices.back().size()), &vertices.back(), GL_STREAM_DRAW_ARB);glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, VBO_index_ids.back());glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, sizeof(unsigned int)*(indexes.back().size()), &indexes.back(), GL_STREAM_DRAW_ARB);glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);}void Model::add_spring(spring new_spring){springs.push_back(new_spring);}std::vector<std::vector<point3> > Model::get_vertices(){return vertices;}std::vector<spring> Model::get_springs(){return springs;}void Model::render_model(float r, float g, float b){for(int n = 0; n < indexes.size(); n++){glPushMatrix();// indexedglTranslatef(center.x, center.y, center.z);glColor3f(r, g, b);glEnableClientState(GL_VERTEX_ARRAY);glBindBufferARB(GL_ARRAY_BUFFER_ARB, VBO_vertex_ids[n]);glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, VBO_index_ids[n]);//glEnableClientState(GL_NORMAL_ARRAY);glVertexPointer(3, GL_FLOAT, 0, 0);//glBindBufferARB(GL_ARRAY_BUFFER_ARB, VBO_normal_ids[n]);//glNormalPointer(GL_FLOAT, 0, &normals[n]);glDrawElements(GL_TRIANGLES, indexes[n].size(), GL_UNSIGNED_INT, 0);//glDisableClientState(GL_NORMAL_ARRAY);glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);glDisableClientState(GL_VERTEX_ARRAY);/*// immediate modeglBegin(GL_TRIANGLES);for(int m = 0; m < indexes.at(n).size(); m++){unsigned int point = indexes.at(n).at(m);glNormal3f(normals.at(n).at(m).x, normals.at(n).at(m).y, normals.at(n).at(m).z);glVertex3f(vertices.at(n).at(point).x, vertices.at(n).at(point).y, vertices.at(n).at(point).z);}glEnd();// draw normal vectorsglDisable(GL_LIGHTING);glBegin(GL_LINES);for(int m = 0; m < indexes.at(n).size(); m++){unsigned int point = indexes.at(n).at(m);vector3 normal = normals.at(n).at(m);glColor3f(1.0, 0.0, 0.0);glNormal3f(normals.at(n).at(m).x, normals.at(n).at(m).y, normals.at(n).at(m).z);glVertex3f(vertices.at(n).at(point).x, vertices.at(n).at(point).y, vertices.at(n).at(point).z);glVertex3f(vertices.at(n).at(point).x + normal.x, vertices.at(n).at(point).y + normal.y, vertices.at(n).at(point).z + normal.z);}glEnd();glEnable(GL_LIGHTING);*/glPopMatrix();}}std::vector<vector3> Model::calculate_forces(){// TODO: Fillstd::vector<vector3> return_val;return return_val;}point3 and vector3 are basically just 3 GLfloats each in a class along with some useful operations.point3.h:#ifndef _point3#define _point3#include <iostream>#include <GLUT/glut.h>using namespace std;class point3{public:GLfloat x,y,z;void set(GLfloat dx, GLfloat dy, GLfloat dz){x=dx; y=dy;z=dz;}void set(point3& p){x=p.x;y=p.y;z=p.z;}point3(GLfloat xx, GLfloat yy, GLfloat zz){x=xx;y=yy;z=zz;}point3(){x=y=z=0;}point3(GLfloat p[3]){x = p[0]; y = p[1]; z = p[2];}void build4tuple(GLfloat v[]){// load 4-tuple with this color: v[3] = 1 for homogenousv[0] = x; v[1] = y;v[2] = z;v[3] = 1.0f;}bool operator==(const point3 &p){// TODO: This comparison function sucks, fix itGLfloat epsilon = .0001;return fabs(x - p.x) < epsilon && fabs(y - p.y) < epsilon && fabs(z - p.z) < epsilon;//return (((x - p.x) < epsilon || (p.x - x) < epsilon) //&& ((y - p.y) < epsilon || (p.y - y) < epsilon) && //((z - p.z) < epsilon || (p.z - z) < epsilon));}float distance(const point3 &p){return sqrt((p.x - x)*(p.x - x) + (p.y - y)*(p.y - y) + (p.z - z)*(p.z - z));}};vector3.h:#include <iostream>#include <GLUT/glut.h>#include "point3.h"using namespace std;#ifndef _vector3#define _vector3class vector3{public:GLfloat x,y,z;void set(float dx, float dy, float dz){x = dx;y = dy;z = dz;}void set(vector3 v){x = v.x;y = v.y;z = v.z;}void flip(){x = -x; y = -y;z = -z;}void setDiff(point3& a, point3& b){x = a.x - b.x;y = a.y - b.y;z = a.z - b.z;}vector3& normalize();vector3(){x = 0.0;y = 0.0;z = 0.0;}vector3(float xx, float yy, float zz){x = xx;y = yy;z = zz;}vector3(GLfloat p[3]){x = p[0]; y = p[1]; z = p[2];}vector3(vector3& v){x = v.x;y = v.y;z = v.z;}vector3(const vector3 &v){x = v.x;y = v.y;z = v.z;}/*vector3(){x = y = z = 0;}*/vector3(const point3& a, const point3& b){x = a.x - b.x;y = a.y - b.y;z = a.z - b.z;}void printVector() const{cout << "(" << x << "," << y << "," << z << ")";}vector3 cross(const vector3 &b);float dot(const vector3 &b);float getLength();vector3 &operator+=(const vector3 &v);vector3 &operator-=(const vector3 &v);vector3 &operator*=(double d);vector3 &operator/=(double d);vector3 operator+(const vector3 &v);vector3 operator-(const vector3 &v);vector3 operator*(double d);vector3 operator/(double d);};bool operator==(const vector3 &a, const vector3 &b);ostream &operator<<(ostream &sOut, const vector3 &V);#endif