openGL

#include "iostream"
#include <GL/glut.h>  
#include<cmath>
#define PI acos(-1)
using namespace std;

struct MPOINT {
    GLdouble x, y;
    MPOINT(int x, int y) {
        this->x = x;
        this->y = y;
    }
};
struct MPOINT *oldPoint, *curPoint;
GLdouble a, b,angle;//输入为角度,计算时转化为弧度
int flag = 0;

void Line_sin()
{
    glClear(GL_COLOR_BUFFER_BIT);
    glColor3f(1.0f, 0.0f, 0.0f);
    glBegin(GL_LINES);
    {
        glVertex2f(-1.0f, 0.0f);
        glVertex2f(1.0f, 0.0f);         // 以上两个点可以画x轴
        glVertex2f(0.0f, -1.0f);
        glVertex2f(0.0f, 1.0f);         // 以上两个点可以画y轴
    }
    glEnd();
    glBegin(GL_LINE_STRIP);
    {
        for (int i = 0; i < 1000; i++) {
            glVertex2f(i, 100*sin(i*1.0));
        }
    }
    glEnd();
    glFlush();
}


void Show()
{
    const GLfloat factor = 0.1f;
    GLfloat x;
    glClear(GL_COLOR_BUFFER_BIT);
    glColor3f(1.0f, 1.0f, 1.0f);
    glBegin(GL_LINES);
    {
        glVertex2f(-1.0f, 0.0f);
        glVertex2f(1.0f, 0.0f);         // 以上两个点可以画x轴
        glVertex2f(0.0f, -1.0f);
        glVertex2f(0.0f, 1.0f);         // 以上两个点可以画y轴
    }
    glEnd();
    glBegin(GL_POINTS);
    {
        for (x = -1.0f / factor; x < 1.0f / factor; x += 0.01f)
        {
            glVertex2f(x*factor, sin(x)*factor);
        }
    }
    glEnd();
    glFlush();
}


/* 函数用来画图 */
void display(void)
{
    
}

//----------------------------------------------------------------------直线
//1.DDA
void Line_DDA(struct MPOINT* p1, struct MPOINT* p2)
{
    //glClear(GL_COLOR_BUFFER_BIT);
    //glColor3f(1.0f, 0.0f, 0.0f);
    //glPointSize(5);//设置点大小为5像素

    GLdouble Xa = p1->x, Ya = p1->y, Xb = p2->x, Yb = p2->y;
    GLint dx = Xb - Xa, dy = Yb - Ya, steps, k;
    GLdouble xIncrement, yIncrement, x = Xa, y = Ya;
    if (abs(dx) > abs(dy))
        steps = abs(dx);
    else
        steps = abs(dy);
    xIncrement = dx / (GLdouble)steps;
    yIncrement = dy / (GLdouble)steps;
    glBegin(GL_POINTS);
    {
        glVertex2d((GLdouble)round(x), (GLdouble)round(y));
        for (k = 0; k < steps; k++)
        {
            x += xIncrement;
            y += yIncrement;
            glVertex2d((GLdouble)round(x), (GLdouble)round(y));
        }
    }
    glEnd();

    glFlush();
}


//中点Bresenham算法(改进版)
void Line_Bresenham(struct MPOINT* p1, struct MPOINT* p2)
{
    GLint dx = p2->x - p1->x, dy = p2->y - p1->y,x = p1->x, y= p1->y,e=0;
    GLdouble k = (dy) / (GLdouble)dx;
    glBegin(GL_POINTS);
    {
        glVertex2i(round(x), round(y));
        if (k >= 0) {
            if (p1->x > p2->x || ((p1->x == p2->x) &&(p1->y > p2->y))) {
                GLint tmp = p1->x;
                x = p2->x;
                p2->x = tmp;
                tmp = p1->y;
                y  = p2->y;
                p2->y = tmp;
                dx *= -1;
                dy *= -1;
            }
            if (k <= 1)
            {
                e = -dx;
                while (x != p2->x && y != p2->y) {
                    e += 2 * dy;
                    if (e > 0) {
                        if (x < p2->x || y< p2->y) {
                            x++;
                            y++;
                        }
                        else if (x > p2->x || y > p2->y)
                        {
                            x--;
                            y--;
                        }
                        e -= 2 * dx;
                    }
                    else {
                        if (x < p2->x) {
                            x++;
                        }
                        else if(x > p2->x)
                        {
                            x--;
                        }
                    }
                    glVertex2i(round(x), round(y));
                }
            }
            else if (k > 1) {
                e = -dy;
                while (x != p2->x && y != p2->y) {
                    e += 2 * dx;
                    if (e > 0) {
                        if (x < p2->x || y< p2->y) {
                            x++;
                            y++;
                        }
                        else if (x > p2->x || y > p2->y)
                        {
                            x--;
                            y--;
                        }
                        e -= 2 * dy;
                    }
                    else {
                        if (y < p2->y) {
                            y++;
                        }
                        else if (y > p2->y)
                        {
                            y--;
                        }
                    }
                    glVertex2i(round(x), round(y));
                }
            }
        }
        else {
            if (k >= -1)
            {
                e = -dx;
                while (x != p2->x && y != p2->y) {
                    e += abs(dy)*2;
                    if (e > 0) {
                        if (x > p2->x || y< p2->y) {
                            x--;
                            y++;
                        }
                        else if (x < p2->x || y > p2->y)
                        {
                            x++;
                            y--;
                        }
                        e -= abs(dx)*2;
                    }
                    else {
                        if (x < p2->x) {
                            x++;
                        }
                        else if (x > p2->x)
                        {
                            x--;
                        }
                    }
                    glVertex2i(round(x), round(y));
                }

            }
            else 
            {
                e = -dy;
                while (x != p2->x && y != p2->y) {
                    e += 2 * abs(dx);
                    if (e > 0) {
                        if (x > p2->x || y< p2->y) {
                            x--;
                            y++;
                        }
                        else if (x < p2->x || y > p2->y)
                        {
                            x++;
                            y--;
                        }
                        e -= 2 * abs(dy);
                    }
                    else {
                        if (y < p2->y) {
                            y++;
                        }
                        else if (y > p2->y)
                        {
                            y--;
                        }
                    }
                    glVertex2i(round(x), round(y));
                }
            }
        }
    }
    glEnd();
    glFlush();
}

//----------------------------------------------------------------------圆形
//极坐标法 for Ciecle
void Circle_Polar(struct MPOINT *c, GLdouble R)
{ 
    GLint n = 100;
    GLdouble x=c->x, y=c->y;
    glBegin(GL_POINTS);
    {
        for (int i = 0; i < n; i++)
        {
            x =c->x + R * cos(2 * PI *i/ n);
            y =c->y + R * sin(2 * PI *i/ n);
            glVertex2f(x,y);
        }
    }
    glEnd();
    glFlush();
}
//中点Bresenham for Circle
//画点(x,y)和他的7个对称点
void Draw8(struct MPOINT *c,GLdouble x, GLdouble y)
{
    GLdouble X = c->x, Y = c->y;
    glBegin(GL_POINTS);
    {
        glVertex2d(x +X,y + Y);
        glVertex2d(-x +X, y + Y);
        glVertex2d(x + X, -y + Y);
        glVertex2d(-x + X, -y + Y);

        glVertex2d(y + X, x + Y);
        glVertex2d(-y + X, x + Y);
        glVertex2d(y + X, -x + Y);
        glVertex2d(-y + X, -x + Y);
    }
    glEnd();
    glFlush();
}
void Circle_Bresenham(struct MPOINT *c,GLdouble R)
{
    GLdouble d = 1 - R, x = 0, y = R;
    while (x <= y)
    {
        Draw8(c, x ,y);
        if (d <= 0)
        {
            d += 2 * x + 3;
            x++;
        }
        else
        {
            d += 2 * (x-y) + 5;
            x++;
            y--;
        }
    }
}

//DDA for Circle
void Circle_DDA(struct MPOINT *c, GLdouble R)
{
    GLdouble xc = c->x, yc = c->y, x = xc + R, y = yc, theta = 0, e = 1 / R;
    glBegin(GL_POINTS);
    {
        while (theta < 2 * PI) {
            glVertex2f(x, y);
            x = x - (y - yc)*e;
            y = y + (x - xc)*e;
            theta += e;
        }
    }
    glEnd();
    glFlush();
}

//----------------------------------------------------------------------椭圆
//某点绕某点旋转后的新坐标
void getNewPoint(struct MPOINT* c,GLdouble X, GLdouble Y,GLdouble& x,GLdouble& y)
{
    x = (X - c->x)*cos(angle*PI / 180) - (Y - c->y)*sin(angle*PI / 180) + c->x;
    y = (X - c->x)*sin(angle*PI / 180) + (Y - c->y)*cos(angle*PI / 180) + c->y;
}
//画点(x,y)和它的3个对称点
void Draw4(struct MPOINT* c,GLdouble x, GLdouble y)
{
    GLdouble X = c->x, Y = c->y,xn,yn;
    
    glBegin(GL_POINTS);
    {
        /*
        glVertex2f(x+X,y+Y);
        glVertex2f(-x+X, y+Y);
        glVertex2f(x+X, -y+Y);
        glVertex2f(-x+X, -y+Y);
        */
        getNewPoint(c,x + X, y + Y, xn, yn);
        glVertex2f(xn, yn);
        getNewPoint(c, -x + X, y + Y, xn, yn);
        glVertex2f(xn, yn);
        getNewPoint(c, x + X, -y + Y, xn, yn);
        glVertex2f(xn, yn);
        getNewPoint(c, -x + X, -y + Y, xn, yn);
        glVertex2f(xn, yn);
    }
    glEnd();
    glFlush();
}
//中点Bresenham算法 for Oval
void Oval_Bresenham(struct MPOINT* c)
{
    if (a <= 0 || b <= 0) {
        a = 50, b = 10;
    }
    GLdouble d = b * b + a * a*(0.25 - b), x = 0, y = b;
    while (b*b*(x + 1) < a*a*(y - 0.5))
    {
        Draw4(c,x, y);
        if (d <= 0)
        {
            d += b * b*(2 * x + 3);
            x++;
        }
        else
        {
            d += b * b*(2 * x + 3) + a * a*(-2 * y + 2);
            x++;
            y--;
        }
    }

    d = b * b*(x + 0.5)*(x + 0.5) + a * a*(y - 1)*(y - 1) - a * a * b * b;
    while (y >= 0)
    {
        Draw4(c,x,y);
        if (d <= 0)
        {
            d += b*b*(2*x + 2) + a*a*(-2*y + 3);
            x++;
            y--;
        }
        else
        {
            d += a*a*(-2*y + 3),
            y--;
        }
    }
}


//==========================================================================事件========
/*鼠标点击事件 */
void mouseClick(int btn, int state, int x, int y)
{
    if (btn == 0 && state == 1) {
        if (oldPoint == NULL) {
            oldPoint = new MPOINT(x, y);
        }
        else {
            curPoint = new MPOINT(x, y);
        }
    }
    if (btn == 2 && state == 1) {
        flag += 1;
        if (oldPoint == NULL) {
            oldPoint = new MPOINT(x, y);
        }
        else {
            curPoint = new MPOINT(x, y);
        }
    }
    if (oldPoint != NULL && curPoint != NULL) {
        if (flag == 0) {

            Line_DDA(oldPoint, curPoint); // DDA for line
            //Line_Bresenham(oldPoint, curPoint);// Bresenham for Line
        }
        else if (flag == 1) {
            GLdouble R = sqrt(pow(curPoint->x - oldPoint->x, 2) + pow(curPoint->y - oldPoint->y, 2));
            //Circle_DDA(oldPoint, R); // DDA for Circle
            //Circle_Polar(oldPoint,R); // Polar for Circle
            Circle_Bresenham(oldPoint, R); // Bresenham for Circle
        }
        else if (flag == 2) {
            Oval_Bresenham(oldPoint); // Bresenham for Oval
        }
        flag = 0;
        free(oldPoint);
        free(curPoint);
        oldPoint = NULL;
        curPoint = NULL;
    }

    //btn 0 left 2 right state 0 按下 1松开 (x,y)代表坐标
    /*
    printf("点击了鼠标,btn:%d,state:%d,x:%d,y:%d\n", btn, state, x, y);
    if (btn == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {
        printf("按下了左边按钮\n");
    }
    if (btn == GLUT_LEFT_BUTTON && state == GLUT_UP) {
        printf("松开了左边按钮\n");
    }
    if (btn == GLUT_RIGHT_BUTTON && state == GLUT_DOWN) {
        printf("按下了右边按钮\n");
    }
    if (btn == GLUT_RIGHT_BUTTON && state == GLUT_UP) {
        printf("松开了右边按钮\n");
    }
    */
}

//键盘事件
void SpecialKey(GLint c, GLint x, GLint y) {
    if (c == GLUT_KEY_UP) {
        glClear(GL_COLOR_BUFFER_BIT);
        glFlush();
        //exit(0);
    }
    if (c == GLUT_KEY_DOWN) {
        cout << "Please input the  long axis, shaort axis and the rotation angle of Oval\n";
        cin >> a >> b >> angle;
    }
    if (c == 27) {
        exit(0);
    }
}

/* 鼠标移动事件 */
void mouseMove(int x, int y)
{
    printf("移动鼠标中,x:%d,y%d\n", x, y);
}

//============================================== MAIN =============================
int main(int argc, char *argv[])
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE | GLUT_DEPTH);
    glutInitWindowPosition(100, 100);
    glutInitWindowSize(400, 400);
    glutCreateWindow("OpenGL");
    //观察参数:
    //gluOrtho2D(-200.0, 200.0, -200.0, 200.0);
    gluOrtho2D(0, 400.0, 400.0, 0);
    glutDisplayFunc(display);
    /*鼠标点击事件,鼠标点击或者松开时调用 */
    glutMouseFunc(mouseClick);
    /*鼠标移动事件,鼠标按下并移动时调用 */
    glutMotionFunc(mouseMove);
    /*键盘事件,键盘按下时调用 */
    glutSpecialFunc(&SpecialKey);
    glutMainLoop();
    return 0;
}

/*
readme:

连续两次左键:绘制直线
连续两次右键:绘制圆形
一左一右/一右一左:绘制椭圆,输入长轴a,短轴b,偏转角度q
*/

猜你喜欢

转载自www.cnblogs.com/kimsimple/p/9065783.html