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
    评论
#include "stdafx.h" #include <GL/glut.h> #include <stdlib.h> #include <stdio.h> #define stripeImageWidth 32 GLubyte stripeImage[4 * stripeImageWidth]; #ifdef GL_VERSION_1_1 static GLuint texName; #endif void makeStripeImage(void) { int j; for (j = 0; j < stripeImageWidth; j++) { stripeImage[4 * j] = (GLubyte)((j <= 4) ? 255 : 0); stripeImage[4 * j + 1] = (GLubyte)((j>4) ? 255 : 0); stripeImage[4 * j + 2] = (GLubyte)0; stripeImage[4 * j + 3] = (GLubyte)255; } } /* planes for texture coordinate generation */ static GLfloat xequalzero[] = { 1.0, 0.0, 0.0, 0.0 }; static GLfloat slanted[] = { 1.0, 1.0, 1.0, 0.0 }; static GLfloat *currentCoeff; static GLenum currentPlane; static GLint currentGenMode; static float roangles; static float roangles1; float roangles2 = -2; float roangles3 = -3; void SpecialKeys(int key, int x, int y) { if (key == GLUT_KEY_F1) roangles += 2.0f; roangles2 += 0.05; roangles3 += 1; if (key == GLUT_KEY_F2) roangles1 += 2.0f; if (roangles2 >= 3) roangles2 = -3; // 使用新的坐标重新绘制场景 glutPostRedisplay(); } void init(void) { glClearColor(1.0, 1.0, 1.0, 0.0); glEnable(GL_DEPTH_TEST); glShadeModel(GL_SMOOTH); makeStripeImage(); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); #ifdef GL_VERSION_1_1 glGenTextures(1, &texName;); glBindTexture(GL_TEXTURE_1D, texName); #endif glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); #ifdef GL_VERSION_1_1 glTexImage1D(GL_TEXTURE_1D, 0, GL_RGBA, stripeImageWidth, 0, GL_RGBA, GL_UNSIGNED_BYTE, stripeImage); #else glTexImage1D(GL_TEXTURE_1D, 0, 4, stripeImageWidth, 0, GL_RGBA, GL_UNSIGNED_BYTE, stripeImage); #endif glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); currentCoeff = xequalzero; currentGenMode = GL_OBJECT_LINEAR; currentPlane = GL_OBJECT_PLANE; glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, currentGenMode); glTexGenfv(GL_S, currentPlane, currentCoeff); glEnable(GL_TEXTURE_GEN_S); glEnable(GL_TEXTURE_1D); //glEnable(GL_CULL_FACE); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glEnable(GL_AUTO_NORMAL); glEnable(GL_NORMALIZE); glFrontFace(GL_CW); //glCullFace(GL_BACK); glMaterialf(GL_FRONT, GL_SHININESS, 64.0); roangles = 45.0f; roangles1 = 362.0f; } void display(void) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glPushMatrix(); glBegin(GL_QUADS); glColor3f(1, 0, 1); glVertex3f(-1, -1, 0); glColor3f(1, 0, 1); glVertex3f(-3, -1, 0); glColor3f(1, 0, 1); glVertex3f(1, -1, 0); glColor3f(1, 0, 1); glVertex3f(-1, -2, 0); glEnd(); glPopMatrix(); glPushMatrix(); glTranslated(roangles2, 2, -3); glRotatef(roangles, 0.0, 1.0, 0.0); #ifdef GL_VERSION_1_1 glBindTexture(GL_TEXTURE_1D, texName); #endif //glutSolidTeapot(2.0); glutSolidSphere(0.8, 32, 32); glPopMatrix(); glFlush(); glPushMatrix(); glTranslated(1, 2, -3); glRotatef(roangles1, 1.0, 0.0, 0.0); glRotatef(roangles3, 0.0, 1.0, 0.0); #ifdef GL_VERSION_1_1 glBindTexture(GL_TEXTURE_1D, texName); #endif //glutSolidTeapot(2.0); glTranslated(-1, -3, -0); glRotatef(90, 1.0f, 0.0f, 0.0f); glRotatef(180, 0.0f, 1.0f, 0.0f); glRotatef(-30, 0.0f, 0.0f, 1.0f); glutSolidCone(1, 2, 32, 32); glPopMatrix(); glFlush(); } void reshape(int w, int h) { glViewport(0, 0, (GLsizei)w, (GLsizei)h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); if (w <= h) glOrtho(-3.5, 3.5, -3.5*(GLfloat)h / (GLfloat)w, 3.5*(GLfloat)h / (GLfloat)w, -3.5, 3.5); else glOrtho(-3.5*(GLfloat)w / (GLfloat)h, 3.5*(GLfloat)w / (GLfloat)h, -3.5, 3.5, -3.5, 3.5); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } void idle() { roangles += 0.1f; glutPostRedisplay(); } int main(int argc, char** argv) { glutInit(&argc;, argv); glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH); glutInitWindowSize(600, 600); glutInitWindowPosition(100, 100); glutCreateWindow(argv[0]); //glutIdleFunc(idle); init(); glutDisplayFunc(display); glutReshapeFunc(reshape); glutSpecialFunc(SpecialKeys); glutMainLoop(); return 0; }

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值