OpenGL利用橡皮筋技术绘制简单图形(直线、圆、矩形、三角形)

总结出以下经验:

  • 想清空屏幕时,要用双缓冲模式,因为单缓冲模式清空时没反应,只会在下一次绘制时清空原来的图形。双缓冲模式可以立即清空屏幕。
  • glutMotionFunc() 函数和 glutPassiveMotionFunc() 函数不同。后者在鼠标按键按下后不再跟踪鼠标位置,前者是在鼠标按下后松开前跟踪鼠标位置。

代码:

#include <windows.h>
#ifdef __APPLE__
#include <GLUT/glut.h>
#else
#include <GL/glut.h>
#endif
#include <bits/stdc++.h>
using namespace std;
#include <stdlib.h>
const int maxn = 1e5+5;
const double PI = acos(-1.0);

static GLsizei iMode = 1;
static GLboolean IsFill = false;

int iPointNum = 0;
double x1=0, x2=0, y1=0, y2=0;
int winWidth = 400, winHeight = 300;

void Initial(){
    glClearColor(1, 1, 1, 1); // 背景颜色
}
void ChangeSize(int w, int h){
    winWidth = w; winHeight = h;
    glViewport(0, 0, w, h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluOrtho2D(0, winWidth, 0, winHeight);
}
namespace Draw_Graph{
    void DrawLine(double x1, double y1, double x2, double y2){
        glBegin(GL_LINES);
            glVertex2f(x1, y1);
            glVertex2f(x2, y2);
        glEnd();
    }
    void DrawCircle(double x1, double y1, double x2, double y2){
        double o_x = (x1+x2)/2, o_y = (y1+y2)/2;
        double r = sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
        glBegin(GL_POLYGON);
            int n = 360;
            for(int i=0; i<n; i++)
                glVertex2f(r*cos(2*i*PI/n)+o_x, r*sin(2*i*PI/n)+o_y);
        glEnd();
    }
    void DrawRectangle(double x1, double y1, double x2, double y2){
        glRectf(x1, y1, x2, y2);
    }
    void DrawTriangle(double x1, double y1, double x2, double y2){
        glBegin(GL_POLYGON);
            glVertex2f(x1, y1);
            glVertex2f(x2, y2);
            glVertex2f(2*x1-x2, y2);
        glEnd();
    }
}
using namespace Draw_Graph;

struct Node{
    double x1, y1, x2, y2; int type;
}graph[maxn];
int tot = 0;

void Display(){
    glClear(GL_COLOR_BUFFER_BIT);
    glColor3f(1, 0, 0);
    glPolygonMode(GL_FRONT, GL_FILL);

    for(int i=1; i<=tot; i++){
        switch(graph[i].type){
        case 1: DrawLine(graph[i].x1, graph[i].y1, graph[i].x2, graph[i].y2); break;
        case 2: DrawCircle(graph[i].x1, graph[i].y1, graph[i].x2, graph[i].y2); break;
        case 3: DrawRectangle(graph[i].x1, graph[i].y1, graph[i].x2, graph[i].y2); break;
        case 4: DrawTriangle(graph[i].x1, graph[i].y1, graph[i].x2, graph[i].y2); break;
        }
    }

    if(iPointNum == 1){
        switch(iMode){
        case 1: DrawLine(x1, y1, x2, y2); break;
        case 2: DrawCircle(x1, y1, x2, y2); break;
        case 3: DrawRectangle(x1, y1, x2, y2); break;
        case 4: DrawTriangle(x1, y1, x2, y2); break;
        }
    }
    glutSwapBuffers();
}
void MousePlot(GLint button, GLint action, GLint xMouse, GLint yMouse){

    if(button == GLUT_LEFT_BUTTON && action == GLUT_DOWN){
        if(iPointNum == 0 || iPointNum == 2){
            iPointNum = 1;
            x1 = xMouse; y1 = winHeight - yMouse;
        }
    }

    if(button == GLUT_LEFT_BUTTON && action == GLUT_UP){
        iPointNum = 2;
        x2 = xMouse; y2 = winHeight - yMouse;
        if(!(x1==x2 && y1==y2))
            graph[++tot] = Node{x1, y1, x2, y2, iMode};
        glutPostRedisplay();
    }
}
void MotionMouse(GLint xMouse, GLint yMouse){ //跟踪鼠标按键按下后松开前的位置
    if(iPointNum == 1){
        x2 = xMouse; y2 = winHeight - yMouse;
        glutPostRedisplay();
    }
}
void ProcessMenu(int value){
    if(value<5) iMode = value;
    if(value == 5) tot = 0;
    glutPostRedisplay();
}
int main(int argc, char **argv)
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE); //清空屏幕时可以立刻显示出效果
    glutInitWindowSize(400, 300);
    glutInitWindowPosition(100, 100);
    glutCreateWindow("橡皮筋技术");

    int nGraphMenu = glutCreateMenu(ProcessMenu);
    glutAddMenuEntry("直线", 1);
    glutAddMenuEntry("圆", 2);
    glutAddMenuEntry("矩形", 3);
    glutAddMenuEntry("三角形", 4);
    glutAddMenuEntry("清屏", 5);
    glutAttachMenu(GLUT_RIGHT_BUTTON);

    glutDisplayFunc(Display);
    glutReshapeFunc(ChangeSize);
    glutMouseFunc(MousePlot);
    glutMotionFunc(MotionMouse);

    Initial();
    glutMainLoop();
}

 

  • 2
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值