計算機圖形學第二次上機——旋轉的三角形

 

計算機圖形學第二次上機實驗 課程實驗報告

寫在前面:這是我的圖形學上機報告,代碼都是自己寫的,實測通過,查閱了許多資料,現以鏈接的形式給出

glut初始化

glutSpecialFunc響應鍵盤方向控制鍵

glutBitmapCharacter函數實現字符顯示

glutPostRedisplay函數

若遇到其他問題,希望大家多動手多查資料,不要矇混過關,這樣纔能有收穫。

最後希望這份報告能夠幫到大家~

 

 

目錄

計算機圖形學第二次上機實驗 課程實驗報告

一、實驗目的

二、實驗環境

三、實驗內容

1.立方體放縮變換

2.對稱變換

3.鍵盤迴調函數實現三角形旋轉

四、實驗心得

五、源代碼


 

一、實驗目的

  1. 掌握配置glut庫的步驟
  2. 測試運行示例代碼
  3. 掌握並編寫中點線算法和中點圓算法

二、實驗環境

1.codeblocks-17.12

2.Windows10 SDK 10.0.17134.0

三、實驗內容

1.立方體放縮變換

問題重述:利用OpenGL實現一個立方體關於參考點(10.0,20.0,10.0)進行放縮變換,放縮因子爲(2.0,1.0,0.5)。

爲了使放縮效果更佳,我將整個圖形進行了旋轉,又由於矩陣堆棧是先進先出的,故變換代碼框架爲:

glRotatef(45,1,1,1);//繞着向量(1,1,1)所指定的軸旋轉45°

glPushMatrix();//保存矩陣狀態

glTranslatef(10,20,10);//從原點平移到原處,T2

    glPushMatrix();

    glScalef(2,1,0.5);//放縮變換,S

    glPushMatrix();

    glTranslatef(-10,-20,-10);//從當前平移至原點,T1

    glPushMatrix();

 

    glColor3f(1.0,0.0,0.0);

glutWireCube(10.0);

 

運行效果:

變換前

 

變換後

 

 

2.對稱變換

問題重述:利用OpenGL實現一個矩形關於y=x+5對稱的新圖形。

 

變換的關鍵就是先通過平移將對稱軸經過原點,再旋轉與座標軸平行。進行對稱變換,然後再變換回去。

主要變換代碼如下

 

 glTranslatef(0,5,0);//T2,y平移5個單位

glPushMatrix();

glRotated(45,0,0,1);//R2,逆時針旋轉45度

glPushMatrix();

glScaled(1,-1,1);//S,放縮變換

glPushMatrix();

glRotated(-45,0,0,1);//R1 逆順時針旋轉45度,與x軸重合

glPushMatrix();

glTranslated(0,-5,0);//T1 y平移-5個單位

glPushMatrix();

 

glColor3f(1,0,0);

glRectf(-5,10,0,50);//x1=T2*R2*S*R1*T1*x

 

注意矩陣堆棧是先進先出即可。

運行結果爲

 

 

3.鍵盤迴調函數實現三角形旋轉

問題重述:通過定義鍵盤迴調函數,每按一次空格鍵,讓三個點依次完成畫點、畫線、畫三角形、讓三角形平移和縮放,並讓三角形沿三角形中心旋轉起來。

問題的關鍵在於註冊回調函數以及如何使三角形旋轉,由於問題較爲複雜,我將分段說明。

3.1定義全局變量以及模式

需要使用的全局變量爲

int currentMode = 0;//當前模式數

int enable=0;//是否旋轉

int angle = 0;   //當前旋轉角度

int step = 1;  //每次的角度遞增值

const int ModeNums = 7;//模式總數

 

窗口回調函數RenderScene定義各個模式爲

void RenderScene()

{

glClear(GL_COLOR_BUFFER_BIT);

switch(currentMode)

{

case 0:

                displayc();//畫點

        glPointSize(4);

glBegin(GL_POINTS);

    glColor3f(0,1.0,0.0);

break;

case 1:displayc();//畫開折線

                glBegin(GL_LINE_STRIP);

    glColor3f(1.0,0,0.0);

    break;

case 2: displayc();//畫閉折線

                glBegin(GL_LINE_LOOP);

    glColor3f(0.0,0.0,1.0);

break;

case 3: displayc();//畫填充三角形

                glBegin(GL_TRIANGLES);

    glColor3f(1.0,0,1.0);

break;

        case 4:displayc();//平移

                glMatrixMode(GL_MODELVIEW);

                glLoadIdentity();

                glTranslated(2,2,0);

                glBegin(GL_TRIANGLES);

                glColor3f(0,0,0);

                break;

        case 5:displayc();//放縮

                glMatrixMode(GL_MODELVIEW);

                glLoadIdentity();

                glScaled(1.5,1.5,1);

                glBegin(GL_TRIANGLES);

                glColor3f(1,0,0);

                break;

        case 6:

                Rotate();//旋轉

                break;

}

glVertex2f( -6.0, -3.0 );

glVertex2f( 4.0, -4.0 );

glVertex2f( 2.0, 7.0 );

glEnd();

 

glFlush();

glutSwapBuffers();

glLoadIdentity();

    if(enable==1)

        glutPostRedisplay();

}

一共有7個模式。

3.2鍵盤迴調函數

對於字符值鍵盤迴調函數,可以用

glutKeyboardFunc(myKey);  //爲當前窗口設置鍵盤迴調函數。

進行註冊,其實現爲:

void myKey( unsigned char key, int x, int y)

//響應ASCII對應鍵,鼠標的當前x和y位置也被返回。

{

switch(key)

{

case ' ': currentMode = (currentMode+1)%ModeNums;

      glutPostRedisplay();

  break;

        case 'r':enable=1;

                  glutPostRedisplay();

  break;

        case 's':enable=0;

                  glutPostRedisplay();

                  break;

case 27:  exit(-1);

}

}

 

對於上下左右特殊按鍵的鍵盤迴調函數,可以用

glutSpecialFunc(SpecialKey);

進行註冊,其實現爲:

void SpecialKey(int key,int x,int y)

{

    switch(key)

    {

        case GLUT_KEY_UP:

 

            step++;

            break;

        case GLUT_KEY_DOWN:

            step--;

            break;

    }

}

 

3.3實現三角形的旋轉

3.3.1初始化雙緩衝區

之前我沒有注意到自己僅僅使用了單緩衝區,導致動畫效果很差,後來詳細查找了一下glutInitDisplayMode函數的參數列表:

函數原型void glutInitDisplayMode(unsigned int mode),函數功能爲設置初始顯示模式。

函數功能:設置初始顯示模式。

函數原型:void glutInitDisplayMode(unsigned int mode);

mode | mode可取以下值或其組合:

對應宏定義

意義

GLUT_RGB

0x0000

指定 RGB 顏色模式的窗口

GLUT_RGBA

0x0000

指定RGBA顏色模式的窗口

GLUT_INDEX

0x0001

指定顏色索引模式的窗口

GLUT_SINGLE

0x0000

指定單緩存窗口

GLUT_DOUBLE

0x0002

指定雙緩存窗口

GLUT_ACCUM

0x0004

窗口使用累加緩存

GLUT_ALPHA

0x0008

窗口的顏色分量包含 alpha 值

GLUT_DEPTH

0x0010

窗口使用深度緩存

GLUT_STENCIL

0x0020

窗口使用模板緩存

GLUT_MULTISAMPLE

0x0080

指定支持多樣本功能的窗口

GLUT_STEREO

0x0100

指定立體窗口

GLUT_LUMINANCE

0x0200

窗口使用亮度顏色模型

用“或“(|)操作符來建立想要的顯示模式

想要流暢地顯示動畫,必須設置雙緩衝區,而且我使用了RGB色彩空間,於是初始化語句爲

glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGB);

3.3.2.通過不斷地刷新並交換緩衝區實現旋轉

1.當使能信號enable=1時可以旋轉,於是先定義矩陣堆棧模式glMatrixMode(GL_MODELVIEW);

glLoadIdentity();//矩陣堆棧可以保存上次旋轉結果

 

2.壓入旋轉角度angle+=step的旋轉矩陣(我定義的三個點的中心剛好在原點,所以不需要計算旋轉中心,默認原點就好)

    angle=(angle+step)%360;

glRotated(angle,0,0,1);

 

3.畫填充三角形並刷新畫面和交換緩衝區

 glBegin(GL_TRIANGLES);

glColor3f(1,0,0);

glVertex2f( -6.0, -3.0 );

glVertex2f( 4.0, -4.0 );

glVertex2f( 2.0, 7.0 );

glEnd();

 

glFlush();

glutSwapBuffers();//交換緩衝區保證有流暢動畫

 

 

4.當使能信號enable=1時重複上述過程,實現旋轉

  if(enable==1)

        glutPostRedisplay();

 

最後一種模式case=6時旋轉,相應的窗口回調函數代碼段爲

void RenderScene()

{

glClear(GL_COLOR_BUFFER_BIT);

switch(currentMode)

{……

case 6:

                Rotate();//旋轉

                break;

}

glVertex2f( -6.0, -3.0 );

glVertex2f( 4.0, -4.0 );

glVertex2f( 2.0, 7.0 );

glEnd();

 

glFlush();

glutSwapBuffers();

glLoadIdentity();

    if(enable==1)

        glutPostRedisplay();

}

 

Rotate函數實現爲:

void Rotate()

{

//顯示提示字符

……

//旋轉

glMatrixMode(GL_MODELVIEW);

    glLoadIdentity();

    angle=(angle+step)%360;

    glRotated(angle,0,0,1);

 

    glBegin(GL_TRIANGLES);

    glColor3f(1,0,0);

}

3.4實現文字提示

Glut內置了字符提示函數

glRasterPos2d(double x,double y)

定義了光標位置,其中座標爲世界座標,即(0,0)爲世界座標中心。

glutBitmapCharacter(font , character)

定義了字體和要顯示的字符,僅限ASC||表中的字符,參數範圍如下

font

設置字符的字體,選擇範圍如下:

GLUT_BITMAP_8_BY_13

GLUT_BITMAP_9_BY_15

GLUT_BITMAP_TIMES_ROMAN_10 字體:TIMES_ROMAN 大小:10

GLUT_BITMAP_TIMES_ROMAN_24 字體:TIMES_ROMAN 大小:24

GLUT_BITMAP_HELVETICA_10

GLUT_BITMAP_HELVETICA_12

GLUT_BITMAP_HELVETICA_18

 

character

要顯示的字符。

 

我用以上兩個內置函數實現了字符提示函數displayc

void displayc()

{

    glColor3f(0, 0, 0);

    char str[]="Press space to continue,press escape to exit!";

    glClear(GL_COLOR_BUFFER_BIT);

    glRasterPos2d(-39.5,20);

    for(int i=0;i<sizeof(str);i++)

    {

        glutBitmapCharacter(GLUT_BITMAP_8_BY_13,str[i]);

    }

    glFlush();

}

以及Rotate函數中顯示字符的代碼段

 

//顯示提示字符

    char str[]="Press 'R' to Rotate,'S' to stop";

    glClear(GL_COLOR_BUFFER_BIT);

    glRasterPos2d(-25,20);

    for(int i=0;i<sizeof(str);i++)

    {

        glutBitmapCharacter(GLUT_BITMAP_8_BY_13,str[i]);

    }

 

    char str1[]="Press Up to Speed up,Down to Slow down";

    glRasterPos2d(-30,15);

    for(int i=0;i<sizeof(str1);i++)

    {

        glutBitmapCharacter(GLUT_BITMAP_8_BY_13,str1[i]);

    }

 

運行結果

1.畫點

 

2.畫開折線

 

3.畫閉折線

4.畫填充三角形

 

5.平移

 

6.放縮

 

 

7.旋轉

 

 

四、實驗心得

此次實驗我查閱了大量資料,終於在詳細瞭解了許多OpenGL函數之後實現了一個簡單的動畫以及鍵盤迴調函數,在最後代碼運行無誤,畫面能正確響應鍵盤的時候內心還是很開心的。

 

五、源代碼

 

 

1.立方體放縮

#include"windows.h"

#ifndef GLUT_DISABLE_ATEXIT_HACK

#define GLUT_DISABLE_ATEXIT_HACK

#endif

#include <glut.h>

void init()

{

glClearColor(1.0,1.0,1.0,1.0);

}

void RenderScene()

{

glClear(GL_COLOR_BUFFER_BIT);

 

glMatrixMode(GL_MODELVIEW);

glLoadIdentity();

 

    glRotatef(45,1,1,1);//繞着向量(1,1,1)所指定的軸旋轉45°

glPushMatrix();//保存矩陣狀態

glTranslatef(10,20,10);//從原點平移到原處,T2

    glPushMatrix();

    glScalef(2,1,0.5);//放縮變換,S

    glPushMatrix();

    glTranslatef(-10,-20,-10);//從當前平移至原點,T1

    glPushMatrix();

 

    glColor3f(1.0,0.0,0.0);

glutWireCube(10.0);

    //glFlush();

glLoadIdentity();

glRotatef(45,1,1,1);//繞着向量(1,1,1)所指定的軸旋轉45°

    //畫x座標軸

glBegin(GL_LINES);

glColor3f(0,0,0);

glVertex3f(0,0,0);

glVertex3f(40,0,0);

glEnd();

//畫y座標軸

glBegin(GL_LINES);

glColor3f(0,0,0);

glVertex3f(0,0,0);

glVertex3f(0,40,0);

glEnd();

//畫z座標軸

glBegin(GL_LINES);

glColor3f(0,0,0);

glVertex3f(0,0,0);

glVertex3f(0,0,40);

glEnd();

 

glFlush();

}

 

void ChangeSize(GLsizei w,GLsizei h)

{

GLfloat aspectRatio;

if(h==0)

h = 1;

glViewport(0,0,w,h);

glMatrixMode(GL_PROJECTION);

glLoadIdentity();

 

aspectRatio = (GLfloat)w/(GLfloat)h;

if(w<=h)

glOrtho(-50.0,50.0,-50.0/aspectRatio,50.0/aspectRatio,-50.0,50.0);

else

glOrtho(-50.0*aspectRatio,50.0*aspectRatio,-50.0,50.0,-50.0,50.0);

 

glMatrixMode(GL_MODELVIEW);

glLoadIdentity();

}

int main()

{

glutInitDisplayMode(GLUT_RGB|GLUT_SINGLE);

glutCreateWindow("Scale_Cube");

 

init();

glutDisplayFunc(RenderScene);

glutReshapeFunc(ChangeSize);

 

glutMainLoop();

return 0;

}

2.旋轉變換

#include<windows.h>

#include <GL/glut.h>

void init()

{

glClearColor(1.0,1.0,1.0,0.0);

}

void RenderScene()

{

glClear(GL_COLOR_BUFFER_BIT);

glMatrixMode(GL_MODELVIEW);

glLoadIdentity();

 

glColor3f(0,0,0.5);

glRectf(-5,10,0,50);

//原矩陣

glBegin(GL_LINES);

 

glColor3f(0,0,0);

glVertex3f(0,0,0);

glVertex3f(80,0,0);

glEnd();

//x軸

glBegin(GL_LINES);

glColor3f(0,0,0);

glVertex3f(0,0,0);

glVertex3f(0,80,0);

glEnd();

 

//y軸

glBegin(GL_LINES);

glColor3f(0,1,0);

glVertex3f(-50,-45,0);

glVertex3f(50,55,0);

glEnd();

 

glTranslatef(0,5,0);//T2,y平移5個單位

glPushMatrix();

glRotated(45,0,0,1);//R2,逆時針旋轉45度

glPushMatrix();

glScaled(1,-1,1);//S,放縮變換

glPushMatrix();

glRotated(-45,0,0,1);//R1 逆順時針旋轉45度,與x軸重合

glPushMatrix();

glTranslated(0,-5,0);//T1 y平移-5個單位

    glPushMatrix();

 

glColor3f(1,0,0);

glRectf(-5,10,0,50);//x1=T2*R2*S*R1*T1*x

 

 

glFlush();

}

void ChangeSize(GLsizei w,GLsizei h)

{

float ratio;

if(h==0)

h = 1;

ratio = (GLfloat)w/(GLfloat)h;

glViewport(0,0,w,h);

glMatrixMode(GL_PROJECTION);

glLoadIdentity();

 

if(w<=h)

gluOrtho2D(-100.0,100.0,-100.0/ratio,100.0/ratio);

else

gluOrtho2D(-100.0*ratio,100.0*ratio,-100.0,100);

 

glMatrixMode(GL_MODELVIEW);

glLoadIdentity();

}

int main()

{

glutInitDisplayMode(GLUT_RGB|GLUT_SINGLE);

glutInitWindowPosition(400,300);

glutInitWindowSize(300,300);

glutCreateWindow("Geometric transformation 2");

 

init();

glutDisplayFunc(RenderScene);

glutReshapeFunc(ChangeSize);

glutMainLoop();

return 0;

}

3.旋轉三角形

#include"windows.h"

#include <stdlib.h>

#include <stdio.h>

#include <glut.h>

#include<gl.h>

#include <stdlib.h>

#include <string>

int currentMode = 0;

int enable=0;//是否旋轉

int angle = 0;   //當前旋轉角度

int step = 1;  //每次的角度遞增值

const int ModeNums = 7;

typedef struct  {

float x,y;

}point;

void Rotate();

void init()

{

glClearColor(1.0,1.0,1.0,1.0);

}

void myKey( unsigned char key, int x, int y) //響應ASCII對應鍵,鼠標的當前x和y位置也被返回。

{

switch(key)

{

case ' ': currentMode = (currentMode+1)%ModeNums;

 

      glutPostRedisplay();

  break;

        case 'r':enable=1;

                  glutPostRedisplay();

  break;

        case 's':enable=0;

                  glutPostRedisplay();

                  break;

 

case 27:  exit(-1);

}

}

void SpecialKey(int key,int x,int y)

{

    switch(key)

    {

        case GLUT_KEY_UP:

 

            step++;

            break;

        case GLUT_KEY_DOWN:

            step--;

            break;

 

    }

 

}

void displayc()

{

    glColor3f(0, 0, 0);

    char str[]="Press space to continue,press escape to exit!";

    glClear(GL_COLOR_BUFFER_BIT);

    glRasterPos2d(-39.5,20);

    for(int i=0;i<sizeof(str);i++)

    {

        glutBitmapCharacter(GLUT_BITMAP_8_BY_13,str[i]);

    }

    glFlush();

}

void RenderScene()

{

glClear(GL_COLOR_BUFFER_BIT);

switch(currentMode)

{

case 0:

                displayc();//畫點

        glPointSize(4);

glBegin(GL_POINTS);

    glColor3f(0,1.0,0.0);

break;

case 1:displayc();//畫開折線

                glBegin(GL_LINE_STRIP);

    glColor3f(1.0,0,0.0);

    break;

case 2: displayc();//畫閉折線

                glBegin(GL_LINE_LOOP);

    glColor3f(0.0,0.0,1.0);

break;

case 3: displayc();//畫填充三角形

                glBegin(GL_TRIANGLES);

    glColor3f(1.0,0,1.0);

break;

        case 4:displayc();//平移

                glMatrixMode(GL_MODELVIEW);

                glLoadIdentity();

                glTranslated(2,2,0);

                glBegin(GL_TRIANGLES);

                glColor3f(0,0,0);

                break;

        case 5:displayc();//放縮

                glMatrixMode(GL_MODELVIEW);

                glLoadIdentity();

                glScaled(1.5,1.5,1);

                glBegin(GL_TRIANGLES);

                glColor3f(1,0,0);

                break;

        case 6:

                Rotate();//旋轉

 

                break;

 

}

glVertex2f( -6.0, -3.0 );

glVertex2f( 4.0, -4.0 );

glVertex2f( 2.0, 7.0 );

glEnd();

 

glFlush();

glutSwapBuffers();//交換緩衝區保證有流暢動畫

glLoadIdentity();

    if(enable==1)

        glutPostRedisplay();

}

void Rotate()

{

    glColor3f(0, 0, 0);//設置黑色繪製顏色

    

    //顯示提示字符

    char str[]="Press 'R' to Rotate,'S' to stop";

    glClear(GL_COLOR_BUFFER_BIT);

    glRasterPos2d(-25,20);

    for(int i=0;i<sizeof(str);i++)

    {

        glutBitmapCharacter(GLUT_BITMAP_8_BY_13,str[i]);

    }

 

    char str1[]="Press Up to Speed up,Down to Slow down";

    glRasterPos2d(-30,15);

    for(int i=0;i<sizeof(str1);i++)

    {

        glutBitmapCharacter(GLUT_BITMAP_8_BY_13,str1[i]);

    }

 

    //旋轉

glMatrixMode(GL_MODELVIEW);

    glLoadIdentity();

    angle=(angle+step)%360;

    glRotated(angle,0,0,1);

 

    glBegin(GL_TRIANGLES);

    glColor3f(1,0,0);

 

}

void ChangeSize(GLsizei w,GLsizei h)

{

float ratio;

if(h==0)

h = 1;

glViewport(0,0,w,h);

glMatrixMode(GL_PROJECTION);

glLoadIdentity();

ratio = (float)w/(float)h;

//gluOrtho2D(-10.0,10.0,-10.0,10.0);

if(w<=h)

gluOrtho2D(-40.0,40.0,-40.0/ratio,40.0/ratio);

else

gluOrtho2D(-40.0*ratio,40.0*ratio,-40.0,40.0);

glMatrixMode(GL_MODELVIEW);

 

}

int main()

{

glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGB);

glutInitWindowPosition(50,50);

glutInitWindowSize(360,360);

glutCreateWindow("KeyboardFunc");

 

init();

glutDisplayFunc(RenderScene);

glutReshapeFunc(ChangeSize);

glutKeyboardFunc(myKey);  //爲當前窗口設置鍵盤迴調函數。

    glutSpecialFunc(SpecialKey);

printf("Press space to continue,press escape to exit!\n");

glutMainLoop();

return 0;

}

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章