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:
- I’m not interpreting the obj file correctly (I loaded it in an online .obj file renderer and it worked)
or - 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
"
"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
"
"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.
");
} else{
printf("
%s
",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.
");
} else{
printf("
%s
",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
",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
",elements[i],iso.triangles[i],(elements[i]==iso.triangles[i])?"true":"false");
totalTSize += sizeof(iso.triangles[i]);
}
printf("vcount:%i
vsize:%i",iso.verticeCount,totalSize);
printf("
tcount:%i
tsize:%i
",iso.triangleCount,totalTSize);
printf("
%i
",sizeof(vertices));
printf("
%i
",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