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();
}
沒有留言:
張貼留言