I'am using quadtree in 2D coordinates (base code get here: https://github.com/veeableful/Quadtree_Minimal)
At start, code using just one point to detect rectangles inside quadtree.
But detecting object is quad - select rectagles from quadtree become more complex. First decision was: detect rectangles form quadtree by 4 points, then sort them and remove duplicates. But question is - how good is this realization? Maybe there is more fast/optimized ways?
Rectangle:
struct stRectangle
{
float p[2]; //start point x/y
float s[2]; //width/height
};
Quad:
struct stQuad
{
glm::vec2 p[4];
};
Detecting by point:
vector<stRectangle*> MQuadTree::GetRectanglesAt(float inX, float inY)
{
if(Level == MaxLevel) return Rectangles;
vector<stRectangle*> ReturnRectangles, ChildReturnRectangles;
if(!Rectangles.empty()) ReturnRectangles = Rectangles;
const float HalfWidth = Width * 0.5;
const float HalfHeight = Height * 0.5;
if(inX > X + HalfWidth && inX < X + Width)
{
if(inY > Y + HalfHeight && inY < Y + Height)
{
ChildReturnRectangles = SE->GetRectanglesAt(inX, inY);
ReturnRectangles.insert(ReturnRectangles.begin(), ChildReturnRectangles.begin(), ChildReturnRectangles.end());
return ReturnRectangles;
}
if(inY > Y && inY <= Y + HalfHeight)
{
ChildReturnRectangles = NE->GetRectanglesAt(inX, inY);
ReturnRectangles.insert(ReturnRectangles.begin(), ChildReturnRectangles.begin(), ChildReturnRectangles.end());
return ReturnRectangles;
}
}
if(inX > X && inX <= X + HalfWidth)
{
if(inY > Y + HalfHeight && inY < Y + Height)
{
ChildReturnRectangles = SW->GetRectanglesAt(inX, inY);
ReturnRectangles.insert(ReturnRectangles.begin(), ChildReturnRectangles.begin(), ChildReturnRectangles.end());
return ReturnRectangles;
}
if(inY > Y && inY <= Y + HalfHeight)
{
ChildReturnRectangles = NW->GetRectanglesAt(inX, inY);
ReturnRectangles.insert(ReturnRectangles.begin(), ChildReturnRectangles.begin(), ChildReturnRectangles.end());
return ReturnRectangles;
}
}
return ReturnRectangles;
}
Detecting by Quad (suspicious code):
vector<stRectangle*> MQuadTree::GetRectanglesAt(float* Points)
{
vector<stRectangle*> ReturnRectangles;
vector<stRectangle*> CurrentRectangles;
CurrentRectangles = GetRectanglesAt(*(Points + 0), *(Points + 1));
ReturnRectangles.insert(ReturnRectangles.end(), CurrentRectangles.begin(), CurrentRectangles.end());
CurrentRectangles = GetRectanglesAt(*(Points + 2), *(Points + 3));
ReturnRectangles.insert(ReturnRectangles.end(), CurrentRectangles.begin(), CurrentRectangles.end());
CurrentRectangles = GetRectanglesAt(*(Points + 4), *(Points + 5));
ReturnRectangles.insert(ReturnRectangles.end(), CurrentRectangles.begin(), CurrentRectangles.end());
CurrentRectangles = GetRectanglesAt(*(Points + 6), *(Points + 7));
ReturnRectangles.insert(ReturnRectangles.end(), CurrentRectangles.begin(), CurrentRectangles.end());
sort(ReturnRectangles.begin(), ReturnRectangles.end());
ReturnRectangles.erase(unique(ReturnRectangles.begin(), ReturnRectangles.end()), ReturnRectangles.end());
return ReturnRectangles;
}
Buttons processing:
void MGame2::OnKeyDown(WPARAM wParam, LPARAM lParam)
{
Key[wParam] = 1;
if(pDrawFunc == &MGame2::DrawGame)
{
if(Key[VK_ESCAPE])
{
SendMessage(m_hWnd, WM_DESTROY, 0, 0);
return;
}
if(!Pause)
{
if(Key[VK_LEFT]) MoveQuad(PointQuad, -5, 0);
if(Key[VK_RIGHT]) MoveQuad(PointQuad, 5, 0);
if(Key[VK_UP]) MoveQuad(PointQuad, 0, 5);
if(Key[VK_DOWN]) MoveQuad(PointQuad, 0, -5);
if(Key[VK_LEFT] || Key[VK_RIGHT] || Key[VK_UP] || Key[VK_DOWN])
{
glBindBuffer(GL_ARRAY_BUFFER, vtxPointQuadId);
glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec2) * 4, &PointQuad.p[0][0], GL_STREAM_DRAW);
NearRectanglesToBuffer(PointQuad);
if(TestCollisions()) SetPointQuadColor(1, 0, 0, 1); else SetPointQuadColor(0, 0, 1, 1);
}
}
}
}
Related
I'm extruding a sine-wave curve into 3d but when rendering, I can see that the normals are not smoothed.
The sine-wave is generated with parametric normals, as follows:
vector<CurvePoint> sineWave(int n, float x0, float y0, float step, float period)
{
vector<CurvePoint> curve;
for (int i = 0; i < n; i++) {
float a = TWO_PI / period;
float x = x0 + i * step;
float y = y0 - sinf(x * a);
float c = cosf(x * a);
auto normal = glm::vec2(a * c, 1) / sqrtf(a * a * c * c + 1);
curve.emplace_back(glm::vec2(x, y), normal);
}
return curve;
}
The extruding method:
void extrude(IndexedVertexBatch<XYZ.N> &batch, const Matrix &matrix, const vector<CurvePoint> &curve, GLenum frontFace, float distance)
{
auto size = curve.size();
if (size > 1 && distance != 0) {
bool cw = ((frontFace == CW) && (distance > 0)) || ((frontFace == CCW) && (distance < 0));
for (auto i = 0; i < size - 1; i++) {
auto &p0 = curve[i].position;
auto &p1 = curve[i + 1].position;
auto normal = matrix.transformNormal(glm::vec3(curve[i].normal, 0));
batch
.addVertex(matrix.transformPoint(p0), normal)
.addVertex(matrix.transformPoint(p1), normal)
.addVertex(matrix.transformPoint(glm::vec3(p1, distance)), normal)
.addVertex(matrix.transformPoint(glm::vec3(p0, distance)), normal);
if (cw) {
batch.addIndices(0, 3, 2, 2, 1, 0);
} else {
batch.addIndices(0, 1, 2, 2, 3, 0);
}
batch.incrementIndices(4);
}
}
}
The rendering (phong-like shading):
How can I obtain smoothed normals?
Stupid me. It was a small bug in the extruding method, which should be like:
void extrude(IndexedVertexBatch<XYZ.N> &batch, const Matrix &matrix, const vector<CurvePoint> &curve, GLenum frontFace, float distance)
{
auto size = curve.size();
if (size > 1 && distance != 0) {
bool cw = ((frontFace == CW) && (distance > 0)) || ((frontFace == CCW) && (distance < 0));
for (auto i = 0; i < size - 1; i++) {
auto &p0 = curve[i].position;
auto &p1 = curve[i + 1].position;
auto normal0 = matrix.transformNormal(glm::vec3(curve[i].normal, 0));
auto normal1 = matrix.transformNormal(glm::vec3(curve[i + 1].normal, 0));
batch
.addVertex(matrix.transformPoint(p0), normal0)
.addVertex(matrix.transformPoint(p1), normal1)
.addVertex(matrix.transformPoint(glm::vec3(p1, distance)), normal1)
.addVertex(matrix.transformPoint(glm::vec3(p0, distance)), normal0);
if (cw) {
batch.addIndices(0, 3, 2, 2, 1, 0);
} else {
batch.addIndices(0, 1, 2, 2, 3, 0);
}
batch.incrementIndices(4);
}
}
}
I try to find the ray intersection distance , t with the wedge shape, I checked the intersection for each finite plane of the wedge, I have this solution but is not working as I expect, I get the wrong result, I need help.
double getIntersectionDistance(Vec3 origin, Vec3 direction) {
//Vec3-3d vector of double
//origin and direction are ray origin and direction respectively.
/*
* BackfaceNormal(1, 0, 0)
* BottomfaceNormal(0, 1, 0)
* DiagonalNormal(1, 1, 0)
* RightTriangle(0, 0, 1)
* LeftTriangle(0, 0, -1)
*/
if(origin.x < 0) {
origin.x = -origin.x;
direction.x = -direction.x;
}
if(origin.y < 0) {
origin.y = -origin.y;
direction.y = -direction.y;
}
if(origin.z < 0) {
origin.z = -origin.z;
direction.z = -direction.z;
}
//for bottom plane
{
Vec3 normal(0, 1, 0);
double ty = (-1 - origin.y) / direction.y;
double y = origin.y + ty * direction.y;
if(std::abs(y) <= 1.0 && ty > 0) {
return ty;
}
}
//for back plane
{
Vec3 normal(1, 0, 0);
double tx = (-1 - origin.x) / direction.x;
double x = origin.x + tx * direction.x;
if(std::abs(x) <= 1.0 && tx > 0) {
return tx;
}
}
//left triangle
{
Vec3 normal(0, 0, 1);
double tz = (-1 - origin.z) / direction.z ;
double z = origin.z + tz * direction.z;
if(std::abs(z) <= 1.0 && tz > 0) {
return tz;
}
}
//right triangle
{
Vec3 normal(0, 0, -1);
double tz = (1 - origin.z) / direction.z;
double z = origin.z + tz * direction.z;
if(std::abs(z) <= 1.0 && tz > 0) {
return tz;
}
}
//diagonal
Vec3 normal(1, 1, 0);
const double dn = direction.x + direction.y;
double txy = (-origin.x - origin.y) / dn;
double x = origin.x + txy * direction.x;
double y = origin.y + txy * direction.y;
if(x + y <= 0.0 && txy > 0) {
return txy;
}
return std::numeric_limits<double>::infinity();//no intersection.
}
It also draws multiply triangles, they are all displaced and in wrong scale.
I am trying to make my own implementation of triangle rasterizer found at:
https://www.scratchapixel.com/lessons/3d-basic-rendering/rasterization-practical-implementation/rasterization-stage
I have no idea what is wrong with my code.
#include<fstream>
#include<cmath>
class Vertice
{
public:
float x, y;
Vertice(float x, float y)
{
this->x = x;
this->y = y;
}
void fitToImage(int imageWidth, int imageHeight)
{
x = (x * (imageWidth / 2)) + (imageWidth / 2);
y = (-y * (imageHeight / 2)) + (imageHeight / 2);
}
};
class Image
{
public:
int imageWidth, imageHeight;
unsigned char* pixels;
Image(int imageWidth, int imageHeight)
{
this->imageWidth = imageWidth;
this->imageHeight = imageHeight;
pixels = new unsigned char[imageWidth * imageHeight * 3];
}
~Image()
{
delete[] pixels;
}
void setPixel(int x, int y, int red, int green, int blue)
{
int help_var = ((y * imageHeight) + x) * 3;
pixels[help_var + 0] = (char)red;
pixels[help_var + 1] = (char)green;
pixels[help_var + 2] = (char)blue;
}
void fillPixels(int red, int green, int blue)
{
int help_var = imageWidth * imageHeight * 3;
for (int i = 0; i < help_var; i += 3) {
pixels[i + 0] = (char)red;
pixels[i + 1] = (char)green;
pixels[i + 2] = (char)blue;
}
}
//-------------------BARYCENTRIC TRIANGLE RASTERISATION------------------------
float edgeFunction(const Vertice& A, const Vertice& B, const Vertice& P)
{
return ((P.x - A.x)*(B.y - A.y) + (P.y - A.y)*(B.x - A.x));
}
void fillTriangleBarycentric(const Vertice& v0, const Vertice& v1, const Vertice& v2)
{
Vertice p(0.0f, 0.0f);
for (int x = 0; x < imageWidth; x++) {
for (int y = 0; y < imageHeight; y++) {
p.x = x + 0.5f; p.y = y + 0.5f;
float w0 = edgeFunction(v1, v2, p);
float w1 = edgeFunction(v2, v0, p);
float w2 = edgeFunction(v0, v1, p);
if (w0 >= 0 && w1 >= 0 && w2 >= 0) {
setPixel(x, y, 0, 0, 255);
}
}
}
}
//-----------------------------------------------------------------------------
};
int main()
{
Image image(800, 600);
image.fillPixels(255, 255, 255);
Vertice a(0.2f, 0.5f);
Vertice b(-0.5f, 0.0f);
Vertice c(0.5f, -0.5f);
a.fitToImage(image.imageWidth, image.imageHeight);
b.fitToImage(image.imageWidth, image.imageHeight);
c.fitToImage(image.imageWidth, image.imageHeight);
image.fillTriangleBarycentric(a, b, c);
std::ofstream imageFile;
imageFile.open("./drawing_triangle_test_image.ppm");
imageFile << "P6\n" << image.imageWidth << " " << image.imageHeight << "\n255\n";
imageFile.write((char*)image.pixels, image.imageWidth * image.imageHeight * 3);
imageFile.close();
return 0;
}
Here is the image I get after running my program.
Thanks for any help!
Here is the better result (where setPixel is using imageWidth instead of imageHeight):
y * imageHeight
Is definitely the type of error your code has (might have multiple instances). You need to multiply the y position by the width. Otherwise, you'll end up interlacing the triangle at random x positions.
The fact that you get four triangles relates to 800/600 simplifying to 4/3. Had you rendered to 797 by 603, you'd probably would have gotten some random mess of horizontal lines.
In addition to #Jeffrey's correction your edge function is also not quite right. It should be
float edgeFunction(const Vertice& A, const Vertice& B, const Vertice& P)
{
return ((P.x - A.x)*(B.y - A.y) - (P.y - A.y)*(B.x - A.x));
}
i.e. there should be a negative sign between the two terms (because it is the cross product of the two position vectors AB and AP).
I am new to SFML and C++ in general.
I am building the Conway's Game of life for a school project.
As base objects for my grid, I have Squares (which are sf::RectangleShape as for base).
The grid is a std::vector<std::vector<Square>> (vector of vectors of Squares).
What I am trying to do at the moment is to change the color of a square when I hover over it with the cursor.
My way of doing it (see code below):
I get the position of cursor when I move it
I iterate through my matrix and check for each square if cursor's position is in the square's boundaries.
When the square under the cursor is found, I want to change its color (.setFillColor(...)).
Point 3 does not work I can't understand why. This is the function "mouseHover" in the code below.
Can you see what is wrong?
int main()
{
int width;
int height;
int numberSquareWidth = 15;
int numberSquareHeight = 15;
int squareSize = 20;
int offset = 1;
initializeWindowGridValues(width, height, numberSquareWidth, numberSquareHeight, squareSize, offset);
sf::RenderWindow window(sf::VideoMode(width, height), "Stephan's Game Of Life!");
std::vector<std::vector<Square>> matrix(numberSquareWidth, std::vector<Square>(numberSquareHeight));
initiatlizeGrid(numberSquareWidth, numberSquareHeight, squareSize, offset, matrix);
sf::Vector2i cursorPos;
while (window.isOpen())
{
sf::Event event;
while (window.pollEvent(event))
{
if (event.type == sf::Event::Closed)
window.close();
if (event.type == sf::Event::MouseMoved)
{
cursorPos = sf::Mouse::getPosition(window);
}
}
mouseHover(matrix, cursorPos, squareSize, offset); // Problem here
window.clear(sf::Color::Black);
drawGrid(window, matrix);
window.display();
}
return 0;
}
void mouseHover(std::vector<std::vector<Square>> &matrix, const sf::Vector2i &cursorPos, const int &squareSize, const int &offset)
{
int rowIndex = floor((cursorPos.x - (offset * floor(cursorPos.x / squareSize))) / squareSize);
int colIndex = floor((cursorPos.y - (offset * floor(cursorPos.y / squareSize))) / squareSize);
matrix[rowIndex][colIndex].setFillColor(sf::Color::Blue); // This does not happen.
}
void drawGrid(sf::RenderWindow &window, const std::vector<std::vector<Square>> &matrix)
{
for (const auto &vector : matrix)
{
for (const auto &square : vector)
{
window.draw(square);
}
}
}
void initiatlizeGrid(const int &numberSquareWidth, const int &numberSquareHeight, const int &squareSize, const int &offset, std::vector<std::vector<Square>> &matrix)
{
int previousY = 0;
for (size_t row = 0; row < numberSquareWidth; row++)
{
int offsetv;
if (row == 0)
{
offsetv = 0;
}
else
{
offsetv = offset;
}
int previousX = 0;
for (size_t col = 0; col < numberSquareHeight; col++)
{
int offseth;
if (col == 0)
{
offseth = 0;
}
else
{
offseth = offset;
}
Square square(squareSize);
square.setPosition(previousX + offseth, previousY + offsetv);
matrix[row][col] = square;
previousX = previousX + squareSize + offseth;
}
previousY = previousY + squareSize + offsetv;
}
}
void initializeWindowGridValues(int &width, int &height, int &nuberSquareWidth, int &nuberSquareHeight, int &squareSize, const int &offset)
{
if (nuberSquareWidth * squareSize + offset * (nuberSquareWidth - 1) > 1800 || nuberSquareHeight * squareSize + offset * (nuberSquareHeight - 1) > 900)
{
nuberSquareWidth = floor(1600 / squareSize);
nuberSquareHeight = floor(900 / squareSize);
width = ceil(nuberSquareWidth * squareSize + offset * (nuberSquareWidth - 1));
height = ceil(nuberSquareHeight * squareSize + offset * (nuberSquareHeight - 1));
}
else if (nuberSquareWidth < 5 || nuberSquareHeight < 5)
{
nuberSquareWidth = 5;
nuberSquareHeight = 5;
width = ceil(nuberSquareWidth * squareSize + offset * (nuberSquareWidth - 1));
height = ceil(nuberSquareHeight * squareSize + offset * (nuberSquareHeight - 1));
}
else
{
width = ceil(nuberSquareWidth * squareSize + offset * (nuberSquareWidth - 1));
height = ceil(nuberSquareHeight * squareSize + offset * (nuberSquareHeight - 1));
}
}
The problem was that I have both inherited the RectangleShape (my square IS A RectangleShape) and made a RectangleShape (square) a member of myclass. When I modify data, I modify class member variables, but inside the draw method I draw the other rectangle.
I removed the class member RectangleShape and continue from here.
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.