2021年6月16日 星期三

築損 Week17

 第1部份

總複習

基本執行程式

先顯示出茶壺

程式碼

#include <GL/glut.h> void display(){ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glutSolidTeapot( 0.3 ); glutSwapBuffers(); } int main( int argc, char ** argv ) { glutInit( &argc, argv); glutInitDisplayMode(GLUT_DOUBLE|GLUT_DEPTH); glutCreateWindow("week17 review"); glutDisplayFunc(display); glutMainLoop(); }











調整視窗大小跟位置

glutCreateWindow("week17 review"); glutInitWindowSize(500,500);



將背景換成紅色,將茶壺換成黃色

void display(){ glClearColor(1,0,0,0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glColor3f(1,1,0); glutSolidTeapot( 0.3 ); glutSwapBuffers(); }




新增第二個小茶壺,顏色是紅色

void display(){ glClearColor(1,0,0,0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glColor3f(1,1,0); glutSolidTeapot( 0.3 ); glColor3f(1,0,0); glutSolidTeapot(0.1); glutSwapBuffers(); }





加上打光

要寫在main函式前

const GLfloat light_ambient[] = { 0.0f, 0.0f, 0.0f, 1.0f }; const GLfloat light_diffuse[] = { 1.0f, 1.0f, 1.0f, 1.0f }; const GLfloat light_specular[] = { 1.0f, 1.0f, 1.0f, 1.0f }; const GLfloat light_position[] = { 2.0f, 5.0f, -5.0f, 0.0f }; const GLfloat mat_ambient[] = { 0.7f, 0.7f, 0.7f, 1.0f }; const GLfloat mat_diffuse[] = { 0.8f, 0.8f, 0.8f, 1.0f }; const GLfloat mat_specular[] = { 1.0f, 1.0f, 1.0f, 1.0f }; const GLfloat high_shininess[] = { 100.0f };





要寫在main函式裡glutMainloop()前

glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LESS); glEnable(GL_LIGHT0); glEnable(GL_NORMALIZE); glEnable(GL_COLOR_MATERIAL); glEnable(GL_LIGHTING); glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient); glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse); glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular); glLightfv(GL_LIGHT0, GL_POSITION, light_position); glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient); glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse); glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular); glMaterialfv(GL_FRONT, GL_SHININESS, high_shininess);








把視窗縮小

新增手臂,加上TRT

float angle=90; void display(){ glClearColor( 1,0,0,0);///用來Clear的Color 用紅色 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glPushMatrix(); glColor3f( 1,1,0 ); glutSolidTeapot( 0.3 );///身體先註解掉身體,只看手臂 glPushMatrix(); glTranslatef(-.3, 0, 0);///(3)再把轉動中的手臂,掛到肩上 glRotatef(angle, 0,0,1);///(2)再轉動它 glTranslatef(-.3, .1, 0);///(1)移動旋轉中心,放正中心 glutSolidTeapot(0.3);///左手臂 glPopMatrix(); glPopMatrix(); glutSwapBuffers(); }







加上mouse motion 讓滑鼠能控制

float oldX=0; void mouse(int button, int state, int x, int y){ oldX = x; } void motion( int x, int y ){ angle += x-oldX; oldX = x;//小心,不要漏掉了 glutPostRedisplay();///重畫畫面 }







記得要在main函式中呼叫mouse motion

glutMouseFunc(mouse);

glutMotionFunc(motion);

新增keyboard控制多個關節轉動

float angle[20]={};///先都設成0 int angleId=0;///現在要動的關節是誰? 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; if(key=='4') angleId=4; if(key=='5') angleId=5; if(key=='6') angleId=6; }






記得在main函式裡註冊keyboard

glutKeyboardFunc(keyboard);

左邊用好複製右手

void display(){ glClearColor( 1,0,0,0);///用來Clear的Color 用紅色 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glPushMatrix(); glColor3f( 1,1,0 ); glutSolidTeapot( 0.3 );///身體先註解掉身體,只看手臂 glPushMatrix();///左半邊 glTranslatef(-.3, 0, 0);///(3)再把轉動中的手臂,掛到肩上 glRotatef(angle[0], 0,0,1);///(2)再轉動它 glTranslatef(-.3, .1, 0);///(1)移動旋轉中心,放正中心 glutSolidTeapot(0.3);///左手臂 glPushMatrix(); glTranslatef(-.3, 0, 0);///(3)再把轉動中的手臂,掛到肩上 glRotatef(angle[1], 0,0,1);///(2)再轉動它 glTranslatef(-.3, 0, 0);///(1)移動旋轉中心,放正中心 glutSolidTeapot(0.3);///左手肘 glPopMatrix(); glPopMatrix(); glPushMatrix();///右半邊 glTranslatef(+.3, 0, 0);///(3)再把轉動中的手臂,掛到肩上 glRotatef(angle[2], 0,0,1);///(2)再轉動它 glTranslatef(+.3, .1, 0);///(1)移動旋轉中心,放正中心 glutSolidTeapot(0.3);///右手臂 glPushMatrix(); glTranslatef(+.3, 0, 0);///(3)再把轉動中的手臂,掛到肩上 glRotatef(angle[3], 0,0,1);///(2)再轉動它 glTranslatef(+.3, 0, 0);///(1)移動旋轉中心,放正中心 glutSolidTeapot(0.3);///右手肘 glPopMatrix(); glPopMatrix(); glPopMatrix(); glutSwapBuffers(); }














新增存讀檔

#include <stdio.h>

FILE * fout = NULL;

FILE * fin = NULL;

    if(key=='s'){///存檔 if( fout==NULL ) fout = fopen("angle.txt", "w+"); for(int i=0; i<20; i++) fprintf(fout, "%.2f ", angle[i]); fprintf(fout, "\n"); printf("save angle.txt\n"); }else if(key=='r'){///讀檔 (不能和存檔同時做,因angle.txt不能開2次) if( fin==NULL ) fin = fopen("angle.txt", "r"); for(int i=0; i<20; i++) fscanf(fin, "%f", &angle[i]); glutPostRedisplay();///重畫畫面 printf("read angle.txt\n"); }






執行後會在專案中新增angle.txt

按下s會儲存座標 按下r會執行angle.txt 中的座標

新增動畫

加上timer

void timer(int t){ glutTimerFunc( 500, timer, t+1); if( fin==NULL ) fin = fopen("angle.txt", "r"); for(int i=0; i<20; i++) fscanf(fin, "%f", &angle[i]); glutPostRedisplay();///重畫畫面 printf("read angle.txt\n"); }




在keyboard裡用按鍵控制timer

if(key=='p'){///Play播放

        glutTimerFunc(0, timer, 0);///一開始的第1個timer

    }

加上alpha讓動畫從定格變流暢

float angle[20]={}, angleOld[20], angleNew[20];///先都設成0

void timer(int t){ glutTimerFunc( 20, timer, t+1); if(t%25==0){ for(int i=0; i<20; i++) angleOld[i] = angleNew[i]; if( fin==NULL ) fin = fopen("angle.txt", "r"); for(int i=0; i<20; i++) fscanf(fin, "%f", &angleNew[i]); printf("read angle.txt\n"); } float alpha = (t%25)/25.0;///介於 0.0 舊 - 1.0 新 之間 (請代入 0, 0.5, 1 觀察) for(int i=0; i<20; i++) angle[i] = alpha*angleNew[i]+(1-alpha)*angleOld[i]; glutPostRedisplay();///重畫畫面 }







這樣就能順暢地播放動畫

執行結果


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

全部程式碼

#include <GL/glut.h> #include <stdio.h> FILE * fout = NULL; FILE * fin = NULL; float angle[20]={}, angleOld[20], angleNew[20];///先都設成0 int angleID=0;///現在要動的關節是誰? void timer(int t){ glutTimerFunc( 20, timer, t+1); if(t%25==0){ for(int i=0; i<20; i++) angleOld[i] = angleNew[i]; if( fin==NULL ) fin = fopen("angle.txt", "r"); for(int i=0; i<20; i++) fscanf(fin, "%f", &angleNew[i]); printf("read angle.txt\n"); } float alpha = (t%25)/25.0;///介於 0.0 舊 - 1.0 新 之間 (請代入 0, 0.5, 1 觀察) for(int i=0; i<20; i++) angle[i] = alpha*angleNew[i]+(1-alpha)*angleOld[i]; glutPostRedisplay();///重畫畫面 } 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; if(key=='4') angleID=4; if(key=='5') angleID=5; if(key=='6') angleID=6; if(key=='p'){///Play播放 glutTimerFunc(0, timer, 0);///一開始的第1個timer } if(key=='s'){///存檔 if( fout==NULL ) fout = fopen("angle.txt", "w+"); for(int i=0; i<20; i++) fprintf(fout, "%.2f ", angle[i]); fprintf(fout, "\n"); printf("save angle.txt\n"); }else if(key=='r'){///讀檔 (不能和存檔同時做,因angle.txt不能開2次) if( fin==NULL ) fin = fopen("angle.txt", "r"); for(int i=0; i<20; i++) fscanf(fin, "%f", &angle[i]); glutPostRedisplay();///重畫畫面 printf("read angle.txt\n"); } }///如果關節很多, 可能要用迴圈來讓程式只要2行 for(int i=0; i<10; i++) ///可能也要用到英文字母 float oldX=0; void mouse(int button, int state, int x, int y){ oldX = x; } void motion( int x, int y ){ angle[angleID] += x-oldX;///0: angle[0], 1: angle[1].. oldX = x; glutPostRedisplay();///重畫畫面 } void display(){ glClearColor( 1,0,0,0);///用來Clear的Color 用紅色 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glPushMatrix(); glColor3f( 1,1,0 ); glutSolidTeapot( 0.3 );///身體先註解掉身體,只看手臂 glPushMatrix();///左半邊 glTranslatef(-.3, 0, 0);///(3)再把轉動中的手臂,掛到肩上 glRotatef(angle[0], 0,0,1);///(2)再轉動它 glTranslatef(-.3, .1, 0);///(1)移動旋轉中心,放正中心 glutSolidTeapot(0.3);///左手臂 glPushMatrix(); glTranslatef(-.3, 0, 0);///(3)再把轉動中的手臂,掛到肩上 glRotatef(angle[1], 0,0,1);///(2)再轉動它 glTranslatef(-.3, 0, 0);///(1)移動旋轉中心,放正中心 glutSolidTeapot(0.3);///左手肘 glPopMatrix(); glPopMatrix(); glPushMatrix();///右半邊 glTranslatef(+.3, 0, 0);///(3)再把轉動中的手臂,掛到肩上 glRotatef(angle[2], 0,0,1);///(2)再轉動它 glTranslatef(+.3, .1, 0);///(1)移動旋轉中心,放正中心 glutSolidTeapot(0.3);///右手臂 glPushMatrix(); glTranslatef(+.3, 0, 0);///(3)再把轉動中的手臂,掛到肩上 glRotatef(angle[3], 0,0,1);///(2)再轉動它 glTranslatef(+.3, 0, 0);///(1)移動旋轉中心,放正中心 glutSolidTeapot(0.3);///右手肘 glPopMatrix(); glPopMatrix(); glPopMatrix(); glutSwapBuffers(); } const GLfloat light_ambient[] = { 0.0f, 0.0f, 0.0f, 1.0f }; const GLfloat light_diffuse[] = { 1.0f, 1.0f, 1.0f, 1.0f }; const GLfloat light_specular[] = { 1.0f, 1.0f, 1.0f, 1.0f }; const GLfloat light_position[] = { 2.0f, 5.0f, -5.0f, 0.0f }; const GLfloat mat_ambient[] = { 0.7f, 0.7f, 0.7f, 1.0f }; const GLfloat mat_diffuse[] = { 0.8f, 0.8f, 0.8f, 1.0f }; const GLfloat mat_specular[] = { 1.0f, 1.0f, 1.0f, 1.0f }; const GLfloat high_shininess[] = { 100.0f }; int main( int argc, char ** argv ) { glutInit( &argc, argv); glutInitWindowSize(300,300); glutInitWindowPosition(700,200); glutInitDisplayMode(GLUT_DOUBLE|GLUT_DEPTH); glutCreateWindow("week17 review"); glutKeyboardFunc(keyboard); glutMouseFunc(mouse); glutMotionFunc(motion); glutDisplayFunc(display); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LESS); glEnable(GL_LIGHT0); glEnable(GL_NORMALIZE); glEnable(GL_COLOR_MATERIAL); glEnable(GL_LIGHTING); glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient); glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse); glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular); glLightfv(GL_LIGHT0, GL_POSITION, light_position); glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient); glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse); glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular); glMaterialfv(GL_FRONT, GL_SHININESS, high_shininess); glutMainLoop(); }


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

沒有留言:

張貼留言

距地表面160 Week11

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