2021年6月9日 星期三

Xian筆記-Week16

 Week 16

1.Timer--> motion + mouse

2.存檔

3.播放動畫

4.主題:內插

(1)

        上週的程式抓出來用,把Timer程式搬家,改用 motion + mouse 函式去改變角度 !
        

        概念:

                在滑鼠點下移動的同時,記下位置,並且 motion "現在的位置 - 原本的位置" 來取得移動的距離,同時更新位置,來達成用滑鼠改變角度控制!



int oldX=0; void timer(int t) { /* glutTimerFunc( 30, timer , t+1); angle[angleID] += diff; ///step02 if(angle[angleID]>90) diff = diff-2 ; ///step02 if(angle[angleID]<0 ) diff = diff+2 ; ///step02 glutPostRedisplay();///以前會用 display()重畫, 現在這個會比較好 */ }///程式搬家,改用mouse motion來做動作 void mouse(int button, int state, int x, int y) { oldX = x;///當mouse按下去時,記下位置 } void motion(int x,int y) { angle[angleID] += x - oldX;///用x-oldX oldX=x;///在更新位置 glutPostRedisplay();///以前會用 display()重畫, 現在這個會比較好 }













glutMouseFunc(mouse); glutMotionFunc(motion);///main()裡面記得呼叫兩個函式



------------------------------------------------------------------------------------------------------.


(2) 存讀檔

            1.把角度輸出存讀檔

                FILE * fout = NULL; ///宣告檔案指標

        if(fout==NULL) fout=fopen("angle.txt", "w+");         for(int i=0; i<20; i++) fprintf( fout , "%.1f ", angle[i]);         fprintf( fout , "\n" );///以上兩行,寫到檔案





FILE * fout = NULL; ///宣告檔案指標 void motion(int x,int y) { angle[angleID] += x - oldX;///用x-oldX oldX=x;///在更新位置 glutPostRedisplay();///以前會用 display()重畫, 現在這個會比較好 if(fout==NULL) fout=fopen("angle.txt", "w+"); for(int i=0; i<20; i++) fprintf( fout , "%.1f ", angle[i]); fprintf( fout , "\n" );///以上兩行,寫到檔案 for(int i=0; i<20; i++) printf( "%.1f ", angle[i]); printf( "\n" );///以上2行,印到畫面(讓你了解印了什麼資料) }










        2. 播放動畫    利用Timer播放動畫
                
                程式會去讀檔案改變角度,形成動畫的效果

            


FILE * fin = NULL;///step02-2 播放動畫,檔案指標fin void timer(int t) { glutTimerFunc( 30 , timer , t+1 );///step02-2 播放動畫 if( fin==NULL ) fin = fopen( "angle.txt", "r" );///step02-2 for(int i=0; i<20; i++) fscanf( fin, "%f", & angle[i] );///step02-2 glutPostRedisplay();///step02-2 播放動畫 重畫畫面 }








        3. 改工作執行目錄 (閉著眼睛我都會改,不寫了)


---------------------------------------------------------------------------------------------


(3)內插

            1.註解掉motion的存檔、Timer的讀檔,改用keyboard控制存讀檔!



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

{ if(key=='l')///load存檔, 把所有的動作存檔後, 要關掉 { if(fout==NULL) fout=fopen("angle.txt", "w+"); for(int i=0; i<20; i++) fprintf( fout , "%.1f ", angle[i]); fprintf( fout , "\n" );///以上兩行,寫到檔案 for(int i=0; i<20; i++) printf( "%.1f ", angle[i]); printf( "\n" );///以上2行,印到畫面(讓你了解印了什麼資料) } if(key=='r')///Read讀檔, 再開之後, 才能讀檔 { if( fin==NULL ) fin = fopen( "angle.txt", "r" );///step02-2 for(int i=0; i<20; i++) fscanf( fin, "%f", & angle[i] );///step02-2 glutPostRedisplay();///step02-2 播放動畫 重畫畫面 } if(key=='p')///play利用Timer整個播放, 再開之後, 才能讀檔 { }  

}          










        2.內插

           利用timer()來做出動畫的內插,其中(1)要更新angle[i]再重畫, (2)利用alpha介於0到1中間,進行alpha乘angleNew[i]+(1-alpha乘angleOld[i], (3) if(t%10==0)來決定更新新舊的時間,(4)alpha怎麼算

            借用老師的圖,講太快了來不及做筆記...




#include <stdio.h> #include <GL/glut.h> float angle[20]={}, diff=2;///angle[i]畫的角度,內插 angleOld[i] angleNew[i] float angleOld[20]={}, angleNew[20]={};///step03-2 新舊資料準備內插 int angleID=0; int oldX=0; FILE * fout = NULL; ///宣告檔案指標 FILE * fin = NULL;///step02-2 播放動畫,檔案指標fin void timer(int t) { glutTimerFunc( 30 , timer , t+1 );///step02-2 播放動畫 if( t%30==0 )///step03-2 每30frame,就讀一筆新資料 { for(int i=0; i<20; i++) angleOld[i] = angleNew[i];///Step03-2 ///讀新資料之前,要先把資料備份^^^^^^^^^^^^^^ if( fin==NULL ) fin = fopen( "angle.txt", "r" );///step03-2 for(int i=0; i<20; i++) fscanf( fin, "%f", & angleNew[i] );///step03-2 } ///再讀入新的資料 angleNew[i] ^^^^^^^^^^^^^^^^^^^^^ float alpha = (t%30)/30.0; for(int i=0; i<20; i++) { angle[i] = alpha*angleNew[i] + (1-alpha)*angleOld[i]; } glutPostRedisplay();///播放動畫 重畫畫面 }
void mouse(int button, int state, int x, int y) { oldX = x;///當mouse按下去時,記下位置 } void motion(int x,int y) { angle[angleID] += x - oldX;///用x-oldX oldX=x;///在更新位置 glutPostRedisplay();///以前會用 display()重畫, 現在這個會比較好 /* if(fout==NULL) fout=fopen("angle.txt", "w+"); for(int i=0; i<20; i++) fprintf( fout , "%.1f ", angle[i]); fprintf( fout , "\n" );///以上兩行,寫到檔案 for(int i=0; i<20; i++) printf( "%.1f ", angle[i]); printf( "\n" );///以上2行,印到畫面(讓你了解印了什麼資料) */ } void keyboard( unsigned char key, int x, int y) ///step02 { if(key=='1') angleID=1; ///step02 if(key=='2') angleID=2; ///step02 if(key=='3') angleID=3; if(key=='4') angleID=4; if(key=='0') angleID=0; ///全部停止 if(key=='l')///load存檔, 把所有的動作存檔後, 要關掉 { if(fout==NULL) fout=fopen("angle.txt", "w+"); for(int i=0; i<20; i++) fprintf( fout , "%.1f ", angle[i]); fprintf( fout , "\n" );///以上兩行,寫到檔案 for(int i=0; i<20; i++) printf( "%.1f ", angle[i]); printf( "\n" );///以上2行,印到畫面(讓你了解印了什麼資料) } if(key=='r')///Read讀檔, 再開之後, 才能讀檔 { if( fin==NULL ) fin = fopen( "angle.txt", "r" );///step02-2 for(int i=0; i<20; i++) fscanf( fin, "%f", & angle[i] );///step02-2 glutPostRedisplay();///step02-2 播放動畫 重畫畫面 } if(key=='p')///play利用Timer整個播放, 再開之後, 才能讀檔 { } } void display() { glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); glPushMatrix(); glutSolidTeapot(0.3);///身體 glPushMatrix();///左手 glTranslatef(-0.3, 0, 0 );///(3)掛在正確的地方 glRotatef(angle[1], 0, 0, 1);///(2)旋轉 ///step02 glTranslatef(-0.4, 0, 0 );///(1)把關節旋轉中心放到畫面中心 glutSolidTeapot(0.3);///左手臂 glPushMatrix(); glTranslatef(-0.3, 0, 0 );///(3)掛在正確的地方 glRotatef(angle[2], 0, 0, 1);///(2)旋轉 ///step02 glTranslatef(-0.4, 0, 0 );///(1)把關節旋轉中心放到畫面中心 glutSolidTeapot(0.3);///左手肘 glPopMatrix(); glPopMatrix(); glPopMatrix(); glPushMatrix();///右手 glTranslatef(0.3, 0, 0 );///(3)掛在正確的地方 glRotatef(-angle[3], 0, 0, 1);///(2)旋轉 ///step02 glTranslatef(0.4, 0, 0 );///(1)把關節旋轉中心放到畫面中心 glutSolidTeapot(0.3);///左手臂 glPushMatrix(); glTranslatef(0.3, 0, 0 );///(3)掛在正確的地方 glRotatef(-angle[4], 0, 0, 1);///(2)旋轉 ///step02 glTranslatef(0.4, 0, 0 );///(1)把關節旋轉中心放到畫面中心 glutSolidTeapot(0.3);///左手肘 glPopMatrix(); glPopMatrix(); glutSwapBuffers(); } int main( int argc, char ** argv ) { glutInit( &argc, argv ); glutInitDisplayMode(GLUT_DOUBLE | GLUT_DEPTH); glutCreateWindow("week16 test"); glutMouseFunc(mouse); glutMotionFunc(motion);///main()裡面記得呼叫兩個函式 glutKeyboardFunc(keyboard);///整合很多關節 會去改angleID glutTimerFunc(0, timer, 0);///設第一個Timer設定動畫 glutDisplayFunc(display); glutMainLoop(); }







































































沒有留言:

張貼留言

距地表面160 Week11

 #include "glm.h" GLMmodel* pmodel = NULL; void drawmodel(void) {     if (!pmodel) { pmodel = glmReadOBJ("data/porsche.obj...