2023年5月24日 星期三

rita - week15 - 主題: 攝影機 Camera 2.投影、運鏡 gluPerspective(), gluLookAt() 3. 期末作品

         去到https://jsyeh.org/3dcg10/

        下載  1.[data]  2.[win32] 兩個檔案 並且解壓縮win32

        將data丟進解壓縮後的windows 

打開projection.exe
1.從哪去看這個模型
2.看模型的哪裡

3.就像用相機拍攝一樣 食指為up向量
每個人拍照角度都不同(有人橫的拍,斜的拍,直的拍)

1.field of view (y方向) 視野的角度
2.aspect ratio 長寬比
3.4.在z方向去決定那些範圍的內容會被投影到方塊內,再壓扁畫出來

    打開git bash / cd desktop / git clone https://github.com/ritahsiao/2023graphicsa

去到雲端把2023graphicsa資料夾下載下來

    開啟codeblock / file / new / project / glut專案 / 專案名稱week15-1_gluPerspective
    選擇桌面後的下一步選擇桌面 / 2023graphicsa / freeglut 


        第一個程式(跑出的結果)(使用原先程式)

           改了這兩行 (原先程式碼內的第35行)   
         //glFrustum(-ar, ar, -1.0, 1.0, 2.0, 100.0);(版本1)

            glOrtho(-ar*3, ar*3, -1*3, 1*3, -100, +100);(版本2)



static void resize(int width, int height)
{
    const float ar = (float) width / (float) height;

    glViewport(0, 0, width, height);
    glMatrixMode(GL_PROJECTION);///week15_step02_02切換成投影矩陣
    glLoadIdentity();///week15_step02_02還原成單位矩陣
    ///glFrustum(-ar, ar, -1.0, 1.0, 2.0, 100.0);
    glOrtho(-ar*3, ar*3, -1*3, 1*3, -100, +100);

    glMatrixMode(GL_MODELVIEW);///week15_step02_02切換成Model View矩陣
    glLoadIdentity() ;///week15_step02_02還原成單位矩陣
}


static void resize(int width, int height)
{
    const float ar = (float) width / (float) height;

    glViewport(0, 0, width, height);
    glMatrixMode(GL_PROJECTION);///week15_step02_02切換成投影矩陣
    glLoadIdentity();///week15_step02_02還原成單位矩陣
    ///glFrustum(-ar, ar, -1.0, 1.0, 2.0, 100.0);
    ///glOrtho(-ar*3, ar*3, -1*3, 1*3, -100, +100);
    gluPerspective(60,ar,0.01,1000);
    ///week15_step02_02 角度, 比例,近的,遠的

    glMatrixMode(GL_MODELVIEW);///week15_step02_02切換成Model View矩陣
    glLoadIdentity() ;///week15_step02_02還原成單位矩陣
}



    第二個程式(版本1)

///week15-2_glutLookAt
#include <GL/glut.h>
void display()
{
    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
    glutSolidTeapot(0.3);
    glutSwapBuffers();
}
void reshape(int w, int h)
{
    glViewport(0,0,w,h);///視窗內會看到的2D範圍,圖案跟著視窗放大縮小
    float ar= w / (float)h;///aspect ratio長寬比
    glMatrixMode(GL_PROJECTION);///先切換到projection矩陣
    glLoadIdentity();///矩陣清空,成為單位矩陣(最一開始的矩陣)
    gluPerspective(60,ar,0.01,1000);///現在一片空白,因為我們現在在茶壺裡

    glMatrixMode(GL_MODELVIEW);///做好後馬上切回到model view矩陣
    glLoadIdentity();///矩陣清空,成為單位矩陣(最一開始的矩陣)
    gluLookAt(0,0,1,  0,0,0,  0,1,0);
    ///在0,0,1 看著茶壺0,0,0, up是0,1,0

    glutPostRedisplay();
}
int main(int argc, char** argv)
{
    glutInit(&argc,argv);
    glutInitDisplayMode(GLUT_DOUBLE|GLUT_DEPTH);
    glutCreateWindow("week15");

    glutDisplayFunc(display);
    glutReshapeFunc(reshape);

    glutMainLoop();
}


    第二個程式(版本2)(增加motion函式,隨著mouse去改變攝影機的位置)

///week15-2_glutLookAt
#include <GL/glut.h>
void display()
{
    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
    glutSolidTeapot(0.3);
    glutSwapBuffers();
}
void reshape(int w, int h)
{
    glViewport(0,0,w,h);///視窗內會看到的2D範圍,圖案跟著視窗放大縮小
    float ar= w / (float)h;///aspect ratio長寬比
    glMatrixMode(GL_PROJECTION);///先切換到projection矩陣
    glLoadIdentity();///矩陣清空,成為單位矩陣(最一開始的矩陣)
    gluPerspective(60,ar,0.01,1000);///現在一片空白,因為我們現在在茶壺裡

    glMatrixMode(GL_MODELVIEW);///做好後馬上切回到model view矩陣
    glLoadIdentity();///矩陣清空,成為單位矩陣(最一開始的矩陣)
    gluLookAt(0,0,1,  0,0,0,  0,1,0);
    ///在0,0,1 看著茶壺0,0,0, up是0,1,0

    glutPostRedisplay();
}
float eyeX = 0,eyeY = 0;
void motion(int x, int y)
{
    eyeX = (x-150.0)/150.0;
    eyeY = (150.0-y)/150.0;
    glMatrixMode(GL_MODELVIEW);///做好後馬上切回到model view矩陣
    glLoadIdentity();///矩陣清空,成為單位矩陣(最一開始的矩陣)
    gluLookAt(eyeX,eyeY,1,  0,0,0,  0,1,0);
    glutPostRedisplay();
}
int main(int argc, char** argv)
{
    glutInit(&argc,argv);
    glutInitDisplayMode(GLUT_DOUBLE|GLUT_DEPTH);
    glutCreateWindow("week15");

    glutMotionFunc(motion);
    glutDisplayFunc(display);
    glutReshapeFunc(reshape);

    glutMainLoop();
}

我用滑鼠將視角從右上方來看茶壺(也可以從左上,中上來看)

    第三個程式(開啟final project 裡頭的.cbp檔案)

///要用keyboard mouse來控制茶壺,可存檔,可自己動
///int angle[20];angle[0] angle[1]...用它們來旋轉
#include <stdio.h>
#include <GL/glut.h>
#include "glm.h"
GLMmodel * head =NULL;///week13 step02-1
GLMmodel * body =NULL;
GLMmodel * uparmR =NULL;
GLMmodel * lowarmR =NULL;
int show[4]={1,1,1,1};///week14_step03-1
int ID=3;///0:頭 1:身體 2:上手臂 3:下手臂///week14_step03-1
void keyboard(unsigned char key,int x ,int y)
{
    if(key=='0') ID = 0;///week14_step02-2
    if(key=='1') ID = 1;///week14_step02-2
    if(key=='2') ID = 2;///week14_step02-2
    if(key=='3') ID = 3;///week14_step02-2
    ///if(key=='0') show[0] = !show[0];///!是將1變0,0變1
    ///if(key=='1') show[1] = !show[1];
    ///if(key=='2') show[2] = !show[2];
    ///if(key=='3') show[3] = !show[3];
    glutPostRedisplay();
}///將原本的keyboard函式先註解掉
FILE * fout = NULL;///一開始,檔案沒有開 NULL
FILE * fin = NULL;///要讀檔用的指標,一開始也是NULL
float teapotX=0,teapotY=0;
///float angle=0, angle2=0, angle3=0;
float angle[20]={};///week15_step03_1 
void display()
{
    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
    glPushMatrix();
        glScalef(0.2, 0.2, 0.2);
        if(body==NULL)
        {
            head=glmReadOBJ("model/head.obj");
            body=glmReadOBJ("model/body.obj");
            uparmR=glmReadOBJ("model/uparmR.obj");
            lowarmR=glmReadOBJ("model/lowarmR.obj");
            ///glmUnitize(body);///這之後還會更改
        }
        if(ID==0) glColor3f(1,0,0);///選定的,紅色
        else glColor3f(1,1,1);///沒選定,白色
        if(show[0]) glmDraw(head,GLM_MATERIAL);

        if(ID==1) glColor3f(1,0,0);///選定的,紅色
        else glColor3f(1,1,1);///沒選定,白色
        if(show[1]) glmDraw(body,GLM_MATERIAL);
        glPushMatrix();
            glTranslatef(-1.426666, +0.320000, 0);///week14_step03-1
            glRotatef(angle[2], 0, 0, 1);///week15_step03_1改用陣列
            ///glTranslatef(teapotX, teapotY, 0);///week14_step03-1
            glTranslatef(1.426666, -0.320000, 0);///week14_step03-1

            if(ID==2) glColor3f(1,0,0);///選定的,紅色
            else glColor3f(1,1,1);///沒選定,白色
            if(show[2]) glmDraw(uparmR,GLM_MATERIAL);
            glPushMatrix();
                glTranslatef(-1.939999, +0.186667, 0);///week14_step03-1
                glRotatef(angle[3], 0, 0, 1);///week15_step03_1改用陣列
                //glTranslatef(teapotX, teapotY, 0);///week14_step03-1
                glTranslatef(1.939999, -0.186667, 0);///week14_step03-1

            if(ID==3) glColor3f(1,0,0);///選定的,紅色
            else glColor3f(1,1,1);///沒選定,白色
            if(show[3]) glmDraw(lowarmR,GLM_MATERIAL);
            glPopMatrix();
        glPopMatrix();
    glPopMatrix();
    glColor3f(0,1,0);///week14_step03-1
    glutSolidTeapot(0.02);///week14_step03-1
    glutSwapBuffers();
}
int oldX=0, oldY=0;
void motion(int x, int y)
{
    teapotX += (x - oldX)/150.0;
    teapotY -= (y - oldY)/150.0;
    angle[ID]+=(x-oldX);///week15_step03_1
    ///angle= x;
    oldX = x;
    oldY = y;
    printf("glTranslatef(%f, %f, 0);\n",teapotX, teapotY);
    glutPostRedisplay();
}
void mouse(int button, int state, int x, int y)
{
    if(state==GLUT_DOWN)
    {
        oldX = x;///teapotX = (x-150)/150.0;
        oldY = y;///teapotY = (150-y)/150.0;
        ///angle = x;///week15_step03_1
        ///if(fout==NULL) fout=fopen("file4.txt","w");///沒開檔就開檔
        ///fprintf(fout,"%f %f\n",teapotX, teapotY);///要再存座標
    }
    display();
}
//void keyboard(unsigned char key, int x, int y)
//{
//    if(fin==NULL)///如果檔案還沒fopen(),就開它
//    {
//        fclose(fout);///要關掉前面mouse開的fout指標
//        fin = fopen("file4.txt","r");///沒開檔就開檔
//    }
//    fscanf(fin, "%f %f",&teapotX, &teapotY);///讀檔
//    display();
//}
 int main(int argc, char *argv[])
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_DEPTH);
    glutCreateWindow("week13");

    glutDisplayFunc(display);
    glutMouseFunc(mouse);
    glutMotionFunc(motion);
    glutKeyboardFunc(keyboard);///keyboard要開檔,讀檔

    glutMainLoop();
}

    第三個程式版本2(可開檔讀檔)

///要用keyboard mouse來控制茶壺,可存檔,可自己動
///int angle[20];angle[0] angle[1]...用它們來旋轉
#include <stdio.h>
#include <GL/glut.h>
#include "glm.h"
GLMmodel * head =NULL;///week13 step02-1
GLMmodel * body =NULL;
GLMmodel * uparmR =NULL;
GLMmodel * lowarmR =NULL;
int show[4]={1,1,1,1};///week14_step03-1
int ID=3;///0:頭 1:身體 2:上手臂 3:下手臂///week14_step03-1
FILE * fout = NULL;///一開始,檔案沒有開 NULL
FILE * fin = NULL;///要讀檔用的指標,一開始也是NULL
float teapotX=0,teapotY=0;
///float angle=0, angle2=0, angle3=0;
float angle[20]={};///week15_step03_1
void keyboard(unsigned char key,int x ,int y)
{
    if(key=='0') ID = 0;///week14_step02-2
    if(key=='1') ID = 1;///week14_step02-2
    if(key=='2') ID = 2;///week14_step02-2
    if(key=='3') ID = 3;///week14_step02-2
    if(key=='s')
    {
        if (fout==NULL) fout=fopen("motion.txt","w");
        for(int i=0;i<20;i++)///week15_step03_2
        {
            fprintf(fout,"%.2f ",angle[i]);///week15_step03_2
        }
        fprintf(fout,"\n");
    }
    else if(key=='r')
    {
        if (fin==NULL) fin=fopen("motion.txt","r");
        for(int i=0;i<20;i++)///week15_step03_2
        {
            fscanf(fin,"%f",&angle[i]);///week15_step03_2
        }
        glutPostRedisplay();
    }
    ///if(key=='0') show[0] = !show[0];///!是將1變0,0變1
    ///if(key=='1') show[1] = !show[1];
    ///if(key=='2') show[2] = !show[2];
    ///if(key=='3') show[3] = !show[3];
    glutPostRedisplay();
}///將原本的keyboard函式先註解掉

void display()
{
    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
    glPushMatrix();
        glScalef(0.2, 0.2, 0.2);
        if(body==NULL)
        {
            head=glmReadOBJ("model/head.obj");
            body=glmReadOBJ("model/body.obj");
            uparmR=glmReadOBJ("model/uparmR.obj");
            lowarmR=glmReadOBJ("model/lowarmR.obj");
            ///glmUnitize(body);///這之後還會更改
        }
        if(ID==0) glColor3f(1,0,0);///選定的,紅色
        else glColor3f(1,1,1);///沒選定,白色
        if(show[0]) glmDraw(head,GLM_MATERIAL);

        if(ID==1) glColor3f(1,0,0);///選定的,紅色
        else glColor3f(1,1,1);///沒選定,白色
        if(show[1]) glmDraw(body,GLM_MATERIAL);
        glPushMatrix();
            glTranslatef(-1.426666, +0.320000, 0);///week14_step03-1
            glRotatef(angle[2], 0, 0, 1);///week15_step03_1改用陣列
            ///glTranslatef(teapotX, teapotY, 0);///week14_step03-1
            glTranslatef(1.426666, -0.320000, 0);///week14_step03-1

            if(ID==2) glColor3f(1,0,0);///選定的,紅色
            else glColor3f(1,1,1);///沒選定,白色
            if(show[2]) glmDraw(uparmR,GLM_MATERIAL);
            glPushMatrix();
                glTranslatef(-1.939999, +0.186667, 0);///week14_step03-1
                glRotatef(angle[3], 0, 0, 1);///week15_step03_1改用陣列
                //glTranslatef(teapotX, teapotY, 0);///week14_step03-1
                glTranslatef(1.939999, -0.186667, 0);///week14_step03-1

            if(ID==3) glColor3f(1,0,0);///選定的,紅色
            else glColor3f(1,1,1);///沒選定,白色
            if(show[3]) glmDraw(lowarmR,GLM_MATERIAL);
            glPopMatrix();
        glPopMatrix();
    glPopMatrix();
    glColor3f(0,1,0);///week14_step03-1
    glutSolidTeapot(0.02);///week14_step03-1
    glutSwapBuffers();
}
int oldX=0, oldY=0;
void motion(int x, int y)
{
    teapotX += (x - oldX)/150.0;
    teapotY -= (y - oldY)/150.0;
    angle[ID]+=(x-oldX);///week15_step03_1
    ///angle= x;
    oldX = x;
    oldY = y;
    printf("glTranslatef(%f, %f, 0);\n",teapotX, teapotY);
    glutPostRedisplay();
}
void mouse(int button, int state, int x, int y)
{
    if(state==GLUT_DOWN)
    {
        oldX = x;///teapotX = (x-150)/150.0;
        oldY = y;///teapotY = (150-y)/150.0;
        ///angle = x;///week15_step03_1
        ///if(fout==NULL) fout=fopen("file4.txt","w");///沒開檔就開檔
        ///fprintf(fout,"%f %f\n",teapotX, teapotY);///要再存座標
    }
    display();
}
//void keyboard(unsigned char key, int x, int y)
//{
//    if(fin==NULL)///如果檔案還沒fopen(),就開它
//    {
//        fclose(fout);///要關掉前面mouse開的fout指標
//        fin = fopen("file4.txt","r");///沒開檔就開檔
//    }
//    fscanf(fin, "%f %f",&teapotX, &teapotY);///讀檔
//    display();
//}
 int main(int argc, char *argv[])
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_DEPTH);
    glutCreateWindow("week13");

    glutDisplayFunc(display);
    glutMouseFunc(mouse);
    glutMotionFunc(motion);
    glutKeyboardFunc(keyboard);///keyboard要開檔,讀檔

    glutMainLoop();
}

將宣告移到上面


按下s鍵 可讀取模型移動座標 存在motion.txt裏頭


按下r鍵 可播放模型移動座標 讀取motion.txt




















沒有留言:

張貼留言