openGL-设计交互平面图形(旋转、平移、缩放)

综述

最近在学习图形学的一些知识。现在做一个可交互的平面图形。
要求是:
1.三个不同的平面图形
2.可以通过鼠标“各自”进行指定的操作。
3.第二条中操作包括:旋转、平移、缩放
该文章:首先介绍一个图形时候的情况。多个图形不断更新。

环境

我是用xcode写的。但是不用担心,你需要修改的或许只是include头文件的两个字母。

基础知识:

你会在这个过程中遇到一些新的命令,如果你想弄明白可以仔细阅读下述内容。当然你也可以直接跳过。先去阅读最后的代码在回来补充知识

glPushMatrix()命令与glPopMatrix()命令

glPushMatrix、glPopMatrix操作其实就相当于栈里的入栈和出栈。许多人不明白的可能是入的是什么,出的又是什么。例如你当前的坐标系原点在你电脑屏幕的左上方。现在你调用glPushMatrix,然后再调用一堆平移、旋转代码等等,然后再画图。那些平移和旋转都是基于坐上角为原点进行变化的。而且都会改变坐标的位置,经过了这些变化后,你的坐标肯定不再左上角了。那如果想恢复怎么办呢?这时就调用glPopMatrix从栈里取出一个“状态”了,这个状态就是你调用glPushMatrix之前的那个状态。就如很多opengl的书上所讲:调用glPushMatrix其实就是把当前状态做一个副本放入堆栈之中。当你做了一些移动或旋转等变换后,使用glPushMatrix();OpenGL 会把这个变换后的位置和角度保存起来。然后你再随便做第二次移动或旋转变换,再用glPopMatrix();OpenGL 就把刚刚保存的那个位置和角度恢复。

比如:

glLoadIdentity();
glTranslatef(1,0,0);//向右移动(1,0,0)
glPushMatrix();//保存当前位置
glTranslatef(0,1,0);//现在是(1,1,0)了

更详细的可以参见如何理解glPushMatrix与glPopMatrix

glTranslatef()命令

在介绍glPushMatrix与glPopMatrix的例子时。我们看到了glTranslatef命令。那么这个命令是干嘛的呢?
其实这个就是核心:也就是我们的平移函数

glTranslatef()

当然还有旋转函数

glRotatef()

注意这系列函数都是依附于指定的坐标系

void glTranslatef(GLfloat x,GLfloat y,GLfloat z);
/*函数功能:沿X轴正方向平移x个单位(x是有符号数)
  沿Y轴正方向平移y个单位(y是有符号数)
  沿Z轴正方向平移z个单位(z是有符号数)*/
void glRotatef(GLfloat angle,GLfloat x,GLfloat y,GLfloat z);
/*先解释一下旋转方向,做(0,0,0)到(x,y,z)的向量,用右手握住这条向量,大拇指指向向量的正方向,四指环绕的方向就是旋转的方向;
函数功能:以点(0,0,0)到点(x,y,z)为轴,旋转angle角度;
*/

这两个函数,不论是平移还是旋转都是针对于上一个矩阵来说的

glutSwapBuffers()命令

该命令就是双缓冲命令。可以避免更新时的闪烁现象。
具体可以参见:glutSwapBuffers()命令

具体实现

下面就是实现代码:(先给出一个图形时的样子)
代码不多请务必仔细阅读。

无交互的单图形移动代码

//
//  main.cpp
//  CG_Ep1
//
//  Created by SDU_bigbean on 2018/4/3.
//  Copyright © 2018年 SDU_bigbean. All rights reserved.
//
#include <iostream>
#include <GLUT/GLUT.h>
using namespace std;
int hmin,hmax;                                 //记录扫描线开始和结束的位置
float window_size = 800;
GLfloat rtx = 0, rty = 0, rtz = 0;
/*
 实验1说明:
 有三个区域可以选择指定图形进行操作:
 1.平移:使用方向键控制
 2.缩放:支持滚轮缩放
 3.旋转:支持自动控制旋转的速度(使用数字键1、2、3标志)
 */
//注意我们的正方形的大小是100*100的
void InitEnvironment()
{   /*
     函数说明:对环境画布进行初始化操作
     注意这里使用像素坐标系
     */
    glClearColor(0.0,0.0,0.0,0);
    glClear(GL_COLOR_BUFFER_BIT);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    gluOrtho2D(0,window_size,0,window_size);
}
void move()
{
    cout << "comming " <<endl;
    static GLfloat step = 10;
    if (rtx + step > 600|| rtx + step < -100)step = -step;
    //限制范围不能出界
    rtx += step;
    glutPostRedisplay();
}

void display(void)
{   /*绘制三个不同的图形*/
    glClear(GL_COLOR_BUFFER_BIT);
    glPushMatrix();
    //模型视图矩阵堆栈是干嘛用的呢?我们在三维空间中绘制模型,大部分时候需要对模
    //型进行移动、旋转、缩放操作.
    //而OpenGL移动的不是模型,而是坐标系

    glTranslatef(rtx, rty, rtz);//指定坐标系

    glBegin(GL_QUADS);
    glColor3f(1.0f, 0.0f, 0.0f); //这个只是对点着色然后好看些
    glVertex2f(100, 200);
    glColor3f(0.0f, 1.0f, 0.0f);
    glVertex2f(200, 200);
    glColor3f(0.0f, 0.0f, 1.0f);
    glVertex2f(200, 300);
    glColor3f(0.5f, 0.5f, 0.5f);
    glVertex2f(100, 300);
    glEnd();
    glFlush();
    glPopMatrix();
    glutSwapBuffers();// 双缓冲操作。“后台先做好,再放在前台来。”可以有效避免刷新闪烁的问题。
}

int main(int argc, char *argv[])
{   glutInit(&argc, argv);   //初始化GLUT
    glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);
    glutInitWindowPosition(300, 100);
    glutInitWindowSize(window_size, window_size);
    glutCreateWindow("实验1");
    InitEnvironment();   //初始化
    glutDisplayFunc(display);
    glutIdleFunc(move);//进行移动操作
    glutMainLoop();    //持续显示,当窗口改变会重新绘制图形
    return 0;
}

有交互的多图形移动代码

/*
   main.cpp
   CG_Ep1
   Created by SDU_bigbean on 2018/4/6.
   Copyright © 2018年 SDU_bigbean. All rights reserved.
 */
#include <GLUT/GLUT.h>
#include <stdlib.h>
#include<math.h>
#include <iostream>
using namespace std;
//屏幕尺寸
int SCREEN_WIDTH = 600;
int SCREEN_HEIGHT = 600;
int radius = 60;
int flag=1;
float scales = 1.1;
float cut_scales = 0.01;
int init_step = 110;                    //记录一开始各个图形之间的间距
float PI = 3.1415926;
float angles = 0.01;
//存放选中物体的缓冲的尺寸
#define SIZE 500
//选中区域的尺寸
#define N 10
struct obj{
    int index;
    GLfloat rtx0 = 0, rty0 = 0, rtz0 =1;
    GLfloat xmin = 0, ymin = 0, xmax = 0,ymax = 0;
    GLfloat x1= xmin, y1 = ymin, x2 = xmax,y2 = ymin,x3 = xmax,y3 = ymax,x4=xmin,y4=ymax;
    GLfloat xscale = 1.0, yscale = 1.0, zscale = 1.0;
    int l,r,u,d;
};
//当前选中物体
obj obj_con[4];
int select_point = 0;//1 是第一个点,2是第二个,以此类推
int selected=0;
void init()
{
    /*函数说明:
     进行初始化布局*/
    glClearColor(0,0,0,1);
    //首先初始化布局画布
    for (int i =1 ; i<=3; i++) {
        if(i==1){
            obj_con[i].xmin = 0+init_step;
            obj_con[i].xmax = 100+init_step;
            obj_con[i].ymin = 320;
            obj_con[i].ymax = 420;
            obj_con[i].index  = 1;
            obj_con[i].r = 400;
            obj_con[i].l = -120;
            obj_con[i].u = 160;
            obj_con[i].d = -330;
        }else if (i==2) {
            obj_con[i].xmin = 60+2*init_step;
            obj_con[i].xmax = 160+2*init_step;
            obj_con[i].ymin = 320;
            obj_con[i].ymax = 420;
            obj_con[i].index  = 2;
            obj_con[i].r = 230;
            obj_con[i].l = -290;
            obj_con[i].u = 160;
            obj_con[i].d = -330;
        }else{
            obj_con[i].r = 20;
            obj_con[i].l = -480;
            obj_con[i].u = 150;
            obj_con[i].d = -320;
        }
        obj_con[i].x1= obj_con[i].xmin;
        obj_con[i].y1 = obj_con[i].ymin;
        obj_con[i].x2 =obj_con[i]. xmax;
        obj_con[i].y2 = obj_con[i].ymin;
        obj_con[i].x3 = obj_con[i].xmax;
        obj_con[i].y3 = obj_con[i].ymax;
        obj_con[i].x4=obj_con[i].xmin;
        obj_con[i].y4=obj_con[i].ymax;
    }

}
void Drawtri()
{
    /*
     函数说明:绘制圆形并进行颜色填充
     理解为足够小的三角形拼凑成为圆形
     */
    double n=1000;//分段数
    float R=20;//半径
    int i;
    glPushMatrix();
    glColor3f(0.0,0.2,0.8);
    glBegin(GL_TRIANGLE_FAN);
    glVertex2f(0.0,0.0);
    for(i=0; i<=n; i++)
        glVertex2f(R*cos(2*PI/n*i), R*sin(2*PI/n*i));
    glEnd();
    glPopMatrix();
}
void draw(GLenum mode)
{   const static GLfloat color_selected[] = {0.5f,1.0f,0.0f};
    const static GLfloat color_unselected[] = {1.0f,1.0f,1.0f};
    //先绘制指示灯
    glBegin(GL_LINES);
    glColor3f(1.0,1.0,1.0);
    glVertex2f(0,570); //定点坐标范围
    glVertex2f(600,570);
    glBegin(GL_LINES);
    glColor3f(1.0,1.0,1.0);
    glVertex2f(0,574); //定点坐标范围
    glVertex2f(600,574);
    glEnd();
    //模型视图矩阵堆栈是干嘛用的呢?我们在三维空间中绘制模型,大部分时候需要对模
    //型进行移动、旋转、缩放操作.
    //而OpenGL移动的不是模型,而是坐标系
    for(int i=1;i<=3;i++)//5个点
    {
        glPointSize(15);
        glBegin(GL_POINTS);
        glVertex2f(0,0);
        glEnd();
        //我们将每个一个坐标系记录在矩阵栈中
        //为了实现鼠标点击我们将每个图形放入对象栈中
        //我们不将指示灯放入坐标矩阵中
        if (mode == GL_SELECT) glLoadName(i);
        glColor3fv( (selected== i)? color_selected : color_unselected );
        glPointSize(15);
        glBegin(GL_POINTS);
        glVertex2f(20+30*i,587);
        glEnd();
        glPushMatrix();
        if(i==1){
            glTranslatef(obj_con[i].rtx0, obj_con[i].rty0, obj_con[i].rtz0);//指定移动坐标系
            glBegin(GL_QUADS);
            glColor3f(0.0f, 1.0f, 0.0f); //这个只是对点着色然后好看些
            glVertex2f(obj_con[i].x1 ,  obj_con[i].y1);
            glColor3f(1.0f, 0.0f, 0.0f);
            glVertex2f(obj_con[i].x2 , obj_con[i].y2);
            glColor3f(0.0f, 0.0f, 1.0f);
            glVertex2f(obj_con[i].x3, obj_con[i].y3);
            glColor3f(0.5f, 0.5f, 0.5f);
            glVertex2f(obj_con[i].x4 ,  obj_con[i].y4);
            glEnd();
        }
        else if(i==2) {
            glTranslatef(obj_con[i].rtx0, obj_con[i].rty0, obj_con[i].rtz0);//指定移动坐标系
            glBegin(GL_TRIANGLES);
            glColor3f(0.0f, 1.0f, 0.0f); //这个只是对点着色然后好看些
            glVertex2f(obj_con[i].x1 ,  obj_con[i].y1);
            glColor3f(1.0f, 0.0f, 0.0f);
            glVertex2f(obj_con[i].x2, obj_con[i].y2);
            glColor3f(0.0f, 0.0f, 1.0f);
            glVertex2f(obj_con[i].x3, obj_con[i].y3);
            glEnd();
        }else{
            glTranslatef(obj_con[i].rtx0, obj_con[i].rty0, obj_con[i].rtz0);//指定移动坐标系
            obj_con[i].xmin = 200+3*init_step;
            obj_con[i].ymin = 370;
            obj_con[i].index  = 3;
            int count;
            int sections=10000;
            GLfloat TWOPI=2.0f * 3.14159f;
            glBegin(GL_TRIANGLE_FAN);
            glVertex2f(obj_con[i].xmin, obj_con[i].ymin);
            glColor3f(1.0f, 0.8f, 0.3f);
            for(count=0; count<=sections; count++)
                glVertex2f( obj_con[i].xmin +radius*cos(count*TWOPI/sections), obj_con[i].ymin+radius*sin(count*TWOPI/sections));
            glEnd();
        }//这里设置我们的图形
        glPopMatrix();
    }
    glutSwapBuffers();
}
void display()
{   glClear(GL_COLOR_BUFFER_BIT);
    draw(GL_RENDER);
    glFlush();
}
void reshape(int width, int height)
{
    glViewport(0, 0, width, height);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluOrtho2D(0,SCREEN_WIDTH,0,SCREEN_HEIGHT);
    glMatrixMode(GL_MODELVIEW);
}
void processHits(GLint hits, GLuint buffer[])
{
    unsigned int i,j;
    GLuint name;
    for(i=0; i<hits;i++)
    {
        name = buffer[3+i*4];
        select_point = name;//每个选中物体有占用名字栈中4个单位,第4个是物体名字的值
        selected  = name;
    }
}
double get_x(double x, double y, double theta) {
    //得到旋转后的x坐标
    return x * cos(theta) - sin(theta) * y;
}
double get_y(double x , double y, double theta) {
    //得到旋转后的y坐标
    return x * sin(theta) + cos(theta) * y;
}
void show_point(int x){
    /*
     函数说明:控制指示灯的闪亮情况
     */
    glBegin(GL_POINTS);
    glPointSize(15);
    glColor3f(1.0,1.0,0.0);
    glVertex2f(20+30*x,787);
    glEnd();
}
void move_to_o(){
    /*函数说明:先将物体移动到原点
     再进行目标操作(旋转放缩)
     */
    float x  = ( obj_con[selected].xmin+obj_con[selected].xmax)/2;
    float y  = ( obj_con[selected].ymin+obj_con[selected].ymax)/2;
    obj_con[selected].x1 -= x;
    obj_con[selected].x2 -= x;
    obj_con[selected].x3 -= x;
    obj_con[selected].x4 -= x;
    obj_con[selected].y1 -= y;
    obj_con[selected].y2 -= y;
    obj_con[selected].y3 -= y;
    obj_con[selected].y4 -= y;
}
void move_back(){
    /*
     函数说明:将移动到原点的物体移动回到原来的位置
     */
    float x  = ( obj_con[selected].xmin+obj_con[selected].xmax)/2;
    float y  = ( obj_con[selected].ymin+obj_con[selected].ymax)/2;
    obj_con[selected].x1 += x;
    obj_con[selected].x2 += x;
    obj_con[selected].x3 += x;
    obj_con[selected].x4 += x;
    obj_con[selected].y1 += y;
    obj_con[selected].y2 += y;
    obj_con[selected].y3 += y;
    obj_con[selected].y4 += y;
}
void move_to_o2(){
    /*函数说明:先将物体移动到原点
     该函数控制的是错切变换的结果
     */
    float x  = ( obj_con[selected].xmin+obj_con[selected].xmax)/2 -(obj_con[selected].xmax  -obj_con[selected].xmin)/2 ;
    float y  = ( obj_con[selected].ymin+obj_con[selected].ymax)/2-(obj_con[selected].ymax  -obj_con[selected].ymin)/2 ;
    obj_con[selected].x1 -= x;
    obj_con[selected].x2 -= x;
    obj_con[selected].x3 -= x;
    obj_con[selected].x4 -= x;
    obj_con[selected].y1 -= y;
    obj_con[selected].y2 -= y;
    obj_con[selected].y3 -= y;
    obj_con[selected].y4 -= y;
}
void move_back2(){
    /*
     函数说明:将移动到原点的物体移动回到原来的位置
     该函数控制的是错切变换的结果
     */
    float x  = ( obj_con[selected].xmin+obj_con[selected].xmax)/2-(obj_con[selected].xmax  -obj_con[selected].xmin)/2 ;
    float y  = ( obj_con[selected].ymin+obj_con[selected].ymax)/2-(obj_con[selected].ymax  -obj_con[selected].ymin)/2 ;
    obj_con[selected].x1 += x;
    obj_con[selected].x2 += x;
    obj_con[selected].x3 += x;
    obj_con[selected].x4 += x;
    obj_con[selected].y1 += y;
    obj_con[selected].y2 += y;
    obj_con[selected].y3 += y;
    obj_con[selected].y4 += y;
}
/*
 注意下述旋转、错切、平移、放缩等
 都需要实现进行移动坐标在移动回来
 */
void rotato(){
    /*
     函数说明:进行旋转操作
     */
    obj_con[selected].x1 =   get_x( obj_con[selected].x1,  obj_con[selected].y1, angles);
    obj_con[selected].y1 =   get_y( obj_con[selected].x1,  obj_con[selected].y1, angles);
    obj_con[selected].x2 =   get_x( obj_con[selected].x2,  obj_con[selected].y2, angles);
    obj_con[selected].y2=   get_y( obj_con[selected].x2,  obj_con[selected].y2, angles);
    obj_con[selected].x3 =   get_x( obj_con[selected].x3,  obj_con[selected].y3, angles);
    obj_con[selected].y3=   get_y( obj_con[selected].x3,  obj_con[selected].y3, angles);
    obj_con[selected].x4=   get_x( obj_con[selected].x4,  obj_con[selected].y4, angles);
    obj_con[selected].y4=   get_y( obj_con[selected].x4,  obj_con[selected].y4, angles);
}
void cut_move(int flag,int flage){
    /*函数说明:进行指定方向的错切操作
     参数说明:第一个参数flag指定x方向和y方向 0,1
     第二个参数flage指定是放大还是缩小
     */
    float sc  = cut_scales;
    if (flage==1)      //看是放大还是缩小
        sc = -sc;
    if (flag ==1) {
        /*x = cx+y
         保持y不变*/
        obj_con[selected].x1 =sc*obj_con[selected].y1+obj_con[selected].x1 ;
        obj_con[selected].x2 =sc*obj_con[selected].y2+obj_con[selected].x2 ;
        obj_con[selected].x3 =sc*obj_con[selected].y3+obj_con[selected].x3 ;
        obj_con[selected].x4 =sc*obj_con[selected].y4+obj_con[selected].x4 ;
    }else if (flag ==2) {
        obj_con[selected].y1 =sc*obj_con[selected].x1+obj_con[selected].y1 ;
        obj_con[selected].y2 =sc*obj_con[selected].x2+obj_con[selected].y2 ;
        obj_con[selected].y3 =sc*obj_con[selected].x3+obj_con[selected].y3 ;
        obj_con[selected].y4 =sc*obj_con[selected].x4+obj_con[selected].y4 ;
    }
}
void enlarge(int flag,int flage){
    /*函数说明:进行指定方向的放缩操作
       参数说明:第一个参数flag指定x方向和y方向以及全方向
                      第二个参数flage指定是放大还是缩小
     */
    float sc  = scales;
    if (flage==1)
        sc = 1/sc;  //判断是放大还是缩小
    if (flag ==1) {
        obj_con[selected].x1 *=sc  ;
        obj_con[selected].x2 *=sc  ;
        obj_con[selected].x3 *=sc  ;
        obj_con[selected].x4 *=sc  ;
    }else if (flag ==2) {
        obj_con[selected].y1*=sc  ;
        obj_con[selected].y2 *=sc  ;
        obj_con[selected].y3 *=sc  ;
        obj_con[selected].y4 *= sc  ;
    }else{
        obj_con[selected].x1 *=sc  ;
        obj_con[selected].x2 *=sc  ;
        obj_con[selected].x3 *=sc  ;
        obj_con[selected].x4 *=sc  ;
        obj_con[selected].y1*=sc  ;
        obj_con[selected].y2 *=sc  ;
        obj_con[selected].y3 *=sc  ;
        obj_con[selected].y4 *=sc  ;
    }
}
void mouse(int button, int state, int x, int y)
{   /*
     函数说明:控制鼠标的事件
     */
    GLuint selectBuffer[SIZE];//存放物体名称的栈
    GLint hits;//存放被选中对象个数
    GLint viewport[4];//存放可视区参数
    if( state == GLUT_DOWN && button == GLUT_LEFT_BUTTON)//当鼠标左键按下时
    {
        glGetIntegerv(GL_VIEWPORT,viewport);         //获取当前视口坐标参数
        glSelectBuffer(SIZE,selectBuffer);                  //选择名称栈存放被选中的名称
        glRenderMode(GL_SELECT);                        //设置当前为 选择模式
        glInitNames();                                             //名称栈
        glPushName(0);
        glMatrixMode(GL_PROJECTION);
        glPushMatrix();
        glLoadIdentity();
        gluPickMatrix(x,viewport[3]-y,N,N,viewport);//创建用于选择的投影矩阵栈
        gluOrtho2D(0,SCREEN_WIDTH,0,SCREEN_HEIGHT);//设置投影方式
        draw(GL_SELECT);//绘制场景
        glPopMatrix();
        glFlush();
        hits = glRenderMode(GL_RENDER);
        glMatrixMode(GL_MODELVIEW);
        if(hits > 0)processHits(hits,selectBuffer);
        glutPostRedisplay();
    }
    if( state == GLUT_DOWN && button == GLUT_RIGHT_BUTTON)//当鼠标左键按下时
    {
        //旋转
        if (obj_con[selected].index==3) {
            return;
        }else if(obj_con[selected].index==1||obj_con[selected].index==2){
            move_to_o();                                                                //首先移动到原点
            rotato();
            move_back();                                                                //然后移动到原来的位置
        }
        glutPostRedisplay();
    }
    if( state == GLUT_UP && button == GLUT_LEFT_BUTTON) //当鼠标左键抬起时
    {   select_point = 0;
        glRenderMode(GL_RENDER);
        draw(GL_RENDER);
        glutPostRedisplay();
    }
}
void processKeyBoard(int key, int x, int y)
{/*
  函数说明:处理键盘的信息。
  具体的操作参考实际操作目录表
  */    int step = 10;
        switch (key)
        {   case '1':
                selected=1;
                break;
            case '2':
                selected=2;
                break;
            case '3':
                selected=3;
                break;
            case 'u':
                move_to_o2();                                                                //首先移动到原点
                cut_move(1,0);
                move_back2();                                                                //然后移动到原来的位置
                break;
            case 'i':
                move_to_o2();                                                                //首先移动到原点
                cut_move(2,0);
                move_back2();
                break;
            case 'j':
                move_to_o2();                                                                //首先移动到原点
                cut_move(1,1);
                move_back2();                                                                //然后移动到原来的位置
                break;
            case 't':
                rotato();
                break;
            case 'k':
                move_to_o2();                                                                //首先移动到原点
                cut_move(2,1);
                move_back2();
                break;
            case 'p':
                scales+=0.01;
                if (scales<1)
                    scales=1;
                cout <<"加速缩放:"<< scales << endl;
                break;
            case 'o':
                scales-=0.01;
                if (scales<1)
                    scales=1;
                cout <<"减速缩放:"<< scales << endl;
                break;
            case 'z':
                if (selected==3) {
                    radius  = radius*scales;
                }else{
                    move_to_o();                                                                //首先移动到原点
                    enlarge(1,0);
                    move_back();                                                                //然后移动到原来的位置
                }
                break;
            case 'x':
                if (selected==3) {
                    radius  = radius*scales;
                }else{
                    move_to_o();                                                                //首先移动到原点
                    enlarge(2,0);
                    move_back();                                                                //然后移动到原来的位置
                }
                break;
            case 'c':
                if (selected==3) {
                    radius  = radius*(scales);
                }else{
                    move_to_o();                                                                //首先移动到原点
                    enlarge(3,0);
                    move_back();                                                                //然后移动到原来的位置
                }
                break;
            case 'v':
                if (selected==3) {
                    radius  = radius*(1/scales);
                }else{
                    move_to_o();                                                                //首先移动到原点
                    enlarge(1,1);
                    move_back();                                                                //然后移动到原来的位置
                }
                break;
            case 'b':
                if (selected==3) {
                    radius  = radius*(1/scales);
                }else{
                    move_to_o();                                                                //首先移动到原点
                    enlarge(2,1);
                    move_back();                                                                //然后移动到原来的位置
                }
                break;
            case 'n':
                if (selected==3) {
                    radius  = radius*(1/scales);
                }else{
                    move_to_o();                                                                //首先移动到原点
                    enlarge(3,1);
                    move_back();                                                                //然后移动到原来的位置
                }
                break;
            case GLUT_KEY_LEFT:
                if (obj_con[selected].rtx0 - step > obj_con[selected].l)obj_con[selected].rtx0 -= step;
                break;
            case GLUT_KEY_RIGHT:
                if (obj_con[selected].rtx0 + step <obj_con[selected].r)obj_con[selected].rtx0 += step;
                break;
            case GLUT_KEY_UP:
                if (obj_con[selected].rty0 + step < obj_con[selected].u)obj_con[selected].rty0 += step;
                break;
            case GLUT_KEY_DOWN:
                if (obj_con[selected].rty0 - step > obj_con[selected].d)obj_con[selected].rty0 -= step;
                break;
            case 'a':
                //表示可以按照反向旋转
                angles = -angles;
                break;
            default:
                break;
        }
    glutPostRedisplay();
    return;
}
int main(int argc, char *argv[])
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_RGBA| GLUT_DEPTH );
    glutInitWindowSize(SCREEN_WIDTH,SCREEN_HEIGHT);
    glutInitWindowPosition(300, 10);
    glutCreateWindow("CG实验1");
    init();
    glutDisplayFunc(display);
    glutReshapeFunc(reshape);
    glutMouseFunc(mouse);
    glutSpecialFunc(processKeyBoard);//定义键盘事件

    glutMainLoop();

    return 1;
}

猜你喜欢

转载自blog.csdn.net/ooffrankdura/article/details/79841314