上週的最後一部分沒能在時間內寫完,內容是有關如何在茶壺放上貼圖。
參考處:
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); ///這個是當沒有執行任何動作時會一直跑的程式。也就是說
"清空畫面>生成圓球>放上貼圖材質>旋轉)"這個程序會一直執行。




沒有留言:
張貼留言