Search code examples
c++openglpixelopengl-compat

how to draw a set of coordinates in OpenGL?


I'm trying to make Conway's Game of Life in C++, and am using OpenGL (However I'm pretty new to OpenGL) because it supports negative coordinates and therefore an infinite world.
I have a class called GameOfLife`` which handles the entire world, and has the alive cells as [x, y] coordinates in an vector. Therefore I'm going to use a for loop throughout the alive cells coordinate and render a single pixel for each coordinate.
However whatever I have tried nothing appears on the screen no matter what I do. Below is the code with an empty glBegin and glEnd function. What should I put between these in order for it to render.

I have tried :
dividing each coordinate by 400 to get float for 1 pixel .
adding 1/400 to both x and y for the third and fourth side.

#include "gol.h"
#include <GL/glew.h>
#include <GLFW/glfw3.h>
int main()
{
  std::vector<std::vector<int>> dupl;
  std::ifstream infile { "test.rle" };
  std::string file_contents { std::istreambuf_iterator<char>(infile), std::istreambuf_iterator<char>() };
  parse_rle(file_contents, 0, dupl);
  GameOfLife gol;
  gol.place_cells(dupl);
  //gol.update();
  GLFWwindow* window;
  if (!glfwInit())
    return 1;
  int width  = 400;
  window = glfwCreateWindow(width, width, "Window", NULL, NULL);
  if (!window) {
    glfwTerminate();
    return 1;
  }
  glfwMakeContextCurrent(window);
  if(glewInit()!=GLEW_OK)
    std::cout<<"Error"<<std::endl;
  glEnable(GL_DEPTH_TEST);
  while(!glfwWindowShouldClose(window)) {
    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
    for(std::vector<int> i : gol.alive)
    {
        glBegin(GL_QUADS);

        glEnd();
    }
    glfwSwapBuffers(window);
    glfwPollEvents();
  }
  glfwTerminate();
}

Solution

  • Since the type of the vertex coordinates is an integral data type

    std::vector<std::vector<int>> dupl;
    

    you have to use glVertex2i().

    The vertex coordinates have to be in the rage of normalized device space, which is [-1, 1] for all 3 components (x, y,z). To "project" your vertex coordinates to this range you've to use a projection matrix.

    Define a range wich is grater than the vertex coordinates and set an orthographic projection matrix (see glMatrixMode) by glOrtho, before you draw the geometry.

    double min_x = ..., min_y = ..., max_x = ..., max_y = ...;
    
    glMatrixMode(GL_PROJECTION);
    glOrtho(min_x, max_x, min_y, max_y, -1.0, 1.0);
    
    while(!glfwWindowShouldClose(window) {
        // [...]
    }
    

    Note, that the orthographic projection should als take into account the aspect ration of the viewport.
    e.g. The vertex coordinates are in rage [0, 400] and the aspect ration of the viewport is 16.0/9.0:

    glOrtho(0.0, 400.0*16.0/9.0, 0.0, 400.0, -1.0, 1.0);
    

    If you prefer to use window coordinates and the size of the window is e.g. 800x600:

    glOrtho(0.0, 800.0, 0.0, 600.0, -1.0, 1.0);
    

    The glBegin/glEnd has to enclose at least the vertex coordinates for one Primitive. A GL_QUADS primitive consists of 4 vertex coordinates.
    But you can encapsulate as many quads to 1 sequence as you want. So the for-loop has to be in between glBegin and glEnd:

    glBegin(GL_QUADS);
    for(std::vector<int> &v : gol.alive)
    {
       glVertex2i(v[0], v[1]);
    }
    glEnd();