2022年3月28日 星期一

熱血的小葉老師圖學筆記 Week06

 # Week06


電腦圖學之父 Ivan Sutherland (Sketchpad)



看課本範例


jsyeh.org/3dcg10 下載 windows.zip data.zip

windows.zip => 下載\windows\Transformation.exe

data.zip    => 下載\windows\data\3D模型

執行 Transformation.exe


下方可以右鍵 Swap Translate/Rotate


自轉 vs. 公轉





# step01-3


接下來, 今天的主題是keyboard, 我們利用 GLUT 來寫今天的程式, 能 有keyboard互動, 重點是 glutKeyboardFunc(keyboard) 可以註冊 void keyboard(unsigned char key, int x, int y) 這個函式,再配合 stdio.h 的 printf()印出鍵盤的值



實作時間

Maya: qwer  

w:移動 e:轉動 r:縮放  

0. 安裝 freeglut, lib改一下  

1. File-New-Project, GLUT  

   week06_keyboard  

2. 接下來, 從上週 blog 複製我們的程式來用。  


多了3行程式, 分別是


int main() 裡 glutCreateWindow()之後

`glutKeyboardFunc(keyboard);`


前面要宣告 `int keyboard(unsigned char key, int x, int y)` 的鍵盤函式


## step01-3

接下來, 今天的主題是keyboard, 我們利用 GLUT 來寫今天的程式, 能 有keyboard互動, 重點是 glutKeyboardFunc(keyboard) 可以註冊 void keyboard(unsigned char key, int x, int y) 這個函式,再配合 stdio.h 的 printf()印出鍵盤的值


```C++

///從上週 blog 貼我們的程式

#include <GL/glut.h>

#include <stdio.h>

void display()

{

    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

        glColor3f( 1, 1, 0 );

        glutSolidTeapot(0.3);

    glutSwapBuffers();

}

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

{

    printf("現在按下:%c 座標在:%d %d\n", key, x, y);

}

int main(int argc, char**argv)

{

    glutInit(&argc, argv);

    glutInitDisplayMode(GLUT_DOUBLE | GLUT_DEPTH);

    glutCreateWindow("week06 keyboard");


    glutDisplayFunc(display);

    glutKeyboardFunc(keyboard);


    glutMainLoop();

}

```


# step02-1

接下來我們稍做修改,除了剛剛的keyboard()函式, 我們再加上 mouse() 及 motion()函式, 希望能完整互動




```C++

#include <GL/glut.h>

#include <stdio.h>

void display()

{

    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

        glColor3f( 1, 1, 0 );

        glutSolidTeapot(0.3);

    glutSwapBuffers();

}

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

{

    printf("現在按下:%c 座標在:%d %d\n", key, x, y);

}

void mouse( int button, int state, int x, int y )

{

}

void motion( int x, int y )

{

}

int main(int argc, char**argv)

{

    glutInit(&argc, argv);

    glutInitDisplayMode(GLUT_DOUBLE | GLUT_DEPTH);

    glutCreateWindow("week06 keyboard mouse motion");


    glutDisplayFunc(display);

    glutKeyboardFunc(keyboard);

    glutMouseFunc(mouse);

    glutMotionFunc(motion);


    glutMainLoop();

}

```


## step02-2

上上週有教glTranslatef()移動, 我們把它做出來



```C++

#include <GL/glut.h>

#include <stdio.h>

float x=0, y=0, z=0, oldX, oldY;

void display()

{

    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

    glPushMatrix();

        glTranslatef(  (x-150)/150.0  , -(y-150)/150.0  ,  z  ); ///Maya: w

        ///glRotatef( angle,  0, 0, 1);

        ///glScalef( scale, scale, scale );

        glColor3f( 1, 1, 0 );

        glutSolidTeapot(0.3);

    glPopMatrix();

    glutSwapBuffers();

}

void keyboard( unsigned char key, int mouseX, int mouseY )

{

    printf("現在按下:%c 座標在:%d %d\n", key, mouseX, mouseY);

}

void mouse( int button, int state, int mouseX, int mouseY )

{

    oldX = mouseX; oldY = mouseY;

}

void motion( int mouseX, int mouseY )

{

    x += (mouseX-oldX);

    y += (mouseY-oldY);

    oldX = mouseX; oldY = mouseY;

    display();

}

int main(int argc, char**argv)

{

    glutInit(&argc, argv);

    glutInitDisplayMode(GLUT_DOUBLE | GLUT_DEPTH);

    glutCreateWindow("week06 keyboard mouse motion");


    glutDisplayFunc(display);

    glutKeyboardFunc(keyboard);

    glutMouseFunc(mouse);

    glutMotionFunc(motion);


    glutMainLoop();

}

```



## step02-3

接下來我們實作出「縮放」的程式,利用 float scale=1.0 這個變數,如果 if(mousX大於oldX)就讓 scale 放大 1%, 反過來就讓 scale 變小 1%, 我們就可以完成這個縮放的版本



```C++

#include <GL/glut.h>

#include <stdio.h>

float x=0, y=0, z=0, scale=1.0, oldX, oldY;

void display()

{

    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

    glPushMatrix();

        //glTranslatef(  (x-150)/150.0  , -(y-150)/150.0  ,  z  ); ///Maya: w

        ///glRotatef( angle,  0, 0, 1);

        glScalef( scale, scale, scale ); ///Maya: r

        glColor3f( 1, 1, 0 );

        glutSolidTeapot(0.3);

    glPopMatrix();

    glutSwapBuffers();

}

void keyboard( unsigned char key, int mouseX, int mouseY )

{

    printf("現在按下:%c 座標在:%d %d\n", key, mouseX, mouseY);

}

void mouse( int button, int state, int mouseX, int mouseY )

{

    oldX = mouseX; oldY = mouseY;

}

void motion( int mouseX, int mouseY )

{

    if( mouseX>oldX ) scale = scale * 1.01;

    if( mouseX<oldX ) scale = scale * 0.99;

    //x += (mouseX-oldX);

    //y += (mouseY-oldY);

    oldX = mouseX; oldY = mouseY;

    display();

}

int main(int argc, char**argv)

{

    glutInit(&argc, argv);

    glutInitDisplayMode(GLUT_DOUBLE | GLUT_DEPTH);

    glutCreateWindow("week06 keyboard mouse motion");


    glutDisplayFunc(display);

    glutKeyboardFunc(keyboard);

    glutMouseFunc(mouse);

    glutMotionFunc(motion);


    glutMainLoop();

}

```


## step03-1


今天的主角是keyboard鍵盤函式, 我們 if(key=='w' 或 key=='W') now=1做移動, if(key=='r' 或 key=='R')now=3 做縮放。接下來在 motion()裡, if(now==1)做移動的計算, if(now==3)做縮放的計算, 這樣就可以又移動、又縮放了 



```C++

#include <GL/glut.h>

#include <stdio.h>

float x=150, y=150, z=0, scale=1.0, angle=0.0, oldX, oldY;

int now=1;///1:移動, 2:旋轉, 3:縮放

void display()

{

    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

    glPushMatrix();

        glTranslatef( (x-150)/150.0 , -(y-150)/150.0 , z ); ///Maya: w

        //glRotatef( angle,  0, 0, 1); ///Maya: e

        glScalef( scale, scale, scale ); ///Maya: r

        glColor3f( 1, 1, 0 );

        glutSolidTeapot(0.3);

    glPopMatrix();

    glutSwapBuffers();

}

void keyboard( unsigned char key, int mouseX, int mouseY )

{   //printf("現在按下:%c 座標在:%d %d\n", key, mouseX, mouseY);

    if(key=='w' || key=='W') now=1;///移動 (小心不要中文)

    //if(key=='e' || key=='E') now=2;///旋轉

    if(key=='r' || key=='R') now=3;///縮放

}

void mouse( int button, int state, int mouseX, int mouseY )

{

    oldX = mouseX; oldY = mouseY;

}

void motion( int mouseX, int mouseY )

{

    if(now==1){///移動

        x += (mouseX-oldX);

        y += (mouseY-oldY);

    }else if(now==3){///縮放

        if( mouseX>oldX ) scale = scale * 1.01;

        if( mouseX<oldX ) scale = scale * 0.99;

    }

    oldX = mouseX; oldY = mouseY;

    display();

}

int main(int argc, char**argv)

{

    glutInit(&argc, argv);

    glutInitDisplayMode(GLUT_DOUBLE | GLUT_DEPTH);

    glutCreateWindow("week06 keyboard mouse motion");


    glutDisplayFunc(display);

    glutKeyboardFunc(keyboard);

    glutMouseFunc(mouse);

    glutMotionFunc(motion);


    glutMainLoop();

}

```


## step03-2


今天最後的任務,是加上旋轉。所以用keyboard的 w,e,r 來切換移動、旋轉、縮放。motion()裡面也有對應的程式, display()也會照著進行 glTranslatef() glRotatef() glScalef() 的程式。我們還多學了 glutInitWindowSize(500,500)放大, 導致 glTranslatef()裡面減一半、除一半的地方有修改。.zip



```C++

#include <GL/glut.h>

#include <stdio.h>

float x=250, y=250, z=0, scale=1.0, angle=0.0, oldX, oldY;

int now=1;///1:移動, 2:旋轉, 3:縮放

void display()

{

    glClearColor(0.5, 0.5, 0.5, 1);///用來 Clear的色彩 R,G,B,A Alpha沒用到

    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

    glPushMatrix();

        glTranslatef( (x-250)/250.0 , -(y-250)/250.0 , z ); ///Maya: w

        glRotatef( angle,  0, 0, 1); ///Maya: e

        glScalef( scale, scale, scale ); ///Maya: r

        glColor3f( 1, 1, 0 );

        glutSolidTeapot(0.3);

    glPopMatrix();

    glutSwapBuffers();

}

void keyboard( unsigned char key, int mouseX, int mouseY )

{   //printf("現在按下:%c 座標在:%d %d\n", key, mouseX, mouseY);

    if(key=='w' || key=='W') now=1;///移動 (小心不要中文)

    if(key=='e' || key=='E') now=2;///旋轉

    if(key=='r' || key=='R') now=3;///縮放

}

void mouse( int button, int state, int mouseX, int mouseY )

{

    oldX = mouseX; oldY = mouseY;

}

void motion( int mouseX, int mouseY )

{

    if(now==1){///移動

        x += (mouseX-oldX);

        y += (mouseY-oldY);

    }else if(now==2){///旋轉

        angle += (mouseX-oldX);

    }else if(now==3){///縮放

        if( mouseX>oldX ) scale = scale * 1.01;

        if( mouseX<oldX ) scale = scale * 0.99;

    }

    oldX = mouseX; oldY = mouseY;

    display();

}

int main(int argc, char**argv)

{

    glutInit(&argc, argv);

    glutInitDisplayMode(GLUT_DOUBLE | GLUT_DEPTH);

    glutInitWindowSize(500, 500);

    glutCreateWindow("week06 keyboard mouse motion");


    glutDisplayFunc(display);

    glutKeyboardFunc(keyboard);

    glutMouseFunc(mouse);

    glutMotionFunc(motion);


    glutMainLoop();

}

```


沒有留言:

張貼留言