SeedyROM
SeedyROM

Reputation: 2443

Drawing a simple 2D grid of rectangles

Basically I want to achieve is a collection of rectangles right next to each other, that I can control from an array. I can't seem to find any reliable information on something this stupidly simple, as most tutorials take too big a jump for me to find helpful. So far I can't even get it to render the grid, it draws it incredibly large. (For some reason?)

The Source

#include <cstdlib>
#include <iostream>
#include <GLUT/GLUT.h>

void display();
void resize(int, int);
void timer(int);

#define SCREEN 512
#define REFRESH 30

const int GRID = 8;

/* Main function: GLUT runs as a console application starting at main()  */
int main(int argc, char** argv) {
    glutInit(&argc, argv);                 // Initialize GLUT
    glutCreateWindow("OpenGL Setup Test"); // Create a window with the given title
    glutInitWindowSize(SCREEN, SCREEN);   // Set the window's initial width & height
    glutTimerFunc(0, timer, 0);
    glutInitWindowPosition(0, SCREEN); // Position the window's initial top-left corner
    glutDisplayFunc(display); // Register display callback handler for window re-paint
    glutInitDisplayMode(GLUT_DOUBLE);
    glutReshapeFunc(resize);
    glutMainLoop();           // Enter the event-processing loop
    return 0;
}

/* Handler for window-repaint event. Call back when the window first appears and
 whenever the window needs to be re-painted. */
void display() {
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // Set background color to black and opaque
    glClear(GL_COLOR_BUFFER_BIT);         // Clear the color buffer (background)
    glMatrixMode(GL_MODELVIEW);     // To operate on Model-View matrix
    glLoadIdentity();

    for(int x=0; x < SCREEN; x+=GRID)
    {
        for(int y=0; y < SCREEN; y+=GRID)
        {
            // Draw a Red 1x1 Square centered at origin
            glPushMatrix();
            glTranslatef((1.0f/x)*GRID, (1.0f/y)*GRID, 0);

            //std::cout << (GLfloat)1/x << " : " << (GLfloat)1/y << std::endl;

            glBegin(GL_QUADS);              // Each set of 4 vertices form a quad
            glColor3f(1.0f, 0.0f, 0.0f); // Red
            glVertex2f(-1.0f/GRID, -1.0f/GRID);    // x, y
            glVertex2f( 1.0f/GRID, -1.0f/GRID);
            glVertex2f( 1.0f/GRID,  1.0f/GRID);
            glVertex2f(-1.0f/GRID,  1.0f/GRID);
            glEnd();

            glPopMatrix();
        }
    }

    /*glBegin(GL_QUADS);              // Each set of 4 vertices form a quad
    glColor3f(1.0f, 0.0f, 0.0f); // Red
    glVertex2f(-0.005, -0.005);    // x, y
    glVertex2f( 0.005, -0.005);
    glVertex2f( 0.005,  0.005);
    glVertex2f(-0.005,  0.005);
    glEnd();*/

    glFlush();  // Render now
}

/* Called back when timer expired */
void timer(int value) {
    glutPostRedisplay();      // Post re-paint request to activate display()
    glutTimerFunc(REFRESH, timer, 0); // next Timer call milliseconds later
}

void resize(int width, int height) {
    // we ignore the params and do:
    glutReshapeWindow( 600, 600);
    gluOrtho2D(0, 0, width, height);
    glTranslatef(-0.5, -0.5, 0);
    glViewport(0, 0, width, height);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
}

What It Looks Like

What I'm seeing!

Upvotes: 1

Views: 6085

Answers (1)

Reto Koradi
Reto Koradi

Reputation: 54572

Let's first define what I believe your values mean, because it seems like you're not using them as you intended:

  • SCREEN: Size of window, in pixels.
  • GRID: Size of each quad, in pixels.

So the number of quads that can fit in each direction is SCREEN / GRID. This value can be calculated once, before the draw loops:

int quadCount = SCREEN / GRID;

The next important part is understanding the OpenGL coordinate system. If you don't apply any transformations (and there's really no need to for your use case), the range of x and y that are mapped to the window is from -1.0f to 1.0f. So to fill the window, the coordinates of all quads need to fill the [-1.0f, 1.0f] range in both directions.

Since the range of coordinates you need to produce is 2.0f (from -1.0f to 1.0f), the width/height of each quad in this coordinate system is 2.0f / quadCount. I would calculate this value once outside the nested loops:

float quadSize = 2.0f / static_cast<float>(quadCount);

Now, to place the quads at a given position, their size needs to be multiplied by their index. And remember again, that the coordinates start at (-1.0f, -1.0f). So the rendering code could look like this:

glBegin(GL_QUADS);
glColor3f(1.0f, 0.0f, 0.0f);

for (int x = 0; x < quadCount; ++x)
{
    float xPos = -1.0f + x * quadSize;

    for (int y = 0; y < quadCount; ++y)
    {
        float yPos = -1.0f + y * quadSize;

        glVertex2f(xPos,            yPos);
        glVertex2f(xPos + quadSize, yPos);
        glVertex2f(xPos + quadSize, yPos + quadSize);
        glVertex2f(xPos,            yPos + quadSize);
    }
}

glEnd();

Upvotes: 6

Related Questions