2022年4月25日 星期一

學習筆記 week10

上週的最後一部分沒能在時間內寫完,內容是有關如何在茶壺放上貼圖。
參考處:
https://2022graphicsb.blogspot.com/2022/04/angry-week09.html

#include <opencv/highgui.h> ///使用 OpenCV 2.1 比較簡單, 只要用 High GUI 即可
#include <opencv/cv.h>
#include <GL/glut.h>
int myTexture(char * filename)
{
    IplImage * img = cvLoadImage(filename); ///OpenCV讀圖
    cvCvtColor(img,img, CV_BGR2RGB); ///OpenCV轉色彩 (需要cv.h)
    glEnable(GL_TEXTURE_2D); ///1. 開啟貼圖功能
    GLuint id; ///準備一個 unsigned int 整數, 叫 貼圖ID
    glGenTextures(1, &id); /// 產生Generate 貼圖ID
    glBindTexture(GL_TEXTURE_2D, id); ///綁定bind 貼圖ID
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); /// 貼圖參數, 超過包裝的範圖T, 就重覆貼圖
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); /// 貼圖參數, 超過包裝的範圖S, 就重覆貼圖
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); /// 貼圖參數, 放大時的內插, 用最近點
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); /// 貼圖參數, 縮小時的內插, 用最近點
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, img->width, img->height, 0, GL_RGB, GL_UNSIGNED_BYTE, img->imageData);
return id;
}

void display(void)
{

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glColor3d(1,1,1);

    glutSolidTeapot(0.3);

    glutSwapBuffers();
}


int main(int argc, char *argv[])
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
    glutCreateWindow("week10 Texture");
    glutDisplayFunc(display);

    myTexture("download.png");

    glutMainLoop();

    return EXIT_SUCCESS;
}


此外,在glutSolidTeapot(0.3);的下面加入這幾行,就可以讓圖片放在茶壺的上面。

glBegin(GL_POLYGON);

glTexCoord2f(0,1);glVertex2f(0,-1);
glTexCoord2f(1,1);glVertex2f(+1,-1);
glTexCoord2f(1,0);glVertex2f(+1,+1);
glTexCoord2f(0,0);glVertex2f(0,+1);

glEnd();

接下來我們來試試看圓球體。這次的程式碼會比較不一樣。

#include <opencv/highgui.h>
#include <opencv/cv.h>
#include <GL/glut.h>
GLUquadric * sphere = NULL;

int myTexture(char * filename)
{
    IplImage * img = cvLoadImage(filename);
    cvCvtColor(img,img, CV_BGR2RGB);
    glEnable(GL_TEXTURE_2D);
    GLuint id;
    glGenTextures(1, &id);
    glBindTexture(GL_TEXTURE_2D, id);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, img->width, img->height, 0, GL_RGB, GL_UNSIGNED_BYTE, img->imageData);
return id;
}

void display(void)
{

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glColor3d(1,1,1);

    glutSolidTeapot(0.3);

    gluQuadricTexture(sphere,1);
    gluSphere(sphere,1,30,30);

    glutSwapBuffers();
}


int main(int argc, char *argv[])
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
    glutCreateWindow("week10 Texture");
    glutDisplayFunc(display);

    myTexture("earth1.png");
    sphere=gluNewQuadric();

    glutMainLoop();

    return EXIT_SUCCESS;
}

重點為這四行:
GLUquadric * sphere = NULL;
gluQuadricTexture(sphere,1);
gluSphere(sphere,1,30,30);
sphere=gluNewQuadric();

earth1.png的圖片如果不是長方形,結果可能會怪怪的。

如果想要選轉這顆地球的話,只需要在宣告圓球時將它旋轉就可以了。
glPushMatrix();
        glRotatef(90,1,0,0);
        gluQuadricTexture(sphere,1);
        gluSphere(sphere,1,30,30);
glPopMatrix();

另外,為了避免破圖,必須在main的地方加上glEnable(GL_DEPTH_TEST);。
剛剛那是靜止的地球,不如我們用angle這個變數來讓地球旋轉?
在void display(void)前宣告float angle=0;

讓每次地球"朝向"的角度不一樣:
glRotatef(90,1,0,0);是為了貼圖材質能夠順利貼在上面

glPushMatrix();
        glRotatef(angle,0,-1,0);
        glRotatef(90,1,0,0);
        gluQuadricTexture(sphere,1);
        gluSphere(sphere,1,30,30);
glPopMatrix();
glutSwapBuffers();
angle+=0.2; ///注意: 這個數值會因每個人的電腦性能而不同

最後,在glutDisplayFunc(display);的後面加上glutIdleFunc(display); ///這個是當沒有執行任何動作時會一直跑的程式。也就是說
"清空畫面>生成圓球>放上貼圖材質>旋轉)"這個程序會一直執行。


沒有留言:

張貼留言