I am using glDrawElement() for rendering a plain but the indexing is not working as intended so i am getting an irrelevant object .I have used AAssetmanager for loading the coordinates from a wavefront object file .
here is my code for rendering :
GLushort squareindices[] = {
0 , 1 ,2,
0, 3, 2
};
GLfloat vertexColor[] = {
1.0f, 1.0f , 0.0f,
0.0f , 0.0f , 1.0f,
1.0f, 1.0f , 0.0f,
0.0f , 0.0f , 1.0f,
};
void flatPlain::render(GLuint program) {
if (renderSelf) {
// flatPlainProgram = program;
auto *gens = new programGenerator;
auto *mats = new matrixOperation;
flatPlainProgram = gens->createProgram(vertexplain, fragmentplain);
// LOGE2("%x" , flatPlainProgram);
vertexLocation = glGetAttribLocation(flatPlainProgram, "vertexPosition");
// textureLocation = glGetAttribLocation(flatPlainProgram, "texturecord");
vertexColorlocation = glGetAttribLocation(flatPlainProgram, "vertexColour");
projection = glGetUniformLocation(flatPlainProgram, "projection");
model = glGetUniformLocation(flatPlainProgram, "modelView");
// sampleLocation = glGetUniformLocation(flatPlainProgram, "texture");
mats->perspective(projectionMatrix, (float) fov, (float) w / (float) h, 0.1f, 100.0f);
// if ( image != nullptr)
// loadTexture();
mats->createVolume(modelMatrix);
mats->rotateX(modelMatrix, angle);
mats->translateMatrix(x, y, z, modelMatrix);
glUseProgram(flatPlainProgram);
glVertexAttribPointer(vertexLocation, 3, GL_FLOAT, GL_FALSE, 0, vertexCord);
glEnableVertexAttribArray(vertexLocation);
glVertexAttribPointer(vertexColorlocation, 3, GL_FLOAT, GL_FALSE, 0, vertexColor);
glEnableVertexAttribArray(vertexColorlocation);
glUniformMatrix4fv(projection, 1, GL_FALSE, projectionMatrix);
glUniformMatrix4fv(model, 1, GL_FALSE, modelMatrix);
// glUniform1i(sampleLocation, 0);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, squareindices);
glDeleteProgram(flatPlainProgram);
}
}
I have read the vertices and then rendered it.
my .obj file:
v 0.000000 0.000000 0.000000
v 10.000000 0.000000 0.000000
v 0.000000 0.000000 -10.000000
v 10.000000 0.000000 -10.000000
vt 0.000000 0.000000
vt 1.000000 0.000000
vt 1.000000 1.000000
vt 0.000000 1.000000
vn 0.0000 1.0000 0.0000
usemtl None
s off
f 1/1/1 2/2/1 4/3/1 3/4/1
my output:
This are your vertex coordinates
0: ( 0.0, 0.0, 0.0)
1: (10.0, 0.0, 0.0)
2: ( 0.0, 0.0, -10.0)
3: (10.0, 0.0, -10.0)
0 1
+-----+
| |
| |
+-----+
2 3
Triangulate the quad with the following indices:
0, 1, 2, 1, 3, 2
0 1
+-----+ +
| / / |
| / / |
+ +-----+
2 3
Related
I have an issue with my wavefront .obj loader where it isn't displaying what I want it to display. I want it to display a cube, but I keep getting this:
Here is my obj file
# cube.obj
#
g cube
v 0.0 0.0 0.0
v 0.0 0.0 1.0
v 0.0 1.0 0.0
v 0.0 1.0 1.0
v 1.0 0.0 0.0
v 1.0 0.0 1.0
v 1.0 1.0 0.0
v 1.0 1.0 1.0
vn 0.0 0.0 1.0
vn 0.0 0.0 -1.0
vn 0.0 1.0 0.0
vn 0.0 -1.0 0.0
vn 1.0 0.0 0.0
vn -1.0 0.0 0.0
f 1//2 7//2 5//2
f 1//2 3//2 7//2
f 1//6 4//6 3//6
f 1//6 2//6 4//6
f 3//3 8//3 7//3
f 3//3 4//3 8//3
f 5//5 7//5 8//5
f 5//5 8//5 6//5
f 1//4 5//4 6//4
f 1//4 6//4 2//4
f 2//1 6//1 8//1
f 2//1 8//1 4//1
I added parts in my code to see if everything is being stored correctly, vertices and normals are stored as GLfloats
Display:
Inputs:
Here is my draw function:
I'm not quite sure about the last parameter in glDrawArrays, it is hard coded because I'm not quite sure about the number of indices.
void Draw(void)
{
glPushMatrix();
glClearColor(0,0,0,1);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glRotatef( rotate_x, 1.0, 0.0, 0.0 );
glRotatef( rotate_y, 0.0, 1.0, 0.0 );
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glNormalPointer(GL_FLOAT, 0, normals);
glVertexPointer(3, GL_FLOAT,0, vertices);
glDrawArrays(GL_TRIANGLES, 0, (14));
glTranslatef(0, 0, -3);
glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
glFlush();
glutSwapBuffers();
glPopMatrix();
}
This is my main aswell:
int main(int argc,char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize(500, 500);
glutCreateWindow("Object Loader!");
glEnable(GL_DEPTH_TEST);
//glEnable(GL_LIGHTING);
//glEnable(GL_LIGHT0);
GLfloat posLight0[] = {0.0f, 0.0f, -1.0f, 0.0f};
GLfloat lightColor[] = {1.0f, 1.0f, 1.0f, 1.0f};
glLightfv(GL_LIGHT0, GL_POSITION, posLight0);
glLightfv(GL_LIGHT0, GL_DIFFUSE, lightColor);
setUpArrays();
glutDisplayFunc(Draw);
glutSpecialFunc(specialKeys);
glutReshapeFunc(reshape);
glutMainLoop();
return 0;
}
One last thing is that I am not allowed to use glDrawElements or glBegin() direct mode.
Here is more of my program if it is helpful:
Global variables setup at the beginning
GLfloat* vertices;
GLfloat* normals;
GLint* faces;
int amountOfFaces;
double rotate_y=0;
double rotate_x=0;
Loader* loader = new Loader();
Setting up the arrays for the vertices, normals and indices:
void setUpArrays()
{
loader->loadObject("cube.obj");
vector<GLfloat> temp = loader->getVerticies();
vertices = new GLfloat[temp.size()];
int tempSize = 0;
cout << "vectors: ";
for(vector<GLfloat>::const_iterator i = temp.begin(); i != temp.end(); ++i)
{
vertices[tempSize] = *i;
cout << vertices[tempSize] << ", ";
tempSize++;
}
cout << endl;
vector<GLfloat> tempNormal = loader->getNormals();
normals = new GLfloat[tempNormal.size()];
tempSize = 0;
cout << "normals: ";
for(vector<GLfloat>::const_iterator i = tempNormal.begin(); i != tempNormal.end(); ++i)
{
normals[tempSize] = *i;
cout << normals[tempSize] << ", ";
tempSize++;
}
amountOfFaces = tempSize;
cout << endl;
vector<GLint> tempIndices = loader->getFaces();
faces = new GLint[tempIndices.size()];
tempSize = 0;
cout << "Indices: ";
for(vector<GLint>::const_iterator i = tempIndices.begin(); i != tempIndices.end(); ++i)
{
faces[tempSize] = *i;
cout << faces[tempSize] << ", ";
tempSize++;
}
cout << endl;
amountOfFaces += tempSize;
}
I'm baffled as to why but the OBJ format gives vertex attribute indices starting at 1, and not 0. I.e. f 1//2 refers to the first vertex and second normal. Your debug output doesn't show a zero in indices so I'm guessing the loader hasn't accounted for this.
A valid vertex index starts from 1 and matches the corresponding vertex elements of a previously defined vertex list. Each face can contain three or more vertices. [wikipedia]
Hopefully the fix is as easy as: faces[tempSize] = *i - 1;
[EDIT]
Your draw call specifies 14 vertices, but you have 12 triangles so should be drawing 36. amountOfFaces sounds like it should be tempIndices.size()/3.
Your vectors should be references to avoid a copy, and it will be way faster to populate faces etc. with a single memcpy. E.g: memcpy(faces, &tempIndices.front(), sizeof(GLint) * tempIndices.size())
[EDIT]
Oh, right, of course. Now I feel silly for not noticing. Faces indexes the vertices, so they can be reused (saves memory and extra processing). Instead of glDrawArrays you want this:
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, faces); //replate 36 for things you draw that aren't cubes
If you wanted to use glDrawArrays, you would have to rearrange your vertex arrays so each vertex appears in the order given by faces, including all the duplicates. For example your new position array would be [0,0,0, 1,1,0 1,0,0 ...] being vectors 0,6,4 forming the first triangle. std::vectors make this kind of rearranging easy to code.
One last thing. The normals array isn't as big as the position array, but OpenGL doesn't support mixed indexing. So you'll have to duplicate some of the normals so every vertex has both a position and normal.
On general my question is how can I provide 2 indices for the vbo. One for the vertices and one for the normals?
I got the next Obj file:
mtllib cube.mtl
v 1.000000 -1.000000 -1.000000
v 1.000000 -1.000000 1.000000
v -1.000000 -1.000000 1.000000
v -1.000000 -1.000000 -1.000000
v 1.000000 1.000000 -0.999999
v 0.999999 1.000000 1.000001
v -1.000000 1.000000 1.000000
v -1.000000 1.000000 -1.000000
vn 0.000000 -1.000000 0.000000
vn 0.000000 1.000000 0.000000
vn 1.000000 0.000000 0.000000
vn -0.000000 -0.000000 1.000000
vn -1.000000 -0.000000 -0.000000
vn 0.000000 0.000000 -1.000000
usemtl Material
f 1//1 2//1 3//1 4//1
f 5//2 8//2 7//2 6//2
f 1//3 5//3 6//3 2//3
f 2//4 6//4 7//4 3//4
f 3//5 7//5 8//5 4//5
f 5//6 1//6 4//6 8//6
As you can see there are 8 vertices and 6 normals. On the faces lines the file connects each vertex to the next vertex by indices and connects the normals too by different indices.
I am trying to draw with cube model with vbo. I have written the following code:
float vertex[] = {1, -1, -1,
1, -1, 1,
-1, -1, 1,
-1, -1, -1,
1, 1, -1,
1, 1, 1,
-1, 1, 1,
-1, 1, -1};
float normals[] = {0, -1, 0,
0, 1, 0,
1, 0, 0,
0, 0, 1,
-1, 0, 0,
0, 0, -1};
int index[] = {0, 1, 2, 3,
4, 7, 6, 5,
0, 4, 5, 1,
1, 5, 6, 2,
2, 6, 7, 3,
4, 0, 3, 8};
GLuint buffer, ind;
int offset = 0;
void vboInit()
{
glGenBuffers(1, &buffer);
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertex) + sizeof(normals), 0, GL_STATIC_DRAW);
glBufferSubData(GL_ARRAY_BUFFER, offset, sizeof(vertex), vertex); offset+= sizeof(vertex);
glBufferSubData(GL_ARRAY_BUFFER, offset, sizeof(normals), normals); offset+= sizeof(normals);
glGenBuffers(1, &ind);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ind);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(index), index, GL_STATIC_DRAW);
}
void vboDraw()
{
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ind);
glNormalPointer(GL_FLOAT, 0, (GLvoid*)(sizeof(vertex)));
glVertexPointer(3, GL_FLOAT, 0, 0);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
for (int i = 0; i < 6; i++)
glDrawElements(GL_TRIANGLE_FAN, 4 + i*4, GL_UNSIGNED_INT, (GLvoid*)(i*4));
glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
glBindBuffer(GL_ARRAY_BUFFER, NULL);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, NULL);
}
This code uses the indices of the vertices for the normals. Therefore the normals does not loading well and I need different indices to the normals. The question is how can I provide 2 indices for the vbo. One for the vertices and one for the normals?
Short answer it that you can't. But if you want long one:
DrawElements takes indices arrays of vertices. Vertex is not a position; it is assembly of all attributes at once. When you fetching vertex by index, you must take it from the very same index from every attribute array. Good side of indices is that they enables usage of post-TNL cache (however, utilisation of cache depends upon actual indices values) and reduces memory usage.
If your data saved in OBJ-like layout where attribute arrays indexed in independent way, you have to convert your arrays to more friendly representation. Simple approach would be:
Allocate big array[s] so it can hold all vertex data even without indices.
For each triangle, fetch data to new arrays using your independent indices. As the result, your vertices are now don't have independent attributes indices - but they don't have indices at all! You already could draw though - with DrawArrays().
If you want indices, now you can recreate them. Remove duplicates from new vertices arrays (duplicates have entire vertices equal, not only positions), and for each triangle find index of vertex in new array.
I am using an object loader to load an obj model that I exported from blender. I can load the model but none of the textures are loaded and I don't know why. Should they be loaded when I render the model in the main class or do I need to load the textures as well as rendering the model?
objloader.cpp
/************************************************************
*Loads obj file - limited to vertices, faces, normals, texture maps
*loads to object structure as defined in .h file
************************************************************/
#include <stdio.h>
#include <iostream>
#include <io.h>
#include <stdlib.h>
#include "glut.h"
#include "objloader.h"
using namespace std;
void object_type::render()
{
glBegin(GL_TRIANGLES); // glBegin and glEnd delimit the vertices that define a primitive (in our case triangles)
for (int j=0;j<polygons_qty;j++)
{
//----------------- FIRST VERTEX -----------------
//Normal coordinates of the first vertex
glNormal3f( normcoord[ polygon[j].n[0] - 1 ].i,
normcoord[ polygon[j].n[0] - 1 ].j,
normcoord[ polygon[j].n[0] - 1 ].k);
// Texture coordinates of the first vertex
glTexCoord2f( mapcoord[ polygon[j].t[0] - 1 ].u,
mapcoord[ polygon[j].t[0] - 1 ].v);
// Coordinates of the first vertex
glVertex3f( vertex[ polygon[j].v[0] - 1].x,
vertex[ polygon[j].v[0] - 1].y,
vertex[ polygon[j].v[0] - 1].z);
//----------------- SECOND VERTEX -----------------
//Normal coordinates of the first vertex
glNormal3f( normcoord[ polygon[j].n[1] - 1 ].i,
normcoord[ polygon[j].n[1] - 1 ].j,
normcoord[ polygon[j].n[1] - 1 ].k);
// Texture coordinates of the first vertex
glTexCoord2f( mapcoord[ polygon[j].t[1] - 1 ].u,
mapcoord[ polygon[j].t[1] - 1 ].v);
// Coordinates of the first vertex
glVertex3f( vertex[ polygon[j].v[1] - 1].x,
vertex[ polygon[j].v[1] - 1].y,
vertex[ polygon[j].v[1] - 1].z);
//----------------- THIRD VERTEX -----------------
//Normal coordinates of the first vertex
glNormal3f( normcoord[ polygon[j].n[2] - 1 ].i,
normcoord[ polygon[j].n[2] - 1 ].j,
normcoord[ polygon[j].n[2] - 1 ].k);
// Texture coordinates of the first vertex
glTexCoord2f( mapcoord[ polygon[j].t[2] - 1 ].u,
mapcoord[ polygon[j].t[2] - 1 ].v);
// Coordinates of the first vertex
glVertex3f( vertex[ polygon[j].v[2] - 1].x,
vertex[ polygon[j].v[2] - 1].y,
vertex[ polygon[j].v[2] - 1].z);
}
glEnd();
}
/*
vertex_type vertex[MAX_VERTICES];
mapcoord_type mapcoord[MAX_VERTICES];
normcoord_type normcoord[MAX_NORMALS];
polygon_type polygon[MAX_POLYGONS];
int id_texture
*/
int object_type::objdatadisplay()
{
int i;
printf("VERTICES: %d\n",vertices_qty);
for (i =0;i<vertices_qty;i++)
{
printf("%f %f %f\n",vertex[i].x,vertex[i].y,vertex[i].z);
}
printf("NORMALS: %d\n",normcoord_qty);
for (i =0;i<normcoord_qty;i++)
{
printf("%f %f %f\n",normcoord[i].i,normcoord[i].j,normcoord[i].k);
}
printf("MAP COORDS: %d\n",mapcoord_qty);
for (i =0;i<mapcoord_qty;i++)
{
printf("%f %f\n",mapcoord[i].u,mapcoord[i].v);
}
printf("POLYGONS: %d\n",polygons_qty);
for (i=0;i<polygons_qty;i++) //for each vertex of polygon (triangle)
{
for (int j = 0;j<3;j++)
{
printf("%d::%d/%d/%d\n",i,polygon[i].v[j],polygon[i].t[j],polygon[i].n[j]);
}
}
return 1;
}
int object_type::objloader(char *p_filename)
{
int ivertex=0; //Index variable
int inormal =0;
int ipolygon=0;
int imap=0;
char string[256];
FILE *l_file; //File pointer
char l_char; //Char variable
unsigned short l_face_flags; //Flag that stores some face information
if ((l_file=fopen (p_filename, "rt"))== NULL) return 0; //Open the file
while (!feof(l_file)) //Loop to scan the whole file
{
fscanf(l_file,"%c",&l_char);
if(l_char=='\n')//read char if'/n' -skip to next and read
fscanf(l_file,"%c",&l_char);
switch (l_char) //parse
{
default: fgets(string,256,l_file);
break;
case 'v': //a vertex or a normal or a text co-ord
fscanf(l_file,"%c",&l_char);
switch (l_char)
{
case ' ': //a vertex -expect and so read 3 floats next
fscanf(l_file,"%f %f %f",&vertex[ivertex].x, &vertex[ivertex].y,&vertex[ivertex].z);
ivertex++;
break;
case 'n': //a normal -expect and so read 3 floats next
fscanf(l_file,"%f %f %f",&normcoord[inormal].i, &normcoord[inormal].j,&normcoord[inormal].k);
inormal++;
break;
case 't': //a texture map coord-expect and so read 2 floats next
fscanf(l_file,"%f %f",&mapcoord[imap].u, &mapcoord[imap].v);
imap++;
break;
} //end switch
break;
case 'f': //a face read next assume format is -> f 1/1/1 2/2/2 3/3/3
for (int i=0;i<3;i++) //for each vertex of polygon (triangle)
{
fscanf(l_file,"%c",&l_char); //read space char - ignore this
fscanf(l_file,"%d",&polygon[ipolygon].v[i]); //read vertex.
fscanf(l_file,"%c",&l_char); //read space char - ignore this
fscanf(l_file,"%d",&polygon[ipolygon].t[i]); //read text coord.
fscanf(l_file,"%c",&l_char); //read space char - ignore this
fscanf(l_file,"%d",&polygon[ipolygon].n[i]); //read normal.
}
ipolygon++;
break;
} //end switch
}
fclose (l_file); // Closes the file stream
vertices_qty = ivertex;
polygons_qty = ipolygon;
mapcoord_qty = imap;
normcoord_qty = inormal;
return 1; //if successful
}
objloader.h
#ifndef OBJLOAD
#define OBJLOAD
/************************************************
*Loads obj file - limited to vertices, faces, normals, texture maps
*loads to object structure as defined in .h file
****************************************************/
#define MAX_VERTICES 8000 // Max number of vertices (for each object)
#define MAX_POLYGONS 8000 // Max number of polygons (for each object)
#define MAX_NORMALS 8000 // Max number of polygons (for each object)
// Our vertex type
typedef struct{
float x,y,z;
}vertex_type;
// Our normal type
typedef struct{
float i,j,k;
}normcoord_type;
// The polygon (triangle), 3 numbers that aim 3 vertices
typedef struct{
int v[3],t[3],n[3];
}polygon_type;
// The mapcoord type, 2 texture coordinates for each vertex
typedef struct{
float u,v;
}mapcoord_type;
// The object type
class object_type{
public:
int id_texture;
object_type(){}
~object_type(){}
int objloader(char *p_filename);
int objdatadisplay();
void render();
private:
char name[20];
int vertices_qty;
int polygons_qty;
int mapcoord_qty;
int normcoord_qty;
vertex_type vertex[MAX_VERTICES];
mapcoord_type mapcoord[MAX_VERTICES];
normcoord_type normcoord[MAX_NORMALS];
polygon_type polygon[MAX_POLYGONS];
};
#endif
main.cpp
#include "objloader.h"
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <GL/glew.h>
#ifdef __WIN32__
#include <windows.h>
#endif
#include "glut.h" //glut has all ogl relevant .h files included
int screen_width=800;
int screen_height=600;
//angle of rotation
float xpos = 0, ypos = 0, zpos = 0, xrot = 0, yrot = 0, angle=0.0;
float cRadius = 10.0f; // our radius distance from our character
float lastx, lasty;
object_type *objarray[2]; //objects container for our world. Used throughout so global
//Lights settings
GLfloat light_ambient[]= { 0.1f, 0.1f, 0.1f, 0.1f };
GLfloat light_diffuse[]= { 1.0f, 1.0f, 1.0f, 0.0f };
GLfloat light_specular[]= { 1.0f, 1.0f, 1.0f, 0.0f };
GLfloat light_position[]= { 100.0f, 0.0f, -10.0f, 1.0f };
//Materials settings
GLfloat mat_ambient[]= { 0.5f, 0.5f, 0.0f, 0.0f };
GLfloat mat_diffuse[]= { 0.5f, 0.5f, 0.0f, 0.0f };
GLfloat mat_specular[]= { 1.0f, 1.0f, 1.0f, 0.0f };
GLfloat mat_shininess[]= { 1.0f };
/************************************
*
* SUBROUTINE init(void)
*
* Used to initialize OpenGL and to setup our world
*
************************************/
void init(void)
{
glClearColor(0.0, 0.0, 0.0, 0.0); // Clear background color to black
// Viewport transformation
glViewport(0,0,screen_width,screen_height);
// Projection transformation
glMatrixMode(GL_PROJECTION); // Specifies which matrix stack is the target for matrix operations
glLoadIdentity(); // We initialize the projection matrix as identity
gluPerspective(45.0f,(GLfloat)screen_width/(GLfloat)screen_height,5.0f,10000.0f);
//Lights initialization and activation
glLightfv (GL_LIGHT1, GL_AMBIENT, light_ambient);
glLightfv (GL_LIGHT1, GL_DIFFUSE, light_diffuse);
glLightfv (GL_LIGHT1, GL_DIFFUSE, light_specular);
glLightfv (GL_LIGHT1, GL_POSITION, light_position);
glEnable (GL_LIGHT1);
glEnable (GL_LIGHTING);
//Materials initialization and activation
glMaterialfv (GL_FRONT, GL_AMBIENT, mat_ambient);
glMaterialfv (GL_FRONT, GL_DIFFUSE, mat_diffuse);
glMaterialfv (GL_FRONT, GL_DIFFUSE, mat_specular);
glMaterialfv (GL_FRONT, GL_POSITION, mat_shininess);
//Other initializations
glShadeModel(GL_SMOOTH); // Type of shading for the polygons
glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Texture mapping perspective correction
glEnable(GL_TEXTURE_2D); // Texture mapping ON
glPolygonMode (GL_FRONT_AND_BACK, GL_FILL); // Polygon rasterization mode (polygon filled)
glEnable(GL_CULL_FACE); // Enable the back face culling
glEnable(GL_DEPTH_TEST); // Enable the depth test
glTranslatef(0.0f, 0.0f, -cRadius);
glRotatef(xrot,1.0,0.0,0.0);
angle++; //increase the angle
for (int i=0;i<2;i++)
{
printf("*************\n");
objarray[i] = new (object_type);
objarray[i]->objloader("C:/3dModels/Museum.obj");
objarray[i]->objdatadisplay();
}
}
/**********************************************************
*
* SUBROUTINE resize(int p_width, int p_height)
*
* This routine must be called everytime we resize our window.
*
* Input parameters: p_width = width in pixels of our viewport
* p_height = height in pixels of our viewport
*
*********************************************************/
void resize (int p_width, int p_height)
{
if (screen_width==0 && screen_height==0) exit(0);
screen_width=p_width; // We obtain the new screen width values and store it
screen_height=p_height; // Height value
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // We clear both the color and the depth buffer so to draw the next frame
glViewport(0,0,screen_width,screen_height); // Viewport transformation
glMatrixMode(GL_PROJECTION); // Projection transformation
glLoadIdentity(); // We initialize the projection matrix as identity
gluPerspective(45.0f,(GLfloat)screen_width/(GLfloat)screen_height,5.0f,10000.0f);
glutPostRedisplay (); // This command redraw the scene (it calls the same routine of glutDisplayFunc)
}
/**********************************************************
*
* SUBROUTINE keyboard(void)
*
* Subroutine to handle keyboard input
*
*********************************************************/
void keyboard (unsigned char key, int x, int y) {
if (key=='q')
{
xrot += 1;
if (xrot >360) xrot -= 360;
}
if (key=='z')
{
xrot -= 1;
if (xrot < -360) xrot += 360;
}
if (key=='w')
{
float xrotrad, yrotrad;
yrotrad = (yrot / 180 * 3.141592654f);
xrotrad = (xrot / 180 * 3.141592654f);
xpos += float(sin(yrotrad));
zpos -= float(cos(yrotrad));
ypos -= float(sin(xrotrad));
}
if (key=='s')
{
float xrotrad, yrotrad;
yrotrad = (yrot / 180 * 3.141592654f);
xrotrad = (xrot / 180 * 3.141592654f);
xpos -= float(sin(yrotrad));
zpos += float(cos(yrotrad));
ypos += float(sin(xrotrad));
}
if (key=='d')
{
float yrotrad;
yrotrad = (yrot / 180 * 3.141592654f);
xpos += float(cos(yrotrad)) * 0.2;
zpos += float(sin(yrotrad)) * 0.2;
}
if (key=='a')
{
float yrotrad;
yrotrad = (yrot / 180 * 3.141592654f);
xpos -= float(cos(yrotrad)) * 0.2;
zpos -= float(sin(yrotrad)) * 0.2;
}
if (key==27)
{
exit(0);
}
}
/**********************************************************
*
* SUBROUTINE mouseMovement(void)
*
* Subroutine to handle mouse input
*
*********************************************************/
void mouseMovement(int x, int y) {
int diffx=x-lastx; //check the difference between the current x and the last x position
int diffy=y-lasty; //check the difference between the current y and the last y position
lastx=x; //set lastx to the current x position
lasty=y; //set lasty to the current y position
xrot += (float) diffy; //set the xrot to xrot with the addition of the difference in the y position
yrot += (float) diffx; //set the xrot to yrot with the addition of the difference in the x position
}
/**********************************************************
*
* SUBROUTINE display(void)
*
* This is our main rendering subroutine, called each frame
*
*********************************************************/
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // This clear the background color to dark blue
glMatrixMode(GL_MODELVIEW); // Modeling transformation
glPushMatrix();
glLoadIdentity(); // Initialize the model matrix as identity
glTranslatef(0.0f, 0.0f, -cRadius); // We move the object forward (the model matrix is multiplied by the translation matrix)
glRotatef(xrot,1.0,0.0,0.0); // Rotations of the object (the model matrix is multiplied by the rotation matrices)
glRotatef(yrot,0.0,1.0,0.0);
glTranslated(-xpos,0.0f,-zpos); //translate the screen to the position of our camera
if (objarray[0]->id_texture!=-1)
{
glBindTexture(GL_TEXTURE_2D, objarray[0]->id_texture); // We set the active texture
glEnable(GL_TEXTURE_2D); // Texture mapping ON
printf("Txt map ON");
}
else
glDisable(GL_TEXTURE_2D); // Texture mapping OFF
objarray[0]->render();
glPopMatrix();
glPushMatrix();
glTranslatef(5.0,0.0,-20.0);
glFlush(); // This force the execution of OpenGL commands
glutSwapBuffers(); // In double buffered mode we invert the positions of the visible buffer and the writing buffer
}
/**********************************************************
*
* The main routine
*
*********************************************************/
int main(int argc, char **argv)
{
// We use the GLUT utility to initialize the window, to handle the input and to interact with the windows system
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(screen_width,screen_height);
glutInitWindowPosition(0,0);
glutCreateWindow("Demo 1: To exit press ESC");
glutDisplayFunc(display);
glutIdleFunc(display);
glutReshapeFunc (resize);
glutPassiveMotionFunc(mouseMovement); //check for mouse movement
glutKeyboardFunc (keyboard);
init();
glutMainLoop();
return(0);
}
Example obj from blender, cube.obj:
# Blender v2.66 (sub 1) OBJ File: 'cube.blend'
# www.blender.org
mtllib cube.mtl
g Cube
v 1.000000 0.665869 -1.000000
v 1.000000 0.665869 1.000000
v -1.000000 0.665869 1.000000
v -1.000000 0.665869 -1.000000
v 1.000000 2.665869 -0.999999
v 0.999999 2.665869 1.000001
v -1.000000 2.665869 1.000000
v -1.000000 2.665869 -1.000000
vt 0.000000 0.334353
vt 0.332314 0.333333
vt 0.333333 0.665647
vt 1.000000 0.001019
vt 0.998981 0.333333
vt 0.666667 0.332314
vt 1.000000 0.665647
vt 0.667686 0.666667
vt 0.334353 0.666667
vt 0.333333 0.334353
vt 0.666667 0.665647
vt 0.333333 0.332314
vt 0.001020 0.333333
vt 0.332314 0.000000
vt 0.333333 0.001019
vt 0.665647 0.000000
vt 0.001019 0.666667
vt 0.667686 0.000000
vt 0.666667 0.334353
vt 0.665647 0.333333
vt 0.000000 0.001020
vt 0.334353 0.333333
vn 0.000000 -1.000000 0.000000
vn -0.000000 1.000000 0.000000
vn 1.000000 -0.000000 0.000001
vn -0.000000 -0.000000 1.000000
vn -1.000000 -0.000000 -0.000000
vn 0.000000 0.000000 -1.000000
vn 1.000000 0.000000 -0.000000
usemtl Material
s off
f 1/1/1 2/2/1 3/3/1
f 5/4/2 8/5/2 7/6/2
f 1/5/3 5/7/3 6/8/3
f 2/9/4 6/10/4 3/11/4
f 3/12/5 7/13/5 4/14/5
f 5/15/6 1/16/6 4/6/6
f 4/17/1 1/1/1 3/3/1
f 6/18/2 5/4/2 7/6/2
f 2/19/7 1/5/7 6/8/7
f 6/10/4 7/20/4 3/11/4
f 7/13/5 8/21/5 4/14/5
f 8/22/6 5/15/6 4/6/6
Your OBJ loader doesn't even attempt to parse MTL files.
You'll have to add MTL handling yourself.
You'll probably just want to support map_Kd.
Good luck.
I have create a program in C++ that contains also OpenGL and I want to create also an OBJ loader in order to load an OBJ file I have! I have already created two functions which are:
void ReadFile(model *md)
{
// Open the file for reading OBJINFO.TXT
ifstream obj_file("tree.obj");
if (obj_file.fail())
exit(1);
// Get the number of vertices
obj_file >> md->vertices;
// Get the number of faces
obj_file >> md->faces;
// Get the vertex coordinates
for (int i = 0; i < md->vertices; i++)
{
obj_file >> md->obj_points[i].x;
obj_file >> md->obj_points[i].y;
obj_file >> md->obj_points[i].z;
}
// Get the face structure
for (int i = 0; i < md->faces; i++)
{
obj_file >> md->obj_faces[i].vn[0];
obj_file >> md->obj_faces[i].vn[1];
obj_file >> md->obj_faces[i].vn[2];
obj_file >> md->obj_faces[i].vn[3];
}
obj_file.close();
}
void DisplayModel(model md)
{
glPushMatrix();
glBegin(GL_TRIANGLES);
for (int i = 0; i < md.faces; i++)
{
glVertex3f(md.obj_points[md.obj_faces[i].vn[0]-1].x, md.obj_points[md.obj_faces[i].vn[0]-1].y, md.obj_points[md.obj_faces[i].vn[0]-1].z);
glVertex3f(md.obj_points[md.obj_faces[i].vn[1]-1].x, md.obj_points[md.obj_faces[i].vn[1]-1].y, md.obj_points[md.obj_faces[i].vn[1]-1].z);
glVertex3f(md.obj_points[md.obj_faces[i].vn[2]-1].x, md.obj_points[md.obj_faces[i].vn[2]-1].y, md.obj_points[md.obj_faces[i].vn[2]-1].z);
glVertex3f(md.obj_points[md.obj_faces[i].vn[2]-1].x, md.obj_points[md.obj_faces[i].vn[2]-1].y, md.obj_points[md.obj_faces[i].vn[3]-1].z);
}
glEnd();
glPopMatrix();
}
The main problem is that when I compile the project and run it, nothing appears in viewport. I increased also the dimensions of viewport in case it is small in order to appear the object, but the situation remains the same! So I reach the result that I have done something wrong in these functions! Could anyone help me?
Also I give some values of my OBJ file:
v 0.158000 0.975000 0.151491 1.000000
v 0.188743 0.025000 0.173826 1.000000
v 0.196000 0.025000 0.151491 1.000000
v 0.158000 0.025000 0.151491 1.000000
v 0.169743 0.025000 0.187631 1.000000
v 0.146257 0.025000 0.187631 1.000000
v 0.127257 0.025000 0.173826 1.000000
vn 0.950370 0.038015 0.308791
vn 0.950370 0.038015 0.308791
vn 0.950370 0.038015 0.308791
vn 0.000000 -1.000000 0.000000
vn 0.000000 -1.000000 0.000000
vn 0.000000 -1.000000 -0.000000
vn 0.587380 0.038015 0.808418
f 1//1 2//2 3//3
f 4//4 3//5 2//6
f 1//7 5//8 2//9
f 4//10 2//11 5//12
f 1//13 6//14 5//15
f 4//16 5//17 6//18
f 1//19 7//20 6//21
// Get the number of vertices
obj_file >> md->vertices;
// Get the number of faces
obj_file >> md->faces;
Mikopos, read the spec again. That's not how OBJs work. You have to parse out the vertexes/texture coordinates/normals/faces as you go along.
Use something like this:
#include <GL/glut.h>
// https://github.com/g-truc/glm
#include <glm/glm.hpp>
#define GLM_ENABLE_EXPERIMENTAL
#include <glm/gtx/component_wise.hpp>
#include <vector>
#include <fstream>
#include <sstream>
struct Vertex
{
glm::vec3 position;
glm::vec2 texcoord;
glm::vec3 normal;
};
struct VertRef
{
VertRef( int v, int vt, int vn ) : v(v), vt(vt), vn(vn) { }
int v, vt, vn;
};
std::vector< Vertex > LoadOBJ( std::istream& in )
{
std::vector< Vertex > verts;
std::vector< glm::vec4 > positions( 1, glm::vec4( 0, 0, 0, 0 ) );
std::vector< glm::vec3 > texcoords( 1, glm::vec3( 0, 0, 0 ) );
std::vector< glm::vec3 > normals( 1, glm::vec3( 0, 0, 0 ) );
std::string lineStr;
while( std::getline( in, lineStr ) )
{
std::istringstream lineSS( lineStr );
std::string lineType;
lineSS >> lineType;
// vertex
if( lineType == "v" )
{
float x = 0, y = 0, z = 0, w = 1;
lineSS >> x >> y >> z >> w;
positions.push_back( glm::vec4( x, y, z, w ) );
}
// texture
if( lineType == "vt" )
{
float u = 0, v = 0, w = 0;
lineSS >> u >> v >> w;
texcoords.push_back( glm::vec3( u, v, w ) );
}
// normal
if( lineType == "vn" )
{
float i = 0, j = 0, k = 0;
lineSS >> i >> j >> k;
normals.push_back( glm::normalize( glm::vec3( i, j, k ) ) );
}
// polygon
if( lineType == "f" )
{
std::vector< VertRef > refs;
std::string refStr;
while( lineSS >> refStr )
{
std::istringstream ref( refStr );
std::string vStr, vtStr, vnStr;
std::getline( ref, vStr, '/' );
std::getline( ref, vtStr, '/' );
std::getline( ref, vnStr, '/' );
int v = atoi( vStr.c_str() );
int vt = atoi( vtStr.c_str() );
int vn = atoi( vnStr.c_str() );
v = ( v >= 0 ? v : positions.size() + v );
vt = ( vt >= 0 ? vt : texcoords.size() + vt );
vn = ( vn >= 0 ? vn : normals.size() + vn );
refs.push_back( VertRef( v, vt, vn ) );
}
// triangulate, assuming n>3-gons are convex and coplanar
for( size_t i = 1; i+1 < refs.size(); ++i )
{
const VertRef* p[3] = { &refs[0], &refs[i], &refs[i+1] };
// http://www.opengl.org/wiki/Calculating_a_Surface_Normal
glm::vec3 U( positions[ p[1]->v ] - positions[ p[0]->v ] );
glm::vec3 V( positions[ p[2]->v ] - positions[ p[0]->v ] );
glm::vec3 faceNormal = glm::normalize( glm::cross( U, V ) );
for( size_t j = 0; j < 3; ++j )
{
Vertex vert;
vert.position = glm::vec3( positions[ p[j]->v ] );
vert.texcoord = glm::vec2( texcoords[ p[j]->vt ] );
vert.normal = ( p[j]->vn != 0 ? normals[ p[j]->vn ] : faceNormal );
verts.push_back( vert );
}
}
}
}
return verts;
}
int btn;
glm::ivec2 startMouse;
glm::ivec2 startRot, curRot;
glm::ivec2 startTrans, curTrans;
void mouse(int button, int state, int x, int y )
{
if( button == GLUT_LEFT_BUTTON && state == GLUT_DOWN )
{
btn = button;
startMouse = glm::ivec2( x, glutGet( GLUT_WINDOW_HEIGHT ) - y );
startRot = curRot;
}
if( button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN )
{
btn = button;
startMouse = glm::ivec2( x, glutGet( GLUT_WINDOW_HEIGHT ) - y );
startTrans = curTrans;
}
}
void motion( int x, int y )
{
glm::ivec2 curMouse( x, glutGet( GLUT_WINDOW_HEIGHT ) - y );
if( btn == GLUT_LEFT_BUTTON )
{
curRot = startRot + ( curMouse - startMouse );
}
else if( btn == GLUT_RIGHT_BUTTON )
{
curTrans = startTrans + ( curMouse - startMouse );
}
glutPostRedisplay();
}
std::vector< Vertex > model;
void display()
{
glClearColor( 0.2f, 0.2f, 0.2f, 1.0f );
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
double w = glutGet( GLUT_WINDOW_WIDTH );
double h = glutGet( GLUT_WINDOW_HEIGHT );
double ar = w / h;
glTranslatef( curTrans.x / w * 2, curTrans.y / h * 2, 0 );
gluPerspective( 60, ar, 0.1, 100 );
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
glTranslatef( 0, 0, -10 );
glPushMatrix();
{
glRotatef( curRot.x % 360, 0, 1, 0 );
glRotatef( -curRot.y % 360, 1, 0, 0 );
// object
glColor3ub( 255, 0, 0 );
glEnableClientState( GL_VERTEX_ARRAY );
glEnableClientState( GL_TEXTURE_COORD_ARRAY );
glEnableClientState( GL_NORMAL_ARRAY );
glVertexPointer( 3, GL_FLOAT, sizeof(Vertex), &model[0].position );
glTexCoordPointer( 2, GL_FLOAT, sizeof(Vertex), &model[0].texcoord );
glNormalPointer( GL_FLOAT, sizeof(Vertex), &model[0].normal );
glDrawArrays( GL_TRIANGLES, 0, model.size() );
glDisableClientState( GL_VERTEX_ARRAY );
glDisableClientState( GL_TEXTURE_COORD_ARRAY );
glDisableClientState( GL_NORMAL_ARRAY );
// bounding cube
glDisable( GL_LIGHTING );
glColor3ub( 255, 255, 255 );
glutWireCube( 7 );
glEnable( GL_LIGHTING );
}
glPopMatrix();
glutSwapBuffers();
}
// return the min/max points of pts
template< typename Vec >
std::pair< Vec, Vec > GetExtents( const Vec* pts, size_t stride, size_t count )
{
unsigned char* base = (unsigned char*)pts;
Vec pmin( *(Vec*)base );
Vec pmax( *(Vec*)base );
for( size_t i = 0; i < count; ++i, base += stride )
{
const Vec& pt = *(Vec*)base;
pmin = glm::min( pmin, pt );
pmax = glm::max( pmax, pt );
}
return std::make_pair( pmin, pmax );
}
// centers geometry around the origin
// and scales it to fit in a size^3 box
template< typename Vec >
void CenterAndScale( Vec* pts, size_t stride, size_t count, const typename Vec::value_type& size )
{
typedef typename Vec::value_type Scalar;
// get min/max extents
std::pair< Vec, Vec > exts = GetExtents( pts, stride, count );
// center and scale
const Vec center = ( exts.first * Scalar( 0.5 ) ) + ( exts.second * Scalar( 0.5f ) );
const Scalar factor = size / glm::compMax( exts.second - exts.first );
unsigned char* base = (unsigned char*)pts;
for( size_t i = 0; i < count; ++i, base += stride )
{
Vec& pt = *(Vec*)base;
pt = ( ( pt - center ) * factor );
}
}
int main( int argc, char **argv )
{
// https://en.wikipedia.org/wiki/Stanford_bunny
std::ifstream ifile( "bunny.obj" );
model = LoadOBJ( ifile );
CenterAndScale( &model[0].position, sizeof( Vertex ), model.size(), 7 );
glutInit( &argc, argv );
glutInitDisplayMode( GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE );
glutInitWindowSize( 640, 480 );
glutCreateWindow( "OBJ" );
glutDisplayFunc( display );
glutMouseFunc( mouse );
glutMotionFunc( motion );
glEnable( GL_DEPTH_TEST );
// set up "headlamp"-like light
glShadeModel( GL_SMOOTH );
glEnable( GL_COLOR_MATERIAL );
glColorMaterial( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE ) ;
glEnable( GL_LIGHTING );
glEnable( GL_LIGHT0 );
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
GLfloat position[] = { 0, 0, 1, 0 };
glLightfv( GL_LIGHT0, GL_POSITION, position );
glPolygonMode( GL_FRONT, GL_FILL );
glPolygonMode( GL_BACK, GL_LINE );
glutMainLoop();
return 0;
}
LMB-drag rotates, RMB-drag "pans".
And use this:
v 0.000000 2.000000 2.000000
v 0.000000 0.000000 2.000000
v 2.000000 0.000000 2.000000
v 2.000000 2.000000 2.000000
f -4 -3 -2 -1
v 2.000000 2.000000 0.000000
v 2.000000 0.000000 0.000000
v 0.000000 0.000000 0.000000
v 0.000000 2.000000 0.000000
f -4 -3 -2 -1
v 2.000000 2.000000 2.000000
v 2.000000 0.000000 2.000000
v 2.000000 0.000000 0.000000
v 2.000000 2.000000 0.000000
f -4 -3 -2 -1
v 0.000000 2.000000 0.000000
v 0.000000 2.000000 2.000000
v 2.000000 2.000000 2.000000
v 2.000000 2.000000 0.000000
f -4 -3 -2 -1
v 0.000000 2.000000 0.000000
v 0.000000 0.000000 0.000000
v 0.000000 0.000000 2.000000
v 0.000000 2.000000 2.000000
f -4 -3 -2 -1
v 0.000000 0.000000 2.000000
v 0.000000 0.000000 0.000000
v 2.000000 0.000000 0.000000
v 2.000000 0.000000 2.000000
f -4 -3 -2 -1
Or this:
v 0.000000 2.000000 0.000000
v 0.000000 0.000000 0.000000
v 2.000000 0.000000 0.000000
v 2.000000 2.000000 0.000000
v 4.000000 0.000000 -1.255298
v 4.000000 2.000000 -1.255298
vn 0.000000 0.000000 1.000000
vn 0.000000 0.000000 1.000000
vn 0.276597 0.000000 0.960986
vn 0.276597 0.000000 0.960986
vn 0.531611 0.000000 0.846988
vn 0.531611 0.000000 0.846988
# 6 vertices
# 6 normals
g all
s 1
f 1//1 2//2 3//3 4//4
f 4//4 3//3 5//5 6//6
# 2 elements
for test.obj.
I'm working on a WaveFront .obj Loader and my first goal is to get all the vertices and indices loaded from the following .obj file (displays a cube with curved edges).
# Blender v2.62 (sub 0) OBJ File: 'Cube.blend'
# www.blender.org
o Cube
v 0.900000 -1.000000 -0.900000
v 0.900000 -1.000000 0.900000
v -0.900000 -1.000000 0.900000
v -0.900000 -1.000000 -0.900000
v 0.900000 1.000000 -0.900000
v 0.899999 1.000000 0.900001
v -0.900000 1.000000 0.900000
v -0.900000 1.000000 -0.900000
v 1.000000 -0.900000 -1.000000
v 1.000000 -0.900000 1.000000
v -1.000000 -0.900000 1.000000
v -1.000000 -0.900000 -1.000000
v 1.000000 0.905000 -0.999999
v 0.999999 0.905000 1.000001
v -1.000000 0.905000 1.000000
v -1.000000 0.905000 -1.000000
f 1//1 2//1 3//1
f 1//1 3//1 4//1
f 13//2 9//2 12//2
f 13//2 12//2 16//2
f 5//3 13//3 16//3
f 5//3 16//3 8//3
f 15//4 7//4 8//4
f 15//5 8//5 16//5
f 11//6 15//6 16//6
f 11//6 16//6 12//6
f 14//7 6//7 7//7
f 14//7 7//7 15//7
f 10//8 14//8 11//8
f 14//8 15//8 11//8
f 13//9 5//9 6//9
f 13//9 6//9 14//9
f 9//10 13//10 10//10
f 13//11 14//11 10//11
f 9//12 1//12 4//12
f 9//12 4//12 12//12
f 3//13 11//13 12//13
f 3//14 12//14 4//14
f 2//15 10//15 11//15
f 2//15 11//15 3//15
f 1//16 9//16 10//16
f 1//16 10//16 2//16
f 5//17 8//17 7//17
f 5//17 7//17 6//17
I've loaded all the vertices and the indices in two vectors called verticesVec and indicesVec and I've checked them both (they have all the input in the correct order, verticesVec[0] = 0.9 and indicesVec[0] = 1). I load the vertices in a VertexBufferObject and the indices in a VerticArrayObject together with the shader fields settings.
However, when I'm rendering the cube I get the following image which is not correct. I've rechecked all my code but I can't find the part where I'm going wrong. Has it something to do with the vectors and the size in bytes of the vectors?
The following code is from my Draw/Render method that does all the rendering.
glUseProgram(theProgram);
GLuint modelToCameraMatrixUnif = glGetUniformLocation(theProgram, "modelToCameraMatrix");
GLuint perspectiveMatrixUnif = glGetUniformLocation(theProgram, "cameraToClipMatrix");
glUniformMatrix4fv(perspectiveMatrixUnif, 1, GL_FALSE, glm::value_ptr(cameraToClipMatrix));
glm::mat4 identity(1.0f);
glutil::MatrixStack stack(identity); // Load identity Matrix
// Push for Camera Stuff
glutil::PushStack camera(stack);
stack.Translate(glm::vec3(camX, camY, camZ));
//Push one step further to fix object 1
glutil::PushStack push(stack);
stack.Translate(glm::vec3(0.0f, 0.0f, 3.0f));
// Draw Blender object
glBindVertexArray(this->load.vertexArrayOBject);
glUniformMatrix4fv(modelToCameraMatrixUnif, 1, GL_FALSE, glm::value_ptr(stack.Top()));
glDrawElements(GL_TRIANGLES, this->load.indicesVec.size(), GL_UNSIGNED_SHORT, 0);
// Pop camera (call destructor to de-initialize all dynamic memory)
camera.~PushStack();
// Now reset all buffers/programs
glBindVertexArray(0);
glUseProgram(0);
And the initialisation of buffer objects in my .obj loader:
void Loader::generateVertexBufferObjects()
{
// Fils the vertex buffer object with data
glGenBuffers(1, &vertexBufferObject);
glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObject);
glBufferData(GL_ARRAY_BUFFER, verticesVec.size() * 4, &verticesVec[0], GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
// Fills the index buffer object with its data
glGenBuffers(1, &indexBufferObject);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferObject);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indicesVec.size() * 4, &indicesVec[0], GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}
void Loader::generateVertexArrayObjects()
{
glGenVertexArrays(1, &vertexArrayOBject);
glBindVertexArray(vertexArrayOBject);
glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObject);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferObject);
glBindVertexArray(0);
}
You're creating your indexes as unsigned ints, but you're passing to OpenGL that they are of type GL_UNSIGNED_SHORT. The type argument to glDrawElements must match the type of data uploaded to the index buffer.