2021年6月16日 星期三

電腦圖學 week17

可以從老師那邊複製程式https://hackmd.io/@jsyeh/opengl

step01_老師新開GLUT專案, 寫出最精簡的程式, 畫出茶壼, 改變 glClearColor() 及 glColor3f() 再加上打光的陣列、打光的函式,光的位置也改了一下,並解釋glEnable(GL_DEPTH_TEST)

 #include <GL/glut.h>

void display()

{

    glClearColor( 1,0,0,0);///用來Clear的Color 用紅色

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        glColor3f( 1,1,0 );///讓茶壺變黃色

        glutSolidTeapot( 0.3 );

    glutSwapBuffers();

}

int main( int argc, char ** argv )

{

    glutInit( &argc, argv );

    glutInitDisplayMode(GLUT_DOUBLE | GLUT_DEPTH);

    glutInitWindowSize(500,500);///可以設定大一點

    glutInitWindowPosition(0,0);///位置

    glutCreateWindow("week17");


    glutDisplayFunc(display);

    glutMainLoop();

}


void display()
{
    glClearColor( 1,0,0,0);///用來Clear的Color 用紅色
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        glColor3f( 1,1,0 );///讓茶壺變黃色
        glutSolidTeapot( 0.3 );

        glColor3f( 1,0,0 );///紅色
        glutSolidTeapot( 0.1 );
    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 };///改成-5.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 };


glEnable(GL_DEPTH_TEST);///3D測是要打開
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);
step01-2_老師講解T-R-T的作法, 並回憶之前的教轉動時,用個時鐘、紙片來看如何轉動
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)再把轉動中的手臂,掛到肩上
glRotatef();///(2)再轉動它
glTranslatef(-0.3, 0.1, 0);///(1)移動旋轉中心,放正中心
glutSolidTeapot(0.3);///左手臂
glPopMatrix();
glPopMatrix();
glutSwapBuffers();
}
step02_利用mouse()及motion()來轉動, 其中有用到 angle += x-oldX
老師利用捲尺來示範講解, 同時要把 oldX=x; 設定新的關始點。
別忘了 glutPostRedisplay()重畫畫面,
還有 glutMouseFunc() glutMotionFunc()
float angle=45,oldX,oldY;
void mouse(int button,int state,int x,int y){
oldX = x;
}
void motion(int x,int y){
angle += x - oldX;
oldX = x;
glutPostRedisplay();
}
    glutMouseFunc(mouse);
glutMotionFunc(motion);

step03_利用keyboard()來切換angleID, 再於 display()裡, 依照 angle[0]
angle[1] angle[2]等去畫出正確姿勢的圖, 記得要glutKeyboardFunc()註冊, 同時在 motion()裡用
angle[angleID]來改變特定的關節
#include <stdio.h>
#include <GL/glut.h>
float angle[20]={};///大括號,表示會自己補0
int angleID = 0;///
float oldX,oldY;
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;
}
void mouse(int button,int state,int x,int y){
    oldX = x;
}
void motion(int x,int y){
    angle[angleID] += x - oldX;
    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(-0.3, 0, 0);///(3)再把轉動中的手臂,掛到肩上
            glRotatef(angle[0], 0,0,1);///(2)再轉動它
            glTranslatef(-0.3,0.1, 0);///(1)移動旋轉中心,放正中心
            glutSolidTeapot(0.3);///左手臂
            glPushMatrix();
                glTranslatef(-0.3, 0, 0);///(3)再把轉動中的手臂,掛到肩上
                glRotatef(angle[1], 0,0,1);///(2)再轉動它
                glTranslatef(-0.3, 0, 0);///(1)移動旋轉中心,放正中心
                glutSolidTeapot(0.3);///左手肘
            glPopMatrix();
        glPopMatrix();
        glPushMatrix();///右半邊
            glTranslatef(+0.3, 0, 0);///(3)再把轉動中的手臂,掛到肩上
            glRotatef(angle[2], 0,0,1);///(2)再轉動它
            glTranslatef(+0.3,0.1, 0);///(1)移動旋轉中心,放正中心
            glutSolidTeapot(0.3);///右手臂
            glPushMatrix();
                glTranslatef(+0.3, 0, 0);///(3)再把轉動中的手臂,掛到肩上
                glRotatef(angle[3], 0,0,1);///(2)再轉動它
                glTranslatef(+0.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 );
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_DEPTH);
    ///glutInitWindowSize(500,500);///可以設定大一點
    glutInitWindowPosition(0,0);///位置
    glutCreateWindow("week17");

    glutKeyboardFunc(keyboard);///要有這行, 註冊 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();
}

step04_要進行存檔、讀檔,所以要有 stdio.h 及 FILE 指標 fout=NULL 及 FILE 指標 fin=NULL 小心,不要宣告成 ==NULL哦! 在keyboard()的 save時, if(fout==NULL) fout=fopen()開檔 並用for迴圈把 angle[i]全部寫檔。在 read時, 就for迴圈一次讀一整行,並glutPostRedisplay()更新畫面

if(key=='s'){///save 存檔
if( fout==NULL ) fout = fopen("angle.txt", "w+");///write加檔案
for(int i=0; i<20; i++) fprintf(fout, "%.2f ", angle[i]);
fprintf(fout, "\n");
printf("save angle.txt\n");///幫你確定你有存一行關節
}///程式要整個關掉(or fclose(fout),檔案確定你有存一行關節
    else if(key=='r'){///read 讀檔 (不能和存檔同時做,因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");
}
step05_利用上週教的動畫內插法,先按 p 呼叫第1個 glutTimerFunc(0, timer, 0)
接下來 timer()裡,會叫用下一次timer(t+1) 而且每過 t%10==0 時就重讀新舊資料,
angle[i] = alpha乘angleNew[i]+alpha乘angleOld[i] 來進行alpha內插
#include <stdio.h> #include <GL/glut.h> float angle[20]={},angleOld[20],angleNew[20];///大括號,表示會自己補0 int angleID = 0;/// float oldX,oldY; FILE * fout = NULL; FILE * fin = NULL; void timer(int t){ glutTimerFunc(16,timer,t+1); if(t%30==0){ for(int i=0;i<20;i++) angleOld[i]=angleNew[i];///備份資料 if(fin==NULL) fin = fopen("angle.txt","r");///read for(int i=0;i<20;i++) fscanf(fin,"%f",&angleNew[i]);///讀到angleNew } float alpha=(t%30)/30.0; 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') glutTimerFunc(0, timer, 0); if(key=='s'){///save 存檔 if(fout==NULL) fout = fopen("angle.txt","w+");///write加檔案 for(int i=0;i<20;i++) fprintf(fout,"%.2f",angle[i]); fprintf(fout,"\n"); printf("save one line\n");///幫你確定你有存一行關節 }///程式要整個關掉(or fclose(fout),檔案確定你有存一行關節 if(key=='r'){///read 讀檔 if(fin==NULL) fin = fopen("angle.txt","r"); for(int i=0;i<20;i++) fscanf(fin,"%f",&angle[i]); glutPostRedisplay();///重畫畫面 } } void mouse(int button,int state,int x,int y){ oldX = x; } void motion(int x,int y){ angle[angleID] += x - oldX; 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(-0.3, 0, 0);///(3)再把轉動中的手臂,掛到肩上 glRotatef(angle[0], 0,0,1);///(2)再轉動它 glTranslatef(-0.3,0.1, 0);///(1)移動旋轉中心,放正中心 glutSolidTeapot(0.3);///左手臂 glPushMatrix(); glTranslatef(-0.3, 0, 0);///(3)再把轉動中的手臂,掛到肩上 glRotatef(angle[1], 0,0,1);///(2)再轉動它 glTranslatef(-0.3, 0, 0);///(1)移動旋轉中心,放正中心 glutSolidTeapot(0.3);///左手肘 glPopMatrix(); glPopMatrix(); glPushMatrix();///右半邊 glTranslatef(+0.3, 0, 0);///(3)再把轉動中的手臂,掛到肩上 glRotatef(angle[2], 0,0,1);///(2)再轉動它 glTranslatef(+0.3,0.1, 0);///(1)移動旋轉中心,放正中心 glutSolidTeapot(0.3);///右手臂 glPushMatrix(); glTranslatef(+0.3, 0, 0);///(3)再把轉動中的手臂,掛到肩上 glRotatef(angle[3], 0,0,1);///(2)再轉動它 glTranslatef(+0.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 ); glutInitDisplayMode(GLUT_DOUBLE | GLUT_DEPTH); ///glutInitWindowSize(500,500);///可以設定大一點 glutInitWindowPosition(0,0);///位置 glutCreateWindow("week17"); glutKeyboardFunc(keyboard);///要有這行, 註冊 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...