I have a terrain class like so:
class Terrian {
public:
Terrian(int width, int height);
virtual ~Terrian();
GLuint get_vertexbuffer();
GLuint get_colorbuffer();
GLuint get_elementbuffer();
protected:
private:
Vector3 **terrian_vertices;
Color **terrian_colors;
GLushort *terrian_elements;
GLuint vbo_terrian_vertices;
GLuint vbo_terrian_colors;
GLuint ibo_terrian_elements;
GLint width;
GLint height;
void construct_vertices();
void construct_buffers();
void construct_elements();
};
My problem is that the terrain simply never shows, I don't know if I am doing anything incorrectly but here is how the vertices are generated (I commented out the actual code and create a box instead).
void Terrian::construct_vertices() {
terrian_vertices = new Vector3*[8];
terrian_colors = new Color*[8];
/* actual code ...*/
GLfloat cube_vertices[] = {
-1.0, -1.0, 1.0,
1.0, -1.0, 1.0,
1.0, 1.0, 1.0,
-1.0, 1.0, 1.0,
// back
-1.0, -1.0, -1.0,
1.0, -1.0, -1.0,
1.0, 1.0, -1.0,
-1.0, 1.0, -1.0,
};
GLfloat cube_colors[] = {
// front colors
1.0, 0.0, 0.0,
0.0, 1.0, 0.0,
0.0, 0.0, 1.0,
1.0, 1.0, 1.0,
// back colors
1.0, 0.0, 0.0,
0.0, 1.0, 0.0,
0.0, 0.0, 1.0,
1.0, 1.0, 1.0,
};
int index = 0;
for (int i = 0; i < 8; i++) {
terrian_vertices[i] = new Vector3(cube_vertices[index], cube_vertices[index+1], cube_vertices[index+2]);
terrian_colors[i] = new Color(cube_colors[index], cube_colors[index+1], cube_colors[index+2]);
index+=3;
}
}
void Terrian::construct_elements() {
int index = 0;
GLushort cube_elements[] = {
// front
0, 1, 2,
2, 3, 0,
// top
1, 5, 6,
6, 2, 1,
// back
7, 6, 5,
5, 4, 7,
// bottom
4, 0, 3,
3, 7, 4,
// left
4, 5, 1,
1, 0, 4,
// right
3, 2, 6,
6, 7, 3,
};
terrian_elements = new GLushort[36];
for (int i = 0; i < 36; i++) {
terrian_elements[i] = cube_elements[i];
}
/* actual code ...*/
}
void Terrian::construct_buffers() {
glGenBuffers(1, &vbo_terrian_vertices);
glBindBuffer(GL_ARRAY_BUFFER, vbo_terrian_vertices);
glBufferData(GL_ARRAY_BUFFER, sizeof(terrian_vertices), terrian_vertices, GL_STATIC_DRAW);
glGenBuffers(1, &vbo_terrian_colors);
glBindBuffer(GL_ARRAY_BUFFER, vbo_terrian_colors);
glBufferData(GL_ARRAY_BUFFER, sizeof(terrian_colors), terrian_colors, GL_STATIC_DRAW);
glGenBuffers(1, &ibo_terrian_elements);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo_terrian_elements);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(terrian_elements), terrian_elements, GL_STATIC_DRAW);
}
My Vector3 and Color structure look like the following:
struct Vector3 {
GLfloat xyz[3];
Vector3(GLfloat x, GLfloat y, GLfloat z) {
this->xyz[0] = x;
this->xyz[1] = y;
this->xyz[2] = z;
}
Vector3() {
}
void set_x(GLfloat x);
void set_y(GLfloat y);
void set_z(GLfloat z);
GLfloat get_x();
GLfloat get_y();
GLfloat get_z();
Vector3 operator=(Vector3 param);
void normalise();
};
Color:
struct Color {
GLfloat rgb[3];
// Storing a one byte value in four bytes FTW
Color(GLfloat r, GLfloat g, GLfloat b) {
this->rgb[0] = r / 255.0;
this->rgb[1] = g / 255.0;
this->rgb[2] = b / 255.0;
}
Color() {
}
GLfloat get_r();
GLfloat get_g();
GLfloat get_b();
void set_r(GLfloat r);
void set_b(GLfloat g);
void set_g(GLfloat b);
};
I render the terrain like:
void render(sf::Window *app, Terrian *terrian) {
app->SetActive();
glClearColor(0.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(program);
glEnableVertexAttribArray(attribute_coord3d);
// Describe our vertices array to OpenGL (it can't guess its format automatically)
glBindBuffer(GL_ARRAY_BUFFER, terrian->get_vertexbuffer());
glVertexAttribPointer(
attribute_coord3d, // attribute
3, // number of elements per vertex, here (x,y,z)
GL_FLOAT, // the type of each element
GL_FALSE, // take our values as-is
0, // no extra data between each position
0 // offset of first element
);
glEnableVertexAttribArray(attribute_v_color);
glBindBuffer(GL_ARRAY_BUFFER, terrian->get_colorbuffer());
glVertexAttribPointer(
attribute_v_color, // attribute
3, // number of elements per vertex, here (R,G,B)
GL_FLOAT, // the type of each element
GL_FALSE, // take our values as-is
0, // no extra data between each position
0 // offset of first element
);
/* Push each element in buffer_vertices to the vertex shader */
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, terrian->get_elementbuffer());
int size;
glGetBufferParameteriv(GL_ELEMENT_ARRAY_BUFFER, GL_BUFFER_SIZE, &size);
glDrawElements(GL_TRIANGLES, size / sizeof(GLushort), GL_UNSIGNED_SHORT, 0);
glDisableVertexAttribArray(attribute_coord3d);
glDisableVertexAttribArray(attribute_v_color);
}
I really have no idea what is wrong, and why nothing is being drawn, I've checked my code against numerous examples but still can't find the issue, in the case that my world transformations may be a problem here they are:
void update(sf::Window *app, sf::Clock *clock) {
float angle = clock->GetElapsedTime() * 45;
glm::vec3 axis_y(0, 1, 0);
glm::mat4 anim = glm::rotate(glm::mat4(1.0f), angle, axis_y);
glm::mat4 model = glm::translate(glm::mat4(1.0f), glm::vec3(0.0, 0.0, -4.0));
// position, centre, up
glm::mat4 view = glm::lookAt(glm::vec3(0.0, 2.0, 0.0), glm::vec3(0.0, 0.0, -4.0), glm::vec3(0.0, 1.0, 0.0));
glm::mat4 projection = glm::perspective(45.0f, 1.0f * 800 / 600, 0.1f, 100.0f);
glm::mat4 mvp = projection * view * model * anim;
glUseProgram(program);
glUniformMatrix4fv(uniform_mvp, 1, GL_FALSE, glm::value_ptr(mvp));
}
Edit
Updated code according to Viclund's answer:
#ifndef TERRIAN_H
#define TERRIAN_H
#include "Vector3.h"
#include "Color.h"
#include <GL/glew.h>
#include <GL/glu.h>
#include <GL/gl.h>
#include <stdlib.h>
#include <vector>
class Terrian {
public:
Terrian(int width, int height);
virtual ~Terrian();
GLuint get_vertexbuffer();
GLuint get_colorbuffer();
GLuint get_elementbuffer();
protected:
private:
Vector3 *terrian_vertices;
Color *terrian_colors;
GLushort *terrian_elements;
GLuint vbo_terrian_vertices;
GLuint vbo_terrian_colors;
GLuint ibo_terrian_elements;
GLint width;
GLint height;
void construct_vertices();
void construct_buffers();
void construct_elements();
};
#endif // TERRIAN_H
...
void Terrian::construct_vertices() {
terrian_vertices = new Vector3[8];
terrian_colors = new Color[8];
GLfloat cube_vertices[] = {
-1.0, -1.0, 1.0,
1.0, -1.0, 1.0,
1.0, 1.0, 1.0,
-1.0, 1.0, 1.0,
// back
-1.0, -1.0, -1.0,
1.0, -1.0, -1.0,
1.0, 1.0, -1.0,
-1.0, 1.0, -1.0,
};
GLfloat cube_colors[] = {
// front colors
1.0, 0.0, 0.0,
0.0, 1.0, 0.0,
0.0, 0.0, 1.0,
1.0, 1.0, 1.0,
// back colors
1.0, 0.0, 0.0,
0.0, 1.0, 0.0,
0.0, 0.0, 1.0,
1.0, 1.0, 1.0,
};
int index = 0;
for (int i = 0; i < 8; i++) {
terrian_vertices[i] = Vector3(cube_vertices[index], cube_vertices[index+1], cube_vertices[index+2]);
terrian_colors[i] = Color(cube_colors[index], cube_colors[index+1], cube_colors[index+2]);
index+=3;
}
}
void Terrian::construct_elements() {
int index = 0;
GLushort cube_elements[] = {
// front
0, 1, 2,
2, 3, 0,
// top
1, 5, 6,
6, 2, 1,
// back
7, 6, 5,
5, 4, 7,
// bottom
4, 0, 3,
3, 7, 4,
// left
4, 5, 1,
1, 0, 4,
// right
3, 2, 6,
6, 7, 3,
};
terrian_elements = new GLushort[36];
for (int i = 0; i < 36; i++) {
terrian_elements[i] = cube_elements[i];
}
}
void Terrian::construct_buffers() {
glGenBuffers(1, &vbo_terrian_vertices);
glBindBuffer(GL_ARRAY_BUFFER, vbo_terrian_vertices);
glBufferData(GL_ARRAY_BUFFER, sizeof(Vector3) * 8, terrian_vertices, GL_STATIC_DRAW);
glGenBuffers(1, &vbo_terrian_colors);
glBindBuffer(GL_ARRAY_BUFFER, vbo_terrian_colors);
glBufferData(GL_ARRAY_BUFFER, sizeof(Color) * 8, terrian_colors, GL_STATIC_DRAW);
glGenBuffers(1, &ibo_terrian_elements);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo_terrian_elements);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLushort) * 36, terrian_elements, GL_STATIC_DRAW);
}
Edit 2
X: 5.69408e-039 Y: 5.745e-039 Z: 5.745e-039
X: 4.12098e+021 Y: 4.74227e+030 Z: 4.74227e+030
X: 1.93472e-019 Y: 1.80569e+028 Z: 1.80569e+028
X: 1.35662e-019 Y: 1.3556e-019 Z: 1.3556e-019
X: 2.79324e+020 Y: 1.15701e+027 Z: 1.15701e+027
X: 4.23282e+021 Y: 1.65846e+019 Z: 1.65846e+019
X: 3.52687e-012 Y: 4.12098e+021 Z: 4.12098e+021
X: 1.46091e-019 Y: 7.03684e+028 Z: 7.03684e+028