PDA

View Full Version : element buffer problems



anon_lastname
10-20-2016, 10:32 AM
I'm trying to load a Wavefront .obj file of an icosahedron I found on the internet.

My problem is that its output is clearly not correct

I expect the problem is one of two things:

1. I'm not interpreting the obj file correctly (I loaded it in an online .obj file renderer and it worked)
or
2. I didn't set up the vertex/element buffer correctly

Incoming wall of code: (most of it isn't important and I tried to make it visible what parts these are):



#define GLEW_STATIC
#include <GL/glew.h>

#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>

#include <chrono>
#include <cmath>


extern "C" {
#include "objReader.h"
}
typedef struct {
GLuint program;
GLuint frag;
GLuint vert;
} shaders;
shaders compileShaders(){
// Shader sources
const GLchar* vertexSource =
"#version 150 core\n"
"in vec3 position;"
"uniform mat4 trans;"
"uniform mat4 model;"
"uniform mat4 view;"
"uniform mat4 proj;"
"void main()"
"{"
// "gl_Position = vec4(position,1.0);"
"gl_Position = proj * view * model * vec4(position, 1.0);"
"}";

const GLchar* fragmentSource =
"#version 150 core\n"
"out vec4 outColor;"
"void main()"
"{"
"outColor = vec4(0,1.0,1.0, 1.0);"
"}";
// Create and compile the vertex shader
GLint status;

GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexSource, NULL);
glCompileShader(vertexShader);

char buffer[512];

glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &status);
glGetShaderInfoLog(vertexShader, 512, NULL, buffer);

if(status == GL_TRUE){
printf("vertex shader compiled.\n");
} else{
printf("\n\n%s\n\n",buffer);
}

GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentSource, NULL);
glCompileShader(fragmentShader);

glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &status);

glGetShaderInfoLog(fragmentShader, 512, NULL, buffer);

if(status == GL_TRUE){
printf("frag shader compiled.\n");
} else{
printf("\n\n%s\n\n",buffer);
}

// Link the vertex and fragment shader into a shader program
GLuint shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glBindFragDataLocation(shaderProgram, 0, "outColor");

glLinkProgram(shaderProgram);
glUseProgram(shaderProgram);

shaders ret;
ret.frag = fragmentShader;
ret.program = shaderProgram;
ret.vert = vertexShader;

return ret;
}


int main()
{
// load the obj file
obj iso = readObjFile("iso.obj");

auto t_start = std::chrono::high_resolution_clock::now();

// init window

glfwInit();

glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
GLFWwindow* window = glfwCreateWindow(800, 600, "OpenGL",NULL,NULL); // Windowed
glfwMakeContextCurrent(window);

glewExperimental = GL_TRUE;
glewInit();

// compile shaders
shaders programs = compileShaders();
GLuint shaderProgram = programs.program;
GLuint vertexShader = programs.vert;
GLuint fragmentShader = programs.frag;

//**********verifying that my problem isn't that the data read from the file isn't accurate (it is)*************

// this is the exact data from the obj file I read
float vertices[36] = {0, -0.525731, 0.850651,
0.850651, 0, 0.525731,
0.850651, 0, -0.525731,
-0.850651, 0, -0.525731,
-0.850651, 0, 0.525731,
-0.525731, 0.850651, 0,
0.525731, 0.850651, 0,
0.525731, -0.850651, 0,
-0.525731, -0.850651, 0,
0, -0.525731, -0.850651,
0, 0.525731, -0.850651,
0, 0.525731, 0.850651};

int elements[60] = {2, 3, 7,
2, 8, 3,
4, 5, 6,
5, 4, 9,
7, 6, 12,
6, 7, 11,
10, 11, 3,
11, 10, 4,
8, 9, 10,
9, 8, 1,
12, 1, 2,
1, 12, 5,
7, 3, 11,
2, 7, 12,
4, 6, 11,
6, 5, 12,
3, 8, 10,
8, 2, 1,
4, 10, 9,
5, 9, 1};
// comparing it to the data I read, getting the size of all elements in a fool-proof way
int totalSize = 0;
int totalTSize = 0;
for (int i = 0; i < 36; i++){
printf("%f:%f:%s\n",vertices[i],iso.vertices[i],(vertices[i]==iso.vertices[i])?"true":"false");
totalSize += sizeof(iso.vertices[i]);
}

for (int i = 0; i < 60; i++){
printf("%i:%i:%s\n",elements[i],iso.triangles[i],(elements[i]==iso.triangles[i])?"true":"false");
totalTSize += sizeof(iso.triangles[i]);
}
printf("vcount:%i\nvsize:%i",iso.verticeCount,totalSize);
printf("\ntcount:%i\ntsize:%i\n",iso.triangleCount,totalTSize);


printf("\n\n%i\n\n",sizeof(vertices));
printf("\n\n%i\n\n",sizeof(elements));
// ************************************************** ************************************************** **********

// Create Vertex Array Object
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);

// Create a Vertex Buffer Object and copy the vertex data to it
GLuint vbo;
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, totalSize, iso.vertices, GL_STATIC_DRAW);
// Create a Element Buffer Object and copy the element data to it
GLuint ebo;
glGenBuffers(1, &ebo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo); // Useful because you could change which buffers are used on the fly
glBufferData(GL_ELEMENT_ARRAY_BUFFER, totalTSize, iso.triangles, GL_STATIC_DRAW);

// Specify the layout of the vertex data
GLint posAttrib = glGetAttribLocation(shaderProgram, "position"); // the compiled program knows what inputs it has (IFAIK)
glEnableVertexAttribArray(posAttrib);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3*sizeof(GL_FLOAT), 0);

// adding standard transforms, making it rotate

GLint uniModel = glGetUniformLocation(shaderProgram, "model");
// Set up projection
glm::mat4 view = glm::lookAt(
glm::vec3(1.2f, 1.2f, 1.2f),
glm::vec3(0.0f, 0.0f, 0.0f),
glm::vec3(0.0f, 0.0f, 1.0f)
);
GLint uniView = glGetUniformLocation(shaderProgram, "view");
glUniformMatrix4fv(uniView, 1, GL_FALSE, glm::value_ptr(view));

glm::mat4 proj = glm::perspective(glm::radians(45.0f), 800.0f / 600.0f, 1.0f, 10.0f);

GLint uniProj = glGetUniformLocation(shaderProgram, "proj");
glUniformMatrix4fv(uniProj, 1, GL_FALSE, glm::value_ptr(proj));

while(!glfwWindowShouldClose(window)){

auto t_now = std::chrono::high_resolution_clock::now();
float time = std::chrono::duration_cast<std::chrono::duration<float>>(t_now - t_start).count();

glClear(GL_COLOR_BUFFER_BIT);

glm::mat4 trans;
trans = glm::rotate(
trans,
time * glm::radians(180.0f),
glm::vec3(0.0f, 0.0f, 1.0f)
);
glm::mat4 model;
model = glm::scale(model, glm::vec3(.01, .01, .01));
glUniformMatrix4fv(uniModel, 1, GL_FALSE, glm::value_ptr(model));
model = glm::rotate(
model,
time * glm::radians(180.0f),
glm::vec3(0.0f, 0.0f, 1.0f)
);
glUniformMatrix4fv(uniModel, 1, GL_FALSE, glm::value_ptr(model));

glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // black

glDrawElements(
GL_LINES, // mode
iso.triangleCount, // count
GL_UNSIGNED_INT, // type
(void*)0 // element array buffer offset
);

glfwSwapBuffers(window);
glfwPollEvents();
}

glDeleteProgram(shaderProgram);
glDeleteShader(fragmentShader);
glDeleteShader(vertexShader);
glDeleteBuffers(1, &vbo);
glDeleteVertexArrays(1, &vao);
free(iso.vertices); // in order to know the data from my reader would be sequential I had to malloc it myself
free(iso.triangles);
return 0;
}




thanks

GClements
10-20-2016, 11:29 AM
2. I didn't set up the vertex/element buffer correctly

I suspect that you aren't accounting for the fact that OBJ vertex indices start at one while OpenGL vertex indices start at zero.

I note that the elements array contains values from 1 to 12 inclusive, but the vertices array only contains 36 elements (so vertex indices should be in the range 0 to 11 inclusive).

anon_lastname
10-20-2016, 11:42 AM
I suspect that you aren't accounting for the fact that OBJ vertex indices start at one while OpenGL vertex indices start at zero.

I note that the elements array contains values from 1 to 12 inclusive, but the vertices array only contains 36 elements (so vertex indices should be in the range 0 to 11 inclusive).

I changed it to subtract 1 from each index, and that made it way more recognizable (although still missing a couple lines)

thank you

GClements
10-20-2016, 02:35 PM
(although still missing a couple lines)
That's because the "f" commands in the OBJ file describe faces, not edges.

Try using glDrawElements(GL_TRIANGLES,...) and glPolygonMode(GL_FRONT_AND_BACK, GL_LINE).

For filled triangles, you'll need some form of lighting, otherwise you'll just see a silhouette.

anon_lastname
10-21-2016, 10:21 AM
That worked as well, thank you