seedFilling & glReadPixels

  • 部分转载自:here

图形学作业

  • 种子填充画五角星
#include <GL/glut.h>
#include <stdlib.h>
#include <unistd.h>
#include <iostream>
#include <math.h>
using namespace std;
float pCenter[2];
float Length, angle = 0;
float R, G, B;
int wWidth,wHeight;
float *rgb;
int PosX, PosY;
int vis[1000][1000];
const double PI = acos(-1.0);
typedef struct tagDIRECTION
{
    int x_offset;
    int y_offset;
} DIRECTION;
// DIRECTION direction_8[] = { {-1, 0}, {-1, 1}, {0, 1}, {1, 1}, {1, 0}, {1, -1}, {0, -1}, {-1, -1} };
DIRECTION direction_4[] = { { -1, 0}, {0, 1}, {1, 0}, {0, -1}};
float* GetPixel(int x, int y)
{
    float *rgb = new float[3];
    glReadPixels(x, y, 1, 1, GL_RGB, GL_FLOAT, rgb);
    return rgb;
}
void myDraw(float Pos[2], float Length, float theta)
{
    // cout << Pos[0] << " " << Pos[1] << endl;
    glBegin(GL_LINE_LOOP);
    float Short = Length * sin(0.1 * PI) / sin(0.7 * PI);
    float beta = 18 + theta; //五角星NE的长半径和x轴的夹角
    float p1[2];
    glColor3f(R, G, B);
    for (int i = 0; i < 5; i++) //从最右边的那个长边顶点开始画
    {
        p1[0] = Length * cos(i * 2 * 0.2 * PI + beta * 3.1415926 / 180.0) + Pos[0]; //x坐标 18 * 3.1415926 = 56.55
        p1[1] = Length * sin(i * 2 * 0.2 * PI + beta * 3.1415926 / 180.0) + Pos[1]; //y坐标
        glVertex2fv(p1);
        p1[0] = Short * cos((i * 2 + 1) * 0.2 * PI + beta * 3.1415926 / 180.0) + Pos[0];
        p1[1] = Short * sin((i * 2 + 1) * 0.2 * PI + beta * 3.1415926 / 180.0) + Pos[1];
        glVertex2fv(p1);
    }
    glEnd();
}
void myDraw1(float Pos[2], float Length, float theta)
{
    // cout << Pos[0] << " " << Pos[1] << endl;
    // glBegin(GL_LINE_LOOP);
    glBegin(GL_TRIANGLES);
    float Short = Length * sin(0.1 * PI) / sin(0.7 * PI);
    float beta = 18 + theta; //五角星NE的长半径和x轴的夹角
    float p1[2], p2[2];
    glColor3f(R, G, B);
    p2[0] = Short * cos(4 * 2 * 0.2 * PI + beta * 3.1415926 / 180.0) + Pos[0]; //x坐标 18 * 3.1415926 = 56.55
    p2[1] = Short * sin(4 * 2 * 0.2 * PI + beta * 3.1415926 / 180.0) + Pos[1]; //y坐标
    for (int i = 0; i < 5; i++) //从最右边的那个长边顶点开始画
    {
        p1[0] = Length * cos(i * 2 * 0.2 * PI + beta * 3.1415926 / 180.0) + Pos[0]; //x坐标 18 * 3.1415926 = 56.55
        p1[1] = Length * sin(i * 2 * 0.2 * PI + beta * 3.1415926 / 180.0) + Pos[1]; //y坐标
        glVertex2fv(p2);
        glVertex2fv(Pos);
        glVertex2fv(p1);
        p2[0] = p1[0], p2[1] = p1[1];
        p1[0] = Short * cos((i * 2 + 1) * 0.2 * PI + beta * 3.1415926 / 180.0) + Pos[0];
        p1[1] = Short * sin((i * 2 + 1) * 0.2 * PI + beta * 3.1415926 / 180.0) + Pos[1];
        glVertex2fv(p2);
        glVertex2fv(Pos);
        glVertex2fv(p1);
        p2[0] = p1[0], p2[1] = p1[1];
    }
    glEnd();
}
void myDraw2(float Pos[2], float Length, float theta)
{
    // cout << Pos[0] << " " << Pos[1] << endl;
    // glBegin(GL_LINE_LOOP);
    glBegin(GL_TRIANGLES);
    float Short = Length * sin(0.1 * PI) / sin(0.7 * PI);
    float beta = 18 + theta; //五角星NE的长半径和x轴的夹角
    float p1[2], p2[2];
    glColor3f(R, G, B);
    p2[0] = Short * cos(4 * 2 * 0.2 * PI + beta * 3.1415926 / 180.0) + Pos[0]; //x坐标 18 * 3.1415926 = 56.55
    p2[1] = Short * sin(4 * 2 * 0.2 * PI + beta * 3.1415926 / 180.0) + Pos[1]; //y坐标
    for (int i = 0; i < 5; i++) //从最右边的那个长边顶点开始画
    {
        p1[0] = Length * cos(i * 2 * 0.2 * PI + beta * 3.1415926 / 180.0) + Pos[0]; //x坐标 18 * 3.1415926 = 56.55
        p1[1] = Length * sin(i * 2 * 0.2 * PI + beta * 3.1415926 / 180.0) + Pos[1]; //y坐标
        glColor3f(1, 1, 0);
        glVertex2fv(p2);
        glVertex2fv(Pos);
        glVertex2fv(p1);
        p2[0] = p1[0], p2[1] = p1[1];
        p1[0] = Short * cos((i * 2 + 1) * 0.2 * PI + beta * 3.1415926 / 180.0) + Pos[0];
        p1[1] = Short * sin((i * 2 + 1) * 0.2 * PI + beta * 3.1415926 / 180.0) + Pos[1];
        glColor3f(1, 0, 1);
        glVertex2fv(p2);
        glVertex2fv(Pos);
        glVertex2fv(p1);
        p2[0] = p1[0], p2[1] = p1[1];
    }
    glEnd();
}
void seedFilling(int x, int y)
{
    // usleep(10000); //4个0的速度还可以忍受
    rgb = GetPixel(x - 1, y); //经过测试发现,前面绘制时会绘制到x - 1, y这个像素点
    if (rgb[0] == 1) return;
    glColor3f(0, 0, 1);
    glBegin(GL_POINTS);
    glVertex2i(x, y);
    glEnd();
    vis[x][y] = 1;
    for (int i = 0; i < 4; i++)
    {
        int xx = x + direction_4[i].x_offset;
        int yy = y + direction_4[i].y_offset;
        if (!vis[xx][yy])
            seedFilling(xx, yy);
    }
    glFlush();
}
void display()
{
    glClearColor(0, 1, 0, 0);
    glClear(GL_COLOR_BUFFER_BIT);
    // // test
    // glColor3f(1, 0, 0);
    // glBegin(GL_POINTS);
    // glVertex2i(100, 100);
    // glEnd();
    // glFlush();
    // for (int i = 80; i <= 120; i++)
    // {
    //     for (int j = 80; j <= 120; j++)
    //     {
    //         rgb = GetPixel(i, j);
    //         if (rgb[0] == 1)
    //         {
    //             cout << i << " " << j << "Pos " << '\t';
    //             cout << rgb[0] << " " << rgb[1] << endl;
    //         } // 对应于glVertex2i(100, 100); 得到的结果是 99, 100
    //     }
    // }
    pCenter[0] = 100; pCenter[1] = 100; Length = 50;
    myDraw1(pCenter, Length, angle);
    pCenter[0] = 200; pCenter[1] = 200; Length = 50;
    myDraw2(pCenter, Length, angle);
    // 种子填充 小bug ,可能中间又一次绘制不了
    pCenter[0] = 300; pCenter[1] = 300; Length = 50;
    myDraw(pCenter, Length, angle);
    // cout << (int)pCenter[0] << " " << pCenter[1] << endl;
    seedFilling((int)pCenter[0], (int)pCenter[1]);
    glFlush();
}
void Reshape(GLsizei w, GLsizei h)
{
    // seedFilling(300, 300);
    cout << "hello" << endl;
    cout << w << " " << h << endl;
    glViewport(0, 0, w, h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    // gluOrtho2D(0, w, 0, h);
    // cout << "hello" << endl;
    // seedFilling((int)pCenter[0], (int)pCenter[1]);
    // seedFilling(300, 300);
    // wWidth = w;
    // wHeight = h;
    // glMatrixMode (GL_PROJECTION);
    // glLoadIdentity ();
    // gluOrtho2D(-w/2, w/2, -h/2, h/2);
    // glMatrixMode (GL_MODELVIEW);
    // glLoadIdentity ();
    // glViewport (0, 0, w, h);
}
int main(int argc, char*argv[])
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DEPTH | GLUT_SINGLE | GLUT_RGB);
    glutInitWindowPosition(300, 300);
    glutInitWindowSize(400, 400);
    glutCreateWindow("test");
    R = 1, G = 0, B = 0; //全局定义颜色
    PosX = 400; PosY = 400;
    gluOrtho2D(0, PosX, 0, PosY);
    glutDisplayFunc(display);
    glutReshapeFunc(Reshape);
    glutMainLoop();
    return 0;
}

void glReadPixels(GLint x,GLint y,GLsizesi width,GLsizei height,GLenum format,GLenum type,GLvoid *pixel);

  • 该函数总共有七个参数。前四个参数可以得到一个矩形,该矩形所包括的像素都会被读取出来。(第一、二个参数表示了矩形的左下角横、纵坐标,坐标以窗口最左下角为零,最右上角为最大值;第三、四个参数表示了矩形的宽度和高度)
  • 第五个参数表示读取的内容,例如:GL_RGB就会依次读取像素的红、绿、蓝三种数据,GL_RGBA则会依次读取像素的红、绿、蓝、alpha四种数据,GL_RED则只读取像素的红色数据(类似的还有GL_GREEN,GL_BLUE,以及GL_ALPHA)。如果采用的不是RGBA颜色模式,而是采用颜色索引模式,则也可以使用GL_COLOR_INDEX来读取像素的颜色索引。目前仅需要知道这些,但实际上还可以读取其它内容,例如深度缓冲区的深度数据等。
  • 第六个参数表示读取的内容保存到内存时所使用的格式,例如:GL_UNSIGNED_BYTE会把各种数据保存为GLubyte,GL_FLOAT会把各种数据保存为GLfloat等。
  • 第七个参数表示一个指针,像素数据被读取后,将被保存到这个指针所表示的地址。注意,需要保证该地址有足够的可以使用的空间,以容纳读取的像素数据。例如一幅大小为256*256的图象,如果读取其RGB数据,且每一数据被保存为GLubyte。
  • 好了,那么重点来了,这个方法的坐标基准点是在画布的左下角!!而我们绘图的基准点是在画布的正中心!!所以我在获取某个点的颜色的时候一直都是错误的结果,这样的话在使用的时候我们的xy坐标值就要加上画布宽高的一半才能正常获取到像素的颜色,希望大家一定注意!!
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值