2022年5月24日 星期二

雪⛄電腦圖學筆記14~

 2022/5/24 第十四周 

主題 : 寫、讀檔,動畫,計時器

1. 寫檔

(1) file-new-empty file,save : week14-1.cpp,存到week14-1_fprintf 目錄裡

(2) 程式碼:

///寫檔

#include <stdio.h>

int main()

{///檔案指標 fout 開啟檔案(檔名, write模式)

    FILE * fout = fopen( "file.txt" , "w+" );

     printf("    Hello World\n");

    fprintf( fout, "Hello World\n");

    fclose(fout);///關閉檔案

}

(3) 執行的時候資料夾會跑出file.txt、.exe檔、.o檔



2. 讀檔

(1) file-new-empty file,save : week14-2.cpp,存到week14-2_fprintf_fscanf 目錄裡

(2) 複製上面的程式碼(寫檔) + 讀檔的程式碼

///讀檔

#include <stdio.h>

int main()

{///檔案指標 fout 開啟檔案(檔名, write模式)

    FILE * fout = fopen("file.txt","w+");  ///f out (f:file)

    fprintf(fout,"3.1415926\n");

    fclose(fout);///關閉檔案


    float angle=0;

    FILE * fin = fopen("file.txt","r");       ///f in

    fscanf(fin,"%f",&angle); ///沒加&會當掉

    printf("讀到了角度:%f",angle);

    fclose(fin);

--------->黑色寫檔、紅色讀檔

(3) 執行的時候資料夾會跑出file.txt、.exe檔、.o檔



3. 加上周的程式碼

(1) 開專案week14_angles_fprintf,把上禮拜week13_rect_many的程式碼 複製貼上

(2) 加上寫檔的程式碼

///week14_angles_fprintf

#include <GL/glut.h>

#include <stdio.h>

float angle[20], oldX=0;

int angleID=0; ///0號關節,1號關節...

FILE * fout = NULL;

void myWrite(){ ///會執行好多次

    if( fout == NULL ) fout= fopen("file.txt","w+");

    for(int i=0; i<20; i++){

        printf("%.1f",angle[i]);///小黑印出來

        fprintf(fout, "%.1f ", angle[i]);///檔案印出來

    }   ///沒有fclose

}

void keyboard(unsigned char key, int x, int y)///鍵盤按數字

{

    if(key=='0') angleID=0;

    if(key=='1') angleID=1;

    if(key=='2') angleID=2;

    if(key=='3') angleID=3;

}

void mouse(int button, int state, int x, int y)///滑鼠按下去

{

    oldX = x;

}

void motion(int x, int y)///滑鼠拖曳

{

    angle[angleID] += (x-oldX);

    myWrite();

    oldX = x;

    glutPostRedisplay(); ///請GLUT重畫畫面

}

void display()

{

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glColor3f(1,1,1);///白色

    glRectf( 0.3, 0.5, -0.3, -0.5);///身體


    glPushMatrix();///右半部

        glTranslatef( 0.3,  0.4, 0);      ///(3)把手臂掛回身體

        glRotatef(angle[0],0,0,1);   ///(2)對z軸做旋轉

        glTranslatef( -0.3, -0.4,0);   ///(1)把手的旋轉中心,放到中心

        glColor3f(1,0,0);///紅色

        glRectf( 0.3, 0.5, 0.7, 0.3);///右上手臂


        glPushMatrix();

            glTranslatef(0.7,0.4,0);

            glRotatef(angle[1],0,0,1);

            glTranslatef(-0.7,-0.4,0);

            glColor3f(0,1,0);///綠色

        glRectf( 0.7, 0.5, 1.0, 0.3);///右上手臂


        glPopMatrix();


    glPopMatrix();


    glPushMatrix();///左半部

        glTranslatef(-0.3, 0.4, 0);      ///(3)把手臂掛回身體

        glRotatef(angle[2],0,0,1);   ///(2)對z軸做旋轉

        glTranslatef(+0.3, -0.4,0);   ///(1)把手的旋轉中心,放到中心

        glColor3f(1,0,0);///紅色

        glRectf(-0.3, 0.5,-0.7, 0.3);///左上手臂


        glPushMatrix();

            glTranslatef(-0.7,0.4,0);

            glRotatef(angle[3],0,0,1);

            glTranslatef(+0.7,-0.4,0);

            glColor3f(0,1,0);///綠色

        glRectf(-0.7, 0.5,-1.0, 0.3);///左下手臂


        glPopMatrix();


    glPopMatrix();


    glutSwapBuffers();

}

int main(int argc, char** argv)

{

    glutInit(&argc, argv);

    glutInitDisplayMode( GLUT_DOUBLE | GLUT_DEPTH);

    ///glutInitWindowSize(600,600);

    glutCreateWindow("week13 rect TRT TRT");


    glutKeyboardFunc(keyboard);

    glutMouseFunc(mouse);

    glutMotionFunc(motion);

    glutDisplayFunc(display);


    glutMainLoop();

}


(3)資料可讀性不高-->加上跳行

///week14_angles_fprintf

#include <GL/glut.h>

#include <stdio.h>

float angle[20], oldX=0;

int angleID=0; ///0號關節,1號關節...

FILE * fout = NULL; ///f out

void myWrite(){ ///每呼叫一次myWrite()

    if( fout == NULL ) fout= fopen("file.txt","w+");


    for(int i=0; i<20; i++){

        printf("%.1f",angle[i]);///小黑印出來

        fprintf(fout, "%.1f ", angle[i]);///檔案印出來

    } 

    printf("\n");///每呼叫一次myWrite(),小黑跳行

    fprintf(fout,"\n");///每呼叫一次myWrite(),檔案也跳行

}

void keyboard(unsigned char key, int x, int y)///鍵盤按數字

{

    if(key=='0') angleID=0;

    if(key=='1') angleID=1;

    if(key=='2') angleID=2;

    if(key=='3') angleID=3;

}


void mouse(int button, int state, int x, int y)///滑鼠按下去

{

    oldX = x;

}


void motion(int x, int y)///滑鼠拖曳

{

    angle[angleID] += (x-oldX);

    myWrite();

    oldX = x;

    glutPostRedisplay(); ///請GLUT重畫畫面

}


void display()

{

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glColor3f(1,1,1);///白色

    glRectf( 0.3, 0.5, -0.3, -0.5);///身體


    glPushMatrix();///右半部

        glTranslatef( 0.3,  0.4, 0);      ///(3)把手臂掛回身體

        glRotatef(angle[0],0,0,1);   ///(2)對z軸做旋轉

        glTranslatef( -0.3, -0.4,0);   ///(1)把手的旋轉中心,放到中心

        glColor3f(1,0,0);///紅色

        glRectf( 0.3, 0.5, 0.7, 0.3);///右上手臂


        glPushMatrix();

            glTranslatef(0.7,0.4,0);

            glRotatef(angle[1],0,0,1);

            glTranslatef(-0.7,-0.4,0);

            glColor3f(0,1,0);///綠色

        glRectf( 0.7, 0.5, 1.0, 0.3);///右上手臂


        glPopMatrix();


    glPopMatrix();


    glPushMatrix();///左半部

        glTranslatef(-0.3, 0.4, 0);      ///(3)把手臂掛回身體

        glRotatef(angle[2],0,0,1);   ///(2)對z軸做旋轉

        glTranslatef(+0.3, -0.4,0);   ///(1)把手的旋轉中心,放到中心

        glColor3f(1,0,0);///紅色

        glRectf(-0.3, 0.5,-0.7, 0.3);///左上手臂


        glPushMatrix();

            glTranslatef(-0.7,0.4,0);

            glRotatef(angle[3],0,0,1);

            glTranslatef(+0.7,-0.4,0);

            glColor3f(0,1,0);///綠色

        glRectf(-0.7, 0.5,-1.0, 0.3);///左下手臂


        glPopMatrix();


    glPopMatrix();


    glutSwapBuffers();

}


int main(int argc, char** argv)

{

    glutInit(&argc, argv);

    glutInitDisplayMode( GLUT_DOUBLE | GLUT_DEPTH);

    ///glutInitWindowSize(600,600);

    glutCreateWindow("week13 rect TRT TRT");


    glutKeyboardFunc(keyboard);

    glutMouseFunc(mouse);

    glutMotionFunc(motion);

    glutDisplayFunc(display);


    glutMainLoop();

}



4. 做動畫~

(1) 在開一個新的專案week14_angles_fprintf_fscanf,加上讀檔的程式碼

(2) Build : 先做完動作後,一直按著r就可以跑出剛剛做的動作(變成動畫)

///week14_angles_fprintf

#include <GL/glut.h>

#include <stdio.h>

float angle[20], oldX=0;

int angleID=0; ///0號關節,1號關節...

FILE * fout = NULL, * fin = NULL;   ///f out、f in

void myWrite(){ ///每呼叫一次myWrite()

    if( fout == NULL ) fout= fopen("file.txt","w+");

    for(int i=0; i<20; i++){

        printf("%.1f ",angle[i]);///小黑印出來

        fprintf(fout, "%.1f ", angle[i]);///檔案印出來

    }

    printf("\n");///每呼叫一次myWrite(),小黑跳行

    fprintf(fout,"\n");///每呼叫一次myWrite(),檔案也跳行

}


void myRead(){

    if( fout != NULL ){ fclose(fout); fout=NULL; }

    if( fin == NULL ) fin = fopen("file.txt","r");

    for(int i=0; i<20; i++){ ///因為下面關節20個,所以要開陣列大小20(第4行)

        fscanf(fin, "%f", &angle[i]);

    }

    glutPostRedisplay();///重畫畫面

}


void keyboard(unsigned char key, int x, int y)///鍵盤按數字

{

    if(key=='r') myRead();   ///一直按r就可以跑出動畫

    if(key=='0') angleID=0;

    if(key=='1') angleID=1;

    if(key=='2') angleID=2;

    if(key=='3') angleID=3;

}


void mouse(int button, int state, int x, int y)///滑鼠按下去

{

    oldX = x;

}


void motion(int x, int y)///滑鼠拖曳

{

    angle[angleID] += (x-oldX);

    myWrite();

    oldX = x;

    glutPostRedisplay(); ///請GLUT重畫畫面

}


void display()

{

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glColor3f(1,1,1);///白色

    glRectf( 0.3, 0.5, -0.3, -0.5);///身體


    glPushMatrix();///右半部

        glTranslatef( 0.3,  0.4, 0);      ///(3)把手臂掛回身體

        glRotatef(angle[0],0,0,1);   ///(2)對z軸做旋轉

        glTranslatef( -0.3, -0.4,0);   ///(1)把手的旋轉中心,放到中心

        glColor3f(1,0,0);///紅色

        glRectf( 0.3, 0.5, 0.7, 0.3);///右上手臂


        glPushMatrix();

            glTranslatef(0.7,0.4,0);

            glRotatef(angle[1],0,0,1);

            glTranslatef(-0.7,-0.4,0);

            glColor3f(0,1,0);///綠色

        glRectf( 0.7, 0.5, 1.0, 0.3);///右上手臂


        glPopMatrix();


    glPopMatrix();


    glPushMatrix();///左半部

        glTranslatef(-0.3, 0.4, 0);      ///(3)把手臂掛回身體

        glRotatef(angle[2],0,0,1);   ///(2)對z軸做旋轉

        glTranslatef(+0.3, -0.4,0);   ///(1)把手的旋轉中心,放到中心

        glColor3f(1,0,0);///紅色

        glRectf(-0.3, 0.5,-0.7, 0.3);///左上手臂


        glPushMatrix();

            glTranslatef(-0.7,0.4,0);

            glRotatef(angle[3],0,0,1);

            glTranslatef(+0.7,-0.4,0);

            glColor3f(0,1,0);///綠色

        glRectf(-0.7, 0.5,-1.0, 0.3);///左下手臂


        glPopMatrix();


    glPopMatrix();


    glutSwapBuffers();

}


int main(int argc, char** argv)

{

    glutInit(&argc, argv);

    glutInitDisplayMode( GLUT_DOUBLE | GLUT_DEPTH);

    ///glutInitWindowSize(600,600);

    glutCreateWindow("week13 rect TRT TRT");


    glutKeyboardFunc(keyboard);

    glutMouseFunc(mouse);

    glutMotionFunc(motion);

    glutDisplayFunc(display);


    glutMainLoop();


}



5. 想把file.txt檔案改放到專案裡(不是放在freeglut/bin裡面)

(1) 用notepad++開啟專案裡的cbp,將第11、21行的雙括號裡面改成 .  : <Option working_dir="." />


(2) 再複製放在freeglut/bin裡的freeglut.dll 放到專案裡

(3) 在跑一次專案,就可以發現專案資料夾裡有file.txt


6. 計時器: 想讓動畫跑順暢一點(因為鍵盤按鍵速度有差) 

(1) 在開一個新的專案week14_timer

(2) 程式碼

///Timer 計時器

#include <GL/glut.h>

#include <stdio.h>

void timer(int t){

    printf("起床,現在時間: %d\n",t);

}

void display(){

}

int main(int argc, char** argv)

{

    glutInit(&argc, argv);

    glutInitDisplayMode(GLUT_DOUBLE | GLUT_DEPTH);

    glutCreateWindow("week14 timer");


    glutTimerFunc(1000, timer, 1);   ///一秒=1000

    glutTimerFunc(2000, timer, 2);

    glutTimerFunc(3000, timer, 3);

    glutTimerFunc(4000, timer, 4);

    glutTimerFunc(5000, timer, 5);

    glutDisplayFunc(display);

    glutMainLoop();



7. 自動計時器: 不想設太多timer

(1) 在開一個新的專案week14_timer_one_by_one

(2) 複製上一個timer程式碼在修改:

///Timer 自動計時器

#include <GL/glut.h>

#include <stdio.h>

void timer(int t){

    printf("起床,現在時間: %d\n",t);

    glutTimerFunc(1000, timer, t+1);

}

void display(){

}

int main(int argc, char** argv)

{

    glutInit(&argc, argv);

    glutInitDisplayMode(GLUT_DOUBLE | GLUT_DEPTH);

    glutCreateWindow("week14 timer");


    glutTimerFunc(5000, timer, 0);///設定5秒後,開始呼叫timer

    glutDisplayFunc(display);

    glutMainLoop();

}


8. 想要加上聲音

(1) 下載do.wav檔案,放在桌面/freeglut/bin



(2) 改剛剛的檔案的程式碼:

///Timer 計時器 + 播聲音

#include <GL/glut.h>

#include <stdio.h>

#include <mmsystem.h>

void timer(int t){

    printf("起床,現在時間: %d\n",t);

    PlaySound("do.wav", NULL, SND_ASYNC);

    glutTimerFunc(2000, timer, t+1);

}

void display(){

}

int main(int argc, char** argv)

{

    glutInit(&argc, argv);

    glutInitDisplayMode(GLUT_DOUBLE | GLUT_DEPTH);

    glutCreateWindow("week14 timer");


    glutTimerFunc(5000, timer, 0);///設定5秒後,開始呼叫timer

    glutDisplayFunc(display);

    glutMainLoop();

}




沒有留言:

張貼留言

VERY BEAUTIFUL, VERY POWERFUL

一.     一樣先安裝且設定好freeglut,OpecCV, 開啟CodeBlocks建立新專案 week11_gundam,                 把 MyGundam.zip下載解壓縮後的data資料夾放到freeglut/bin裡面 把week09_openc...