opengl paint程序在每次击键时都会改变

时间:2014-01-19 23:12:41

标签: c++ opengl glut

我正在使用OpenGl开发一个简单的绘图程序。其中一个要求是用户能够使用1-7键更改线条的颜色,使用“+”或“ - ”键更改笔划的大小,以及其他几种情况。我已经完成了大部分工作,但这里是我遇到麻烦的地方。每当我按任意键更改下一个笔划时,它都会修改已在屏幕上绘制的所有内容。因此,如果我画了一个白色的波浪线,然后想要改变下一行,我将通过按“1”键绘制为红色,它将改变我已经绘制为红色的白色波浪线。刷子的尺寸和/或形状(三角形和线条)也是如此。

我不期待一步一步的演练,而是关于如何继续的一些建议。

以下是我的参考代码:

#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;
}

2 个答案:

答案 0 :(得分:2)

由于OpenGL作为状态机运行,因此glColor之类的命令会更改颜色,直到再次更改为止。这就是为什么您的其他对象也以所选颜色绘制的原因。您需要在内部保留当前颜色,在绘制线条时设置它,然后在绘制下一个对象时重置它。

例如:

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();
        }
    }
    ...
}

所以你在绘制之前基本上设置了所有相关的状态。或者,您可以在行之前设置颜色并在之后直接重置,因此您无需在其他绘制调用中关注它。

答案 1 :(得分:1)

这更像是家庭作业的提示。

创建一个类/结构顶点,用于存储其中的所有顶点信息,您可以轻松地将它们一起添加。

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

并创建一个列表std::vector<Vertex> vertices;,而不是为每个组件创建多个列表。同样的事情,但它会更清洁。然后你将只使用

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