spearman008
spearman008

Reputation: 87

opengl paint program changing on each keystroke

I am working on a simple paint program using OpenGl. One of the requirements is for the user to be able to change the color of the line using the 1-7 keys, change the size of the stroke with the '+' or '-' keys, and a couple of other cases. I have most of this implemented, but here is where I am having trouble. Whenever I press any key to change the next stroke, it modifies everything that is already drawn on the screen. So if I drew a white squiggle, and then wanted to change the next line I am about to draw to red by pressing the '1' key, it will change the white squiggle I already drew to red. Same goes for size, and/or shape of the brush (triangle and line).

I am not expecting a walkthrough step by step, but some advice on how to proceed.

Here is my code for reference:

#include "stdafx.h"
#include <vector>
#include <gl/glut.h>
#include <gl/gl.h>


#define WINDOW_WIDTH 800
#define WINDOW_HEIGHT 600

std::vector<int>mouseX;
std::vector<int>mouseY;
int size=1;
int num = 0;
bool leftClick = false;



void drawShape(int num)
{
    if (num == 0) // quad brush
    {
        for (unsigned int x = 0; x < mouseX.size(); x++)
        {
            glBegin(GL_POLYGON);
            glVertex2f(mouseX[x] - size, mouseY[x] - size);
            glVertex2f(mouseX[x] + size, mouseY[x] - size);
            glVertex2f(mouseX[x] + size, mouseY[x] + size);
            glVertex2f(mouseX[x] - size, mouseY[x] + size);
            glEnd();
        }
    }
    if (num == 1) //triangle brush
    {
        for (unsigned int x = 0; x < mouseX.size(); x++)
        {
            glBegin(GL_TRIANGLES);
            glVertex2f(mouseX[x] - size, mouseY[x] - size);
            glVertex2f(mouseX[x] + size, mouseY[x] - size);
            glVertex2f(mouseX[x], mouseY[x] + size);
            glEnd();
        }
    }
    if (num == 2) //line brush
    {
        for (unsigned int x = 0; x < mouseX.size(); x++)
        {
            glBegin(GL_LINES);
            glVertex2f(mouseX[x], mouseY[x] - size);
            glVertex2f(mouseX[x], mouseY[x] + size);
            glEnd();
        }
    }
    if (num == 3) // circle brush
    {
        for (unsigned int x = 0; x < mouseX.size(); x++)
        {

        }
    }
    glFlush();
}

void display(void)
{
    glClearColor(0, 0, 0, 0 );
    glClear(GL_COLOR_BUFFER_BIT);
    drawShape(num);
    glFlush();
}

void keyboard(unsigned char key, int x, int y)
{
    switch (key)
    {
        case '1': //change the color to red
            glClear(GL_COLOR_BUFFER_BIT);
            glColor3f(1, 0, 0);
            break;
        case '2': //change the color to green
            glColor3f(0, 1, 0);
            break;
        case '3': //change the color yellow
            glColor3f(1, 1, 0);
            break;
        case '4': //change the color to blue
            glColor3f(0, 0, 1);
            break;
        case '5': //change the color to magenta
            glColor3f(1, 0, 1);
            break;
        case '6': //change the color to cyan
            glColor3f(0, 1, 1);
            break;
        case '7': //change the color to white
            glColor3f(1, 1, 1);
            break;
        case '=': //increase brush size by 2
            if (size < 65)
                size = size * 2;
            break;
        case '-': //decrease brush size by 2
            if (size > 1 )
                size = size / 2;
            break;
        case 'b': //cycle through brushes (0 - quad, 1 - triangle, 2 - line, 3 - circle)
            num++;
            if (num > 3)
                num = 0;
            break;
        case 'c': //clear the screen back to black
            glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
            glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
            break;
        case 'r': //rotate the brush in 10 degree increments

            break;
        //EXTRA CREDIT ***case 'a':*** //a spray paint brush that has the edges blurred (transparent) 
    }
    glutPostRedisplay();
}

void init(void)
{
    glClearColor(0.0, 0.0, 0.0, 0.0);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(0.0, WINDOW_WIDTH - 1, WINDOW_HEIGHT - 1, 0, -1.0, 1.0);
    glMatrixMode(GL_MODELVIEW);
}


void mouse(int button, int action, int x, int y)
{
    if (button == GLUT_LEFT_BUTTON)
    {
        if (action == GLUT_DOWN)
            leftClick = true;
        else
            leftClick = false;
    }
}


void mouseMove(int x, int y)
{
    if (leftClick)
    {
        mouseX.push_back(x);
        mouseY.push_back(y);
        glutPostRedisplay();
    } 
}


int main(int argc, char *argv[])
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
    glutInitWindowSize(WINDOW_WIDTH, WINDOW_HEIGHT);
    glutInitWindowPosition(500, 300);
    glutCreateWindow("Christopher Spear - Assignment 1");
    init();
    glutDisplayFunc(display);
    glutMotionFunc(mouseMove);
    glutMouseFunc(mouse);
    glutKeyboardFunc(keyboard);
    glutMainLoop();
    return 0;
}

Upvotes: 1

Views: 2528

Answers (2)

user1781290
user1781290

Reputation: 2874

Since OpenGL works as a state machine, it commands like glColor will change the color until changed again. This is the reason why your other objects get drawn in the selected color as well. You need to keep the current color internally, set it when you draw your line, then reset it when you draw the next object.

ex:

float lineColor[3];
void keyboard(unsigned char key, int x, int y)
{
    switch (key)
    {
    case '1': //change the color to red
        lineColor[0] = 1.0f;
        lineColor[1] = 0.0f;
        lineColor[2] = 0.0f;
        break;
      ... and so on
     }
}

void drawShape(int num)
{
    if (num == 0) // quad brush
    {
        glColor3f(1.0f, 1.0f, 1.0f);
        for (unsigned int x = 0; x < mouseX.size(); x++)
        {
            glBegin(GL_POLYGON);
            glVertex2f(mouseX[x] - size, mouseY[x] - size);
            glVertex2f(mouseX[x] + size, mouseY[x] - size);
            glVertex2f(mouseX[x] + size, mouseY[x] + size);
            glVertex2f(mouseX[x] - size, mouseY[x] + size);
            glEnd();
        }
    }
    ...
    if (num == 2) //line brush
    {
        glColor3fv(lineColor);
        for (unsigned int x = 0; x < mouseX.size(); x++)
        {
            glBegin(GL_LINES);
            glVertex2f(mouseX[x], mouseY[x] - size);
            glVertex2f(mouseX[x], mouseY[x] + size);
            glEnd();
        }
    }
    ...
}

So you basically set all relevant states before you draw. Alternatively you can set the color before the line and reset it directly afterwards, so you do not need to care about it in the other draw calls.

Upvotes: 2

Gasim
Gasim

Reputation: 7991

This is more of a tip to your homework assignment.

Create a class/struct Vertex that stores all the vertex information in it and you can easily add them together.

struct Vertex {
    float x,y;
    float r,g,b,a;
};

and create one list std::vector<Vertex> vertices;, instead of multiple lists for each component. Its the same thing but it would be cleaner. And then you will just use

glVertex3f(vertices[i].x - size, vertices[i].y - size);

Upvotes: 1

Related Questions