# Week16
做內插,把動作串起來。
step01-1 利用Excel練習內插
-打開Excel
-有參數time,alpha和angle
-內插公式:alpha*新的+(1-alpha)*舊的
*利用上述的公式,去算出每秒手臂轉的比例,每秒動多少角度,最後完成動作,這就是動畫的效果。
step01-2 利用上週的week15_angles_TRT_again去做改裝,做出動作內插
-打開新的GLUT專案,檔案名稱取名為week16_interpolation
-先複製上週的程式碼
-加上執行內插的程式
操作流程:
(記得file.txt要先有動作儲存著)
-按兩次'r'
-然後,再按'p'鍵
內插就出來了!
```Cpp
#include <GL/glut.h>
#include <stdio.h>//為了printf,fprintf,fopen,fclose
float angle[20],oldX=0;
int angleID=0;
FILE * fout = NULL,*fin=NULL;
void myWrite()
{
if(fout==NULL) fout=fopen("file.txt","w+");
for(int i=0;i<20;i++)
{
printf( "%.2f",angle[i]);
fprintf(fout,"%.2f ",angle[i]);
}
printf("\n");
fprintf(fout,"\n");
}
float NewAngle[20],OldAngle[20];
void myRead()
{
if(fout!=NULL){
fclose(fout);fout=NULL;
}
if(fin==NULL) fin=fopen("file.txt","r");
for(int i=0;i<20;i++)
{
OldAngle[i]=NewAngle[i];
fscanf(fin, "%f",&NewAngle[i]);
}
glutPostRedisplay();
}
void myInterpolate(float alpha)
{
for(int i=0;i<20;i++)
{
angle[i]=alpha*NewAngle[i]+(1-alpha)*OldAngle[i];
printf("%.2f ",angle[i]);
}
printf("\n");
glutPostRedisplay();
}
float alpha=0;
void keyboard(unsigned char key,int x,int y)
{
if(key=='p')
{
myInterpolate(alpha);
alpha=(alpha+0.01);
if(alpha>1)alpha=alpha-1;
}
if(key=='r')myRead();
if(key=='s')myWrite();
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)//mosue按下去
{
oldX=x;
}
void motion(int x,int y)
{
angle[angleID]+=(x-oldX);
///myWrite();
oldX=x;
glutPostRedisplay();
}
void display()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor3f(1,1,1);
glRectf(0.3,0.5,-0.3,-0.2);//正方形當作身體
glPushMatrix(); //右半邊
glTranslatef(0.3,0.5,0);
glRotatef(angle[0],0,0,1);
glTranslatef(-0.3,-0.4,0);
glColor3f(1,0,0);
glRectf(0.3,0.5,0.8,0.3);
glPushMatrix();
glTranslatef(0.8,0.4,0);//(3)把下手臂掛在關節上
glRotatef(angle[1],0,0,1);//(2)旋轉
glTranslatef(-0.8,-0.4,0);//(1)把下手臂的旋轉中心,放正中心
glColor3f(0,1,0);
glRectf(0.8,0.5,1.1,0.3);//再畫下手臂
glPopMatrix();
glPopMatrix();
glPushMatrix(); //左半邊
glTranslatef(-0.3,0.5,0);
glRotatef(angle[2],0,0,1);
glTranslatef(+0.3,-0.4,0);
glColor3f(1,0,0);
glRectf(-0.3,0.5,-0.8,0.3);
glPushMatrix();
glTranslatef(-0.8,0.4,0);//(3)把下手臂掛在關節上
glRotatef(angle[3],0,0,1);//(2)旋轉
glTranslatef(+0.8,-0.4,0);//(1)把下手臂的旋轉中心,放正中心
glColor3f(0,1,0);
glRectf(-0.8,0.5,-1.1,0.3);//再畫下手臂
glPopMatrix();
glPopMatrix();
glutSwapBuffers();
}
int main(int argc,char**argv)
{
glutInit(&argc,argv);
glutInitDisplayMode( GLUT_DOUBLE | GLUT_DEPTH );
glutCreateWindow("week15 angles TRT again");
glutKeyboardFunc(keyboard);
glutMouseFunc(mouse);
glutMotionFunc(motion);
glutDisplayFunc( display );
glutMainLoop();
}
```
step02-1 利用timer自動做內插
-程式先存4個動作(file.txt)
-利用glutTimerFunc(0,timer,0); 播放
-在if(key=='p') 進行播放的動作
-依照時間的流動,算出適當的alpha
操作過程:
-要記得先存動作(把程式碼關掉後)
-程式執行,按下p,就會開始播放動作
-file.txt全部讀完後,動作就會卡在那邊(正常的!)
```Cpp
#include <GL/glut.h>
#include <stdio.h>//為了printf,fprintf,fopen,fclose
float angle[20],oldX=0;
int angleID=0;
FILE * fout = NULL,*fin=NULL;
void myWrite()
{
if(fout==NULL) fout=fopen("file.txt","w+");
for(int i=0;i<20;i++)
{
printf( "%.2f",angle[i]);
fprintf(fout,"%.2f ",angle[i]);
}
printf("\n");
fprintf(fout,"\n");
}
float NewAngle[20],OldAngle[20];
void myRead()
{
if(fout!=NULL){
fclose(fout);fout=NULL;
}
if(fin==NULL) fin=fopen("file.txt","r");
for(int i=0;i<20;i++)
{
OldAngle[i]=NewAngle[i];
fscanf(fin, "%f",&NewAngle[i]);
}
glutPostRedisplay();
}
void myInterpolate(float alpha)
{
for(int i=0;i<20;i++)
{
angle[i]=alpha*NewAngle[i]+(1-alpha)*OldAngle[i];
printf("%.2f ",angle[i]);
}
printf("\n");
glutPostRedisplay();
}
float alpha=0;
void timer(int t)
{
float alpha=(t%100)/100.0;
if(t%100==0) myRead();//做交接
myInterpolate(alpha);
glutTimerFunc(33,timer,t+1);
}
void keyboard(unsigned char key,int x,int y)
{
if(key=='p')
{
myRead();
glutTimerFunc(0,timer,0);
//myInterpolate(alpha);
//alpha=(alpha+0.01);
//if(alpha>1)alpha=alpha-1;
}
if(key=='r')myRead();
if(key=='s')myWrite();
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)//mosue按下去
{
oldX=x;
}
void motion(int x,int y)
{
angle[angleID]+=(x-oldX);
///myWrite();
oldX=x;
glutPostRedisplay();
}
void display()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor3f(1,1,1);
glRectf(0.3,0.5,-0.3,-0.2);//正方形當作身體
glPushMatrix(); //右半邊
glTranslatef(0.3,0.5,0);
glRotatef(angle[0],0,0,1);
glTranslatef(-0.3,-0.4,0);
glColor3f(1,0,0);
glRectf(0.3,0.5,0.8,0.3);
glPushMatrix();
glTranslatef(0.8,0.4,0);//(3)把下手臂掛在關節上
glRotatef(angle[1],0,0,1);//(2)旋轉
glTranslatef(-0.8,-0.4,0);//(1)把下手臂的旋轉中心,放正中心
glColor3f(0,1,0);
glRectf(0.8,0.5,1.1,0.3);//再畫下手臂
glPopMatrix();
glPopMatrix();
glPushMatrix(); //左半邊
glTranslatef(-0.3,0.5,0);
glRotatef(angle[2],0,0,1);
glTranslatef(+0.3,-0.4,0);
glColor3f(1,0,0);
glRectf(-0.3,0.5,-0.8,0.3);
glPushMatrix();
glTranslatef(-0.8,0.4,0);//(3)把下手臂掛在關節上
glRotatef(angle[3],0,0,1);//(2)旋轉
glTranslatef(+0.8,-0.4,0);//(1)把下手臂的旋轉中心,放正中心
glColor3f(0,1,0);
glRectf(-0.8,0.5,-1.1,0.3);//再畫下手臂
glPopMatrix();
glPopMatrix();
glutSwapBuffers();
}
int main(int argc,char**argv)
{
glutInit(&argc,argv);
glutInitDisplayMode( GLUT_DOUBLE | GLUT_DEPTH );
glutCreateWindow("week15 angles TRT again");
glutKeyboardFunc(keyboard);
glutMouseFunc(mouse);
glutMotionFunc(motion);
glutDisplayFunc( display );
glutMainLoop();
}
```
step03-1 運鏡
-打開老師的網址,下載win32&data,data解壓縮後放進解壓縮後的window資料夾裡:打開Projection.exe
-gluLookAt()改變裡面的參數:
- 眼睛在哪裡(從哪裡看)
- 要看哪裡((要拍誰(向哪裡)),相機的正中間要向哪裡)
- 相機是否旋轉(通常都設定為0,1,0)(食指向哪裡,unity的x,y,z的感覺。)
做投影的時候,會有一個神奇的函式resize
-aspect ratio=螢幕的長寬比=寬度/高度(寬度除高度)
step03-2 實作程式:利用滑鼠改變lookAt位置
沒有留言:
張貼留言