How to generate a plane using GL_TRIANGLES? - c++

Is there an algorithm that could be used to generate a plane using the GL_TRIANGLES primitive type?
Here's my current function:
Mesh* Mesh::CreateMeshPlane(vec2 bottomleft, ivec2 numvertices, vec2 worldsize){
int numVerts = numvertices.x * numvertices.y;
float xStep = worldsize.x / (numvertices.x - 1);
float yStep = worldsize.y / (numvertices.y - 1);
VertexFormat* verts = new VertexFormat[numVerts];
for (int y = 0; y < numvertices.y; y++)
{
for (int x = 0; x < numvertices.x; x++)
{
verts[x + (y * numvertices.x)].pos.x = bottomleft.x + (xStep * x);
verts[x + (y * numvertices.x)].pos.y = bottomleft.y + (yStep * y);
verts[x + (y * numvertices.x)].pos.z = 0;
}
}
Mesh* pMesh = new Mesh();
pMesh->Init(verts, numVerts, indices, 6, GL_STATIC_DRAW);
glPointSize(10.0f);
pMesh->m_PrimitiveType = GL_POINTS;
delete[] verts;
return pMesh;}
I'm just unsure how to implement indices into the for loop to be able to know which points to draw.
What I think I need to know:
Each square will be made up of 2 triangles, each square requiring 6 indices
Currently I'm drawing from the bottom left
I need to know how many squares I'll have from the numbers passed in

Maybe something like this:
int width = 4;
int length = 6;
int height = 1;
std::vector<float> planeVertices;
for (int x = 0; x < width - 1; x++) {
for (int z = 0; z < length - 1; z++) {
planeVertices.push_back(x);
planeVertices.push_back(height);
planeVertices.push_back(z);
planeVertices.push_back(x);
planeVertices.push_back(height);
planeVertices.push_back(z + 1);
planeVertices.push_back(x + 1);
planeVertices.push_back(height);
planeVertices.push_back(z + 1);
planeVertices.push_back(x);
planeVertices.push_back(height);
planeVertices.push_back(z);
planeVertices.push_back(x + 1);
planeVertices.push_back(height);
planeVertices.push_back(z);
planeVertices.push_back(x + 1);
planeVertices.push_back(height);
planeVertices.push_back(z + 1);
}
}
...
unsigned int VBO, VAO;
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, planeVertices.size() * sizeof(float), planeVertices.data(), GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), 0);
glEnableVertexAttribArray(0);
...
glDrawArrays(GL_TRIANGLES, 0, (width - 1) * (length - 1) * 6);
This code creates an std::vector<float> and adds the plane vertices to it. The nested for loops add two triangles for every unit of the plane (so with width as 4 and length as 6 the plane will be 4 units by 6 units, and will be made of 6 * 4 * 2 = 48 triangles). The height of the plane is set by the height variable. This only generates flat planes, but a simple transformation lets you rotate and scale this as you need.
WARNING: this code is untested.

Just to close this question here's how I did it:
Mesh* Mesh::CreateMeshPlane(vec3 bottomleft, ivec2 numvertices, vec2
worldsize, vec2 texturerepetition)
{
int numVerts = numvertices.x * numvertices.y;
int numFaces = (numvertices.x - 1) * (numvertices.y - 1);
int numIndices = numFaces * 6;
float xStep = worldsize.x / (numvertices.x - 1);
float yStep = worldsize.y / (numvertices.y - 1);
float zStep = worldsize.y / (numvertices.y - 1);
float uStep = texturerepetition.x / (numvertices.x - 1);
float vStep = texturerepetition.y / (numvertices.y - 1);
VertexFormat* verts = new VertexFormat[numVerts];
unsigned int* indices = new unsigned int[numIndices];
for (int y = 0; y < numvertices.y; y++)
{
for (int x = 0; x < numvertices.x; x++)
{
verts[x + (y * numvertices.x)].pos.x = bottomleft.x + (xStep * x);
verts[x + (y * numvertices.x)].pos.y = bottomleft.y;
verts[x + (y * numvertices.x)].pos.z = bottomleft.z + (zStep * y);
verts[y * numvertices.x + x].uv.x = uStep * x;
verts[y * numvertices.x + x].uv.y = vStep * y;
}
}
int offset = 0;
for (int i = 0; i < numIndices; i++)
{
// The bottom left index of the current face
// + the offset to snap back when we hit the edge
unsigned int cornerIndex = i/6 + offset;
// If we reach the edge we increase the offset so that it goes to the next bottom left
if ((cornerIndex + 1)%numvertices.x == 0)
{
offset++;
cornerIndex++; // Adding new offset to the bottom left
}
// First triangle
indices[i] = (unsigned int)cornerIndex;
i++;
indices[i] = (unsigned int)cornerIndex + numvertices.x;
i++;
indices[i] = (unsigned int)cornerIndex + numvertices.x + 1;
i++;
// Second triangle
indices[i] = (unsigned int)cornerIndex;
i++;
indices[i] = (unsigned int)cornerIndex + numvertices.x + 1;
i++;
indices[i] = (unsigned int)cornerIndex + 1;
}
//glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
Mesh* pMesh = new Mesh();
pMesh->Init(verts, numVerts, indices, numIndices, GL_STATIC_DRAW);
delete[] verts;
return pMesh;
}
Workflow:
1. Calculating number of faces I need, then the number of indices
2. Creating an offset that is added to the cornerIndex when we realize we hit the edge of the vertex array (by using modulus numvertices.y)
3. Doing simple math to draw corners in correct order based on the cornerIndex
Notes:
1. Im drawing using GL_TRIANGLES as the primitive type
2. Drawing from bottom left to top right
3. cornerIndex therefore is the bottom left of the current square we're drawing on
Hope someone can find this helpful!

Related

Texture multiple triangles of a circle in OpenGL

I'm trying to center a square texture on a circle using openGL, I have created a loop that fills an array with my circle coordinates, followed by my +/-normals for lighting, finally followed by my (x,y) for the texture coordinates.
For some reason the image ends up kind of smooshed instead of evenly spreading out around the circle. I'm ot sure if my calculations for the polar to cartesian coordinates are a little off or what.
Below is a section of the code as well as an image of the output.
{
/*FIX STILL NEEDED TO DYNAMICALLY UPDATE THESE VALUES*/
//When changing numberOfSides need to also update indices[] to numberOfSides*3 and allCircleVertices[] to numberOfVertices*numberOfSides
GLfloat x = 0;
GLfloat y = 0;
GLfloat z = 0;
GLfloat radius = 4;
GLuint numberOfSides = 20;
GLuint numberOfVertices = numberOfSides + 1;
GLuint k = 22;
GLuint angle = 360 / numberOfSides;
GLushort indices[60];
GLfloat doublePi = 2.0f * M_PI;
GLfloat* circleVerticesX = new GLfloat[numberOfVertices];
GLfloat* circleVerticesY = new GLfloat[numberOfVertices];
GLfloat* circleVerticesZ = new GLfloat[numberOfVertices];
GLfloat allCircleVertices[420]; /*= new GLfloat[numberOfVertices * numberOfSides];*/
circleVerticesX[0] = x;
circleVerticesY[0] = y;
circleVerticesZ[0] = z;
//Loop to determine angles between vertices
for (int i = 1; i < numberOfVertices; i++)
{
circleVerticesX[i] = x + (radius * cos(i * doublePi / numberOfSides));
circleVerticesY[i] = y;
circleVerticesZ[i] = z + (radius * sin(i * doublePi / numberOfSides));
}
//Loop to fill array with vertices
for (int i = 0; i < numberOfVertices; i++)
{
allCircleVertices[i * 8] = circleVerticesX[i];
allCircleVertices[(i * 8) + 1] = circleVerticesY[i];
allCircleVertices[(i * 8) + 2] = circleVerticesZ[i];
allCircleVertices[(i * 8) + 3] = 0.0f;
allCircleVertices[(i * 8) + 4] = 1.0f;
allCircleVertices[(i * 8) + 5] = 0.0f;
if ((i * 8) + 6 == 6)
{
allCircleVertices[6] = 0.5f;
}
else
{
allCircleVertices[(i * 8 + 6)] = 0.5 * (sin(angle * i));
}
if ((i * 8 + 7) == 7)
{
allCircleVertices[7] = 0.5f;
}
else
{
allCircleVertices[(i * 8 + 7)] = 0.5 * (cos(angle * i));
}
}
//For loop to fill Indices array with correct indices based on number of sides
for (int i = 0; i < numberOfSides; i++)
{
if (i == (numberOfSides - 1))
{
indices[i * 3] = 0;
indices[(i * 3) + 1] = indices[2];
indices[(i * 3) + 2] = numberOfSides;
//cout << indices[i * 3] << ", " << indices[(i * 3) + 1] << ", " << indices[(i * 3) + 2] << endl;
}
else
{
indices[i * 3] = 0;
indices[(i * 3) + 1] = i + 2;
indices[(i * 3) + 2] = i + 1;
//cout << indices[i * 3] << ", " << indices[(i * 3) + 1] << ", " << indices[(i * 3) + 2] << endl;
}
}
const GLuint floatsPerVertex = 3;
const GLuint floatsPerNormal = 3;
const GLuint floatsPerUV = 2;
glGenVertexArrays(1, &mesh.vao); // we can also generate multiple VAOs or buffers at the same time
glBindVertexArray(mesh.vao);
// Create 2 buffers: first one for the vertex data; second one for the indices
glGenBuffers(2, mesh.vbos);
glBindBuffer(GL_ARRAY_BUFFER, mesh.vbos[0]); // Activates the buffer
glBufferData(GL_ARRAY_BUFFER, sizeof(allCircleVertices), allCircleVertices, GL_STATIC_DRAW); // Sends vertex or coordinate data to the GPU
mesh.nIndices = sizeof(indices) / sizeof(indices[0]) * (floatsPerVertex + floatsPerNormal + floatsPerUV);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh.vbos[1]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
// Strides between vertex coordinates is 6 (x, y, z, r, g, b, a). A tightly packed stride is 0.
GLint stride = sizeof(float) * (floatsPerVertex + floatsPerNormal + floatsPerUV);// The number of floats before each
// Create Vertex Attribute Pointers
glVertexAttribPointer(0, floatsPerVertex, GL_FLOAT, GL_FALSE, stride, 0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, floatsPerNormal, GL_FLOAT, GL_FALSE, stride, (char*)(sizeof(float)* floatsPerVertex));
glEnableVertexAttribArray(1);
glVertexAttribPointer(2, floatsPerUV, GL_FLOAT, GL_FALSE, stride, (void*)(sizeof(float)* (floatsPerVertex + floatsPerNormal)));
glEnableVertexAttribArray(2);
}

glDrawElements has stopped working

I had glDrawElements working consistently, initially with a simple box and then with more complex shapes made up of a large amount of vertices. Then it simply stopped drawing the mesh. I have taken the code back to it's most basic, just drawing 2 triangles to make a 2D square. This also no longer works.
void createMesh(void) {
float vertices[12];
vertices[0] = -0.5; vertices[1] = -0.5; vertices[2] = 0.0; // Bottom left corner
vertices[3] = -0.5; vertices[4] = 0.5; vertices[5] = 0.0; // Top left corner
vertices[6] = 0.5; vertices[7] = 0.5; vertices[8] = 0.0; // Top Right corner
vertices[9] = 0.5; vertices[10] = -0.5; vertices[11] = 0.0; // Bottom right corner
short indices[] = { 0, 1, 2, 0, 2, 3};
glEnableClientState(GL_VERTEX_ARRAY); // Enable Vertex Arrays
glVertexPointer(3, GL_FLOAT, 0, vertices); // Set The Vertex Pointer To Our Vertex Data
glDrawElements(GL_TRIANGLES,6 , GL_UNSIGNED_SHORT, indices);
glDisableClientState(GL_VERTEX_ARRAY);
}
The more advanced code that used to work is shown below:
void createMesh(void) {
float vertices[(amountOfHorizontalScans * 480 * 3)];// Amount of vertices
//build the array of vertices from a matrix of data
int currentVertex = -1;
std::vector <std::vector<double>> currentPointCloudMatrix = distanceCalculator.getPointCloudMatrix();
double plotY = 0;
double plotX = 0;
for (int j = 0; j < currentPointCloudMatrix.size(); j++){
std::vector <double> singleDistancesVector = currentPointCloudMatrix.at(j);
for (int i = 0; i < singleDistancesVector.size(); i++){
if (singleDistancesVector.at(i) != 0){
vertices[++currentVertex] = plotX;
vertices[++currentVertex] = plotY;
vertices[++currentVertex] = singleDistancesVector.at(i);
}
plotX += 0.1;
}
plotX = 0;
plotY += 0.2; //increment y by 0.02
}
//Creating the array of indices, 480 is the amount of columns
int i = 0;
short indices2[(amountOfHorizontalScans * 480 * 3)];
for (int row = 0; row<amountOfHorizontalScans - 1; row++) {
if ((row & 1) == 0) { // even rows
for (int col = 0; col<480; col++) {
indices2[i++] = col + row * 480;
indices2[i++] = col + (row + 1) * 480;
}
}
else { // odd rows
for (int col = 480 - 1; col>0; col--) {
indices2[i++] = col + (row + 1) * 480;
indices2[i++] = col - 1 + +row * 480;
}
}
}
glEnableClientState(GL_VERTEX_ARRAY); // Enable Vertex Arrays
glVertexPointer(3, GL_FLOAT, 0, vertices); // Set The Vertex Pointer To Our Vertex Data
glDrawElements(GL_TRIANGLE_STRIP, (amountOfHorizontalScans * 480 * 3), GL_UNSIGNED_SHORT, indices2);
glDisableClientState(GL_VERTEX_ARRAY);
}
I am at a complete loss as to why it has stopped working as it was working perfectly for a good number of runs, then just completely stopped. I have debugged through and all the code is being reached, also the vertices and indices are populated with data. What could cause this to stop working?
EDIT:
So I am really quite confused now. I came back to this issue this morning, and everything worked fine again, as in the meshes would draw with no issues. After doing some tests and running the program a number of times it has simply stopped drawing meshes again!
Could this be something memory related? I am not 100% sure on how glDrawElements stores the data passed to it, so could it be that I have to clear something somewhere that I keep filling up with data?
You cannot allocate dynamically arrays in stack:
short indices2[(amountOfHorizontalScans * 480 * 3)];
In code:
short indices2[(amountOfHorizontalScans * 480 * 3)];
for (int row = 0; row<amountOfHorizontalScans - 1; row++) {
if ((row & 1) == 0) { // even rows
for (int col = 0; col<480; col++) {
indices2[i++] = col + row * 480;
indices2[i++] = col + (row + 1) * 480;
}
}
else { // odd rows
for (int col = 480 - 1; col>0; col--) {
indices2[i++] = col + (row + 1) * 480;
indices2[i++] = col - 1 + +row * 480;
}
}
}
Must be
short* indices2 = new short[(amountOfHorizontalScans * 480 * 3)];
than free allocated memory
delete [] indices2;
Triangle strip is pretty tricky mode did you try to work directly with GL_TRIANGLES.

2D std::vector array to glBufferData

I'm trying to use a 2D vector array of GLfloats to draw a grid. I cant seem to get the right code for glBufferData with a 2d vector instead of the examples I see online which are for 1D.
UPDATED - I have to multply glBufferData by 2 or else only half the grid gets drawn....
struct point
{
GLfloat x;
GLfloat y;
};
float gridMinus = flatGrid_lines / 2.0f;
//point Vertices[20][20];
GLfloat HEIGHT = 20.0f;
GLfloat WIDTH = 20.0f;
vector<point> VerticesD(flatGrid_lines * flatGrid_lines);
//VERTICAL LINES
for (int i = 0; i < flatGrid_lines; i++)
{
for (int j = 0; j < flatGrid_lines; j++)
{
VerticesD[i + j * flatGrid_lines].x = (j - gridMinus) / gridMinus;
VerticesD[i + j * flatGrid_lines].y = (i - gridMinus) / gridMinus;
}
}
glGenVertexArrays(1, &vao_grid1);
glBindVertexArray(vao_grid1);
glGenBuffers(1, &vbo_grid1);
glBindBuffer(GL_ARRAY_BUFFER, vbo_grid1);
glBufferData(GL_ARRAY_BUFFER, VerticesD.size() * 2 * sizeof(GLfloat), &VerticesD[0], GL_STATIC_DRAW);

Draw cylinder in shader based opengl

I'm looking for a good way to draw cylinder on opengl, i tried to draw multiple circles
for (GLuint m = 0; m <= segments; ++m) {
for (GLuint n = 0; n <= segments; ++n) {
GLfloat const t = 2 * M_PI * (float) n / (float) segments;
//position
points[num++] = x + sin(t) * r;
points[num++] = .0005 * m;
points[num++] = y + cos(t) * r;
//color
points[num++] = 1;
points[num++] = 1;
points[num++] = 1;
//texture
points[num++] = sin(t) * 0.5 + 0.5;
points[num++] = cos(t) * 0.5 + 0.5;
}
}
and on display function
GLuint pointer = 0;
for (GLuint i = 0; i <= segments; ++i) {
glDrawArrays(GL_TRIANGLE_FAN, pointer, segments + 1);
pointer += segments + 1;
}
I'm asking if there is a direct way to draw this cylinder
drawing many discs one on top of the other is too slow (unless you really want to draw the cylinder as slices of discs)
You should just draw the sides of the cylinder. For example a quad mesh would be
// for (GLuint m = 0; m <= segments; ++m)
float const bottom = .0005f * 0.f;
float const top = .0005f * (segments-1.f);
for(GLuint n = 0; n <= segments; ++n)
{
GLfloat const t0 = 2 * M_PI * (float)n / (float)segments;
GLfloat const t1 = 2 * M_PI * (float)(n+1) / (float)segments;
//quad vertex 0
points[num++] = x + sin(t0) * r;
points[num++] = bottom;
points[num++] = y + cos(t0) * r;
//quad vertex 1
points[num++] = x + sin(t1) * r;
points[num++] = bottom;
points[num++] = y + cos(t1) * r;
//quad vertex 2
points[num++] = x + sin(t1) * r;
points[num++] = top;
points[num++] = y + cos(t1) * r;
//quad vertex 3
points[num++] = x + sin(t0) * r;
points[num++] = top;
points[num++] = y + cos(t0) * r;
}
You can add 2 disks (the bases) to close the cylinder.
You can reduce fetching vertices form memory using a vertex+index buffer.
In new versions of OGL you can eliminate vertex memory read by indexing the mesh using gl_VertexID

Blue Screen of Death caused by Quad Tree Program

I am writing a Quad tree structure for a planet, that decreases and in increases in detail when you are far away from the quad and close to it receptively. However, I am running into some really serious, and annoying bugs.
I have two preprocessor defined constant that determines the size of the Quad tree (QUAD_WIDTH and QUAD_HEIGHT) when I change the value to anything but 32 (16 or 64 for example) I get a blue screen of death. I am using code::blocks as my IDE, another thing: Whenever I try to debug the program in code::blocks I also get a blue screen of death (Doesn't matter if the constants are 32 or not)
Why is this the case? And how can I fix it.
PQuad.cpp
#include "..\include\PQuad.h"
#include "..\include\Color3.h"
#include <iostream>
#include <vector>
#include <cmath>
#include <GL/glew.h>
#include <GL/glu.h>
#include <GL/gl.h>
#define QUAD_WIDTH 32
#define QUAD_HEIGHT 32
#define NUM_OF_CHILDREN 4
#define MAX_DEPTH 4
PQuad::PQuad(FaceDirection face_direction, float planet_radius) {
this->built = false;
this->spherised = false;
this->face_direction = face_direction;
this->radius = planet_radius;
this->planet_centre = glm::vec3(0, 0, 0);
}
PQuad::~PQuad() {
}
std::vector<PQuad> PQuad::get_children() {
return children;
}
bool PQuad::get_built() {
return this->built;
}
int PQuad::get_depth() {
return this->depth;
}
float *PQuad::get_table() {
return tree;
}
float PQuad::get_element_width() {
return element_width;
}
glm::vec3 PQuad::get_position() {
return position;
}
glm::vec3 PQuad::get_centre() {
return centre;
}
void PQuad::get_recursive(glm::vec3 player_pos, std::vector<PQuad*>& out_children) {
for (size_t i = 0; i < children.size(); i++) {
children[i].get_recursive(player_pos, out_children);
}
if (this->should_draw(player_pos) ||
this->depth == 0) {
out_children.emplace_back(this);
}
}
GLuint PQuad::get_vertexbuffer() {
return vbo_vertices;
}
GLuint PQuad::get_colorbuffer() {
return vbo_colors;
}
GLuint PQuad::get_normalbuffer() {
return vbo_normals;
}
GLuint PQuad::get_elementbuffer() {
return ibo_elements;
}
void PQuad::set_parent(PQuad *quad) {
this->parent = quad;
}
void PQuad::set_child_index(int child_index) {
this->child_index = child_index;
}
void PQuad::set_depth(int depth) {
this->depth = depth;
}
void PQuad::set_root(bool root) {
this->root = root;
}
void PQuad::calculate_position() {
this->element_width = depth == 0 ? 1.0f : parent->get_element_width() / 2.0f;
float quad_y = child_index / 2 == 0 ? 0 : element_width * QUAD_HEIGHT - element_width;
float quad_x = child_index % 2 == 0 ? 0 : element_width * QUAD_WIDTH - element_width;
if (this->depth != 0) {
quad_x += parent->get_position().x;
quad_y += parent->get_position().y;
}
this->position = glm::vec3(quad_x, quad_y, 0);
}
void PQuad::construct() {
if (!this->built) {
std::vector<glm::vec3> vertices;
std::vector<glm::vec3> normals;
std::vector<Color3> colors;
std::vector<GLushort> elements;
construct_vertices(&vertices, &colors);
construct_elements(&elements);
spherise(&vertices, &normals);
construct_normals(&vertices, &elements, &normals);
construct_buffers(&vertices, &colors, &elements, &normals);
float distance = radius;
if (!spherised) {
distance = QUAD_WIDTH;
}
construct_depth_table(distance);
this->built = true;
}
}
void PQuad::construct_depth_table(float distance) {
tree[0] = -1;
for (int i = 1; i < MAX_DEPTH; i++) {
tree[i] = distance;
distance /= 2.0f;
}
}
void PQuad::construct_children() {
calculate_position();
if (depth < (int)MAX_DEPTH) {
children.reserve((int)NUM_OF_CHILDREN);
for (int i = 0; i < (int)NUM_OF_CHILDREN; i++) {
children.emplace_back(PQuad(this->face_direction, this->radius));
PQuad *child = &children.back();
child->set_depth(depth + 1);
child->set_child_index(i);
child->set_parent(this);
child->construct_children();
}
} else {
leaf = true;
}
}
void PQuad::construct_vertices(std::vector<glm::vec3> *vertices, std::vector<Color3> *colors) {
vertices->reserve(QUAD_WIDTH * QUAD_HEIGHT);
for (int y = 0; y < QUAD_HEIGHT; y++) {
for (int x = 0; x < QUAD_WIDTH; x++) {
switch (face_direction) {
case YIncreasing:
vertices->emplace_back(glm::vec3(position.x + x * element_width, QUAD_HEIGHT - 1, -(position.y + y * element_width)));
break;
case YDecreasing:
vertices->emplace_back(glm::vec3(position.x + x * element_width, 0, -(position.y + y * element_width)));
break;
case XIncreasing:
vertices->emplace_back(glm::vec3(QUAD_WIDTH - 1, position.y + y * element_width, -(position.x + x * element_width)));
break;
case XDecreasing:
vertices->emplace_back(glm::vec3(0, position.y + y * element_width, -(position.x + x * element_width)));
break;
case ZIncreasing:
vertices->emplace_back(glm::vec3(position.x + x * element_width, position.y + y * element_width, 0));
break;
case ZDecreasing:
vertices->emplace_back(glm::vec3(position.x + x * element_width, position.y + y * element_width, -(QUAD_WIDTH - 1)));
break;
}
// Position the bottom, right, front vertex of the cube from being (0,0,0) to (-16, -16, 16)
(*vertices)[vertices->size() - 1] -= glm::vec3(QUAD_WIDTH / 2.0f, QUAD_WIDTH / 2.0f, -(QUAD_WIDTH / 2.0f));
colors->emplace_back(Color3(255.0f, 255.0f, 255.0f, false));
}
}
switch (face_direction) {
case YIncreasing:
this->centre = glm::vec3(position.x + QUAD_WIDTH / 2.0f, QUAD_HEIGHT - 1, -(position.y + QUAD_HEIGHT / 2.0f));
break;
case YDecreasing:
this->centre = glm::vec3(position.x + QUAD_WIDTH / 2.0f, 0, -(position.y + QUAD_HEIGHT / 2));
break;
case XIncreasing:
this->centre = glm::vec3(QUAD_WIDTH - 1, position.y + QUAD_HEIGHT / 2.0f, -(position.x + QUAD_WIDTH / 2.0f));
break;
case XDecreasing:
this->centre = glm::vec3(0, position.y + QUAD_HEIGHT / 2.0f, -(position.x + QUAD_WIDTH / 2.0f));
break;
case ZIncreasing:
this->centre = glm::vec3(position.x + QUAD_WIDTH / 2.0f, position.y + QUAD_HEIGHT / 2.0f, 0);
break;
case ZDecreasing:
this->centre = glm::vec3(position.x + QUAD_WIDTH / 2.0f, position.y + QUAD_HEIGHT / 2.0f, -(QUAD_HEIGHT - 1));
break;
}
this->centre -= glm::vec3(QUAD_WIDTH / 2.0f, QUAD_WIDTH / 2.0f, -(QUAD_WIDTH / 2.0f));
}
void PQuad::construct_elements(std::vector<GLushort> *elements) {
int index = 0;
elements->reserve((QUAD_WIDTH - 1) * (QUAD_HEIGHT - 1) * 6);
for (int y = 0; y < QUAD_HEIGHT - 1; y++) {
for (int x = 0; x < QUAD_WIDTH - 1; x++) {
GLushort bottom_left = x + y * QUAD_WIDTH;
GLushort bottom_right = (x + 1) + y * QUAD_WIDTH;
GLushort top_left = x + (y + 1) * QUAD_WIDTH;
GLushort top_right = (x + 1) + (y + 1) * QUAD_WIDTH;
elements->emplace_back(top_left);
elements->emplace_back(bottom_right);
elements->emplace_back(bottom_left);
elements->emplace_back(top_left);
elements->emplace_back(top_right);
elements->emplace_back(bottom_right);
}
}
}
void PQuad::construct_normals(std::vector<glm::vec3> *vertices, std::vector<GLushort> *elements, std::vector<glm::vec3> *normals) {
normals->reserve(QUAD_WIDTH * QUAD_HEIGHT);
for (int i = 0; i < elements->size() / 3; i++) {
int index1 = elements->at(i * 3);
int index2 = elements->at(i * 3 + 1);
int index3 = elements->at(i * 3 + 2);
glm::vec3 side1 = vertices->at(index1) - vertices->at(index3);
glm::vec3 side2 = vertices->at(index1) - vertices->at(index2);
glm::vec3 normal = glm::cross(side1, side2);
normal = glm::normalize(normal);
normals->emplace_back(normal);
normals->emplace_back(normal);
normals->emplace_back(normal);
}
}
void PQuad::spherise(std::vector<glm::vec3> *vertices, std::vector<glm::vec3> *normals) {
for (int i = 0; i < QUAD_WIDTH * QUAD_HEIGHT; i++) {
glm::vec3 normal = glm::normalize(vertices->at(i) - planet_centre);
(*vertices)[i] = (float)(radius) * normal;
}
glm::vec3 normal = glm::normalize(centre - planet_centre);
centre = normal * (float)(radius);
this->spherised = true;
}
void PQuad::construct_buffers(std::vector<glm::vec3> *vertices, std::vector<Color3> *colors, std::vector<GLushort> *elements, std::vector<glm::vec3> *normals) {
glGenBuffers(1, &vbo_vertices);
glBindBuffer(GL_ARRAY_BUFFER, vbo_vertices);
glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec3) * vertices->size(), &((*vertices)[0]), GL_STATIC_DRAW);
glGenBuffers(1, &vbo_colors);
glBindBuffer(GL_ARRAY_BUFFER, vbo_colors);
glBufferData(GL_ARRAY_BUFFER, sizeof(Color3) * colors->size(), &((*colors)[0]), GL_STATIC_DRAW);
glGenBuffers(1, &vbo_normals);
glBindBuffer(GL_ARRAY_BUFFER, vbo_normals);
glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec3) * normals->size(), &((*normals)[0]), GL_STATIC_DRAW);
glGenBuffers(1, &ibo_elements);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo_elements);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLushort) * elements->size(), &((*elements)[0]), GL_STATIC_DRAW);
}
float distance3(glm::vec3 v1, glm::vec3 v2) {
return sqrt(pow(abs(v1.x - v2.x), 2) + pow(abs(v1.y - v2.y), 2) + pow(abs(v1.z - v2.z), 2));
}
bool PQuad::should_draw(glm::vec3 player_position) {
float distance = distance3(player_position, centre);
if (distance < tree[depth]) {
return true;
}
return false;
}
A blue screen of death should be just impossible to reach from a regular user space program... no matter what you do.
However unfortunately it's easy to bump into this kind of system level bug when writing software that interacts heavily with device drivers because they are software too, and they are not bug free (and a bug in a device driver can take down the whole system with a BSOD).
The meaning is that you are making some call to OpenGL with wrong parameters, and that the driver of your video card has a bug and instead of detecting the problem and returning a failure code, it just takes down the machine.
You may try to use a log of the operations, writing to a file each single step so after you get a BSOD and reboot you can check what was the last command written to the file. Note that you should open the file in append, write the log line and then close the file. Not even this gives you a 100% guarantee the content of the file will have been written really to the disk when you get the BSOD, but IMO in this case the probability should be high. A better alternative would be just sending log messages over the serial line or using the network to another computer.
It may be a difficult problem to track and solve.
Another option would be using a different OpenGL implementation (like Mesa). May be with another implementation calls are checked better and you can spot what is the call with wrong parameters.
It could even be that your code is just triggering a bug in the video driver and your code is not doing anything wrong. This should be your last thought however.
Actually the answer is quite simple. There is something really wrong with the debugger in Code::Blocks on Windows. I have seen it blue screen multiple systems. Switch to using output statements or another IDE.