實(shí) 驗(yàn) 報(bào) 告
一、實(shí)驗(yàn)?zāi)康?/strong>
- 掌握三維圖形的顯示原理和方法,掌握三維觀察的原理和方法;
- 掌握OpenGL中矩陣堆棧函數(shù)的使用,會(huì)使用堆棧函數(shù)進(jìn)行復(fù)雜場(chǎng)景的組裝。
- 掌握OpenGL中三維觀察變換常用的函數(shù)的使用方法,了解三維模型的貼圖方法;
- 掌握自由曲線的生成方法,熟練掌握B樣條曲線的生成原理、方法和特點(diǎn)。
二、實(shí)驗(yàn)內(nèi)容與實(shí)驗(yàn)步驟
太陽系:
使用線框球體繪制函數(shù)實(shí)現(xiàn)球體繪制。當(dāng)按下鍵盤“D”或“d”時(shí),行星將實(shí)現(xiàn)自轉(zhuǎn);按下鍵盤“Y”或“y”時(shí),行星將繞太陽公轉(zhuǎn)。實(shí)現(xiàn)以下兩個(gè)內(nèi)容:
(1)給行星加上衛(wèi)星;
(2)實(shí)現(xiàn)自動(dòng)旋轉(zhuǎn)功能,即衛(wèi)星繞行星自動(dòng)旋轉(zhuǎn)、行星自動(dòng)自傳同時(shí)繞太陽公轉(zhuǎn)。
(3)(選做)程序例子2是一個(gè)粘貼了紋理圖像的自轉(zhuǎn)的地球的例子(位圖文件見實(shí)驗(yàn)任務(wù)附件ear.bmp),理解其中的紋理圖像裝載和使用方法,自制貼圖圖片,仿照這個(gè)程序編寫九大行星運(yùn)行的3D動(dòng)畫。
B樣條曲線繪制:
在OpenGL 中實(shí)現(xiàn)動(dòng)態(tài)輸入任意多個(gè)控制點(diǎn)(控制點(diǎn)個(gè)數(shù)大于等于4),采用三次參數(shù)樣條曲線,按照分段拼接的方式生成逼近任意多個(gè)控制點(diǎn)組成的多邊形的光滑曲線。并按照給定的控制點(diǎn)個(gè)數(shù)繪制B樣條曲線。
其基函數(shù)遞歸公式為:
取,
將上式帶入B樣條定義式得:
其中一段3次參數(shù)B樣條曲線由四個(gè)控制點(diǎn)P0、P1、P2和P3生成,調(diào)和矩陣為中間的4*4矩陣,在編寫程序時(shí)盡量考慮減少無用的運(yùn)算,盡量提高運(yùn)算的效率。
要求生成曲線的過程按照下面的交互方式輸入:
(1)在控制點(diǎn)輸入狀態(tài)下,點(diǎn)擊左鍵,增加一個(gè)控制點(diǎn),并繪制上一個(gè)控制點(diǎn)到當(dāng)前控制點(diǎn)的連線。
(2)點(diǎn)擊左鍵增加一個(gè)控制點(diǎn),點(diǎn)擊右鍵按照已選擇的控制點(diǎn)生成B樣條曲線。
(3)設(shè)置一種控制鍵的處理可以清除屏幕上的圖形,重新進(jìn)行控制點(diǎn)輸入狀態(tài)。
三、實(shí)驗(yàn)環(huán)境
- 操作系統(tǒng):macOS Big Sur Version 11.6
- 調(diào)試軟件:Xcode Version 13.0
- 上機(jī)地點(diǎn):信息樓Bxxx
- 機(jī)器臺(tái)號(hào):xx
四、實(shí)驗(yàn)過程與分析
地球公轉(zhuǎn)&自轉(zhuǎn):
首先單實(shí)現(xiàn)地球繞太陽的公轉(zhuǎn)和自轉(zhuǎn)。使用線框球體繪制函數(shù)實(shí)現(xiàn)球體繪制。當(dāng)按下鍵盤“D”或“d”時(shí),行星將實(shí)現(xiàn)自轉(zhuǎn);按下鍵盤“Y”或“y”時(shí),行星將繞太陽公轉(zhuǎn)。
太陽系:
坐標(biāo)變換過程:
????????太陽:不變,在中心即可。
??????? 地球:用循環(huán)改變SolarAngle的值,調(diào)用glRotatef()函數(shù)實(shí)現(xiàn)公轉(zhuǎn);
????????????????用循環(huán)改變OwnAxisAngle的值,調(diào)用glRotatef()實(shí)現(xiàn)自轉(zhuǎn);
????????????????調(diào)用glTranslatef()函數(shù)將其平移至公轉(zhuǎn)軌道,并隨時(shí)間在軌道上改變位置。
??????? 月球:類似地球的坐標(biāo)變換過程。
函數(shù)作用:
?
以上函數(shù)的功能分別是:加載貼圖;控制臺(tái)顯示提示;繪制太陽;初始化;繪制圖形;調(diào)整圖形;鍵盤與鼠標(biāo)的事件;主函數(shù)。
具體實(shí)現(xiàn)見代碼中的注釋:
load_texture()函數(shù):
int load_texture(const char* file_name, int width, int height, int depth, GLenum colour_type, GLenum filter_type)
{
GLubyte* raw_bitmap;
FILE* file;
//if ((file = fopen_s(file_name, "rb")) == NULL)
if ((file = fopen(file_name, "rb")) == NULL)
{
return 1;
}
raw_bitmap = (GLubyte*)malloc(width * height * depth * (sizeof(GLubyte)));
if (raw_bitmap == NULL)
{
fclose(file);
return 2;
}
fread(raw_bitmap, width * height * depth, 1, file);
fclose(file);
// 設(shè)置過濾類型
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter_type);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter_type);
// 設(shè)置紋理環(huán)境
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
gluBuild2DMipmaps(GL_TEXTURE_2D, 3, width, height, colour_type,
GL_UNSIGNED_BYTE, raw_bitmap);
free(raw_bitmap);
glDisable(GL_TEXTURE_2D);
return 0;
}
Load_texture()函數(shù):
void LoadTextures(GLuint texture_id, int MaxNrOfTextures)
{
// 第一種紋理
glPixelStorei(GL_UNPACK_ALIGNMENT, 1); //控制所讀取數(shù)據(jù)的對(duì)齊方式
glGenTextures(MaxNrOfTextures, &texture_id); // 生成紋理的數(shù)量-MaxNrOfTextures 存儲(chǔ)紋理索引-texture_id
glBindTexture(GL_TEXTURE_2D, 1); //將一個(gè)命名的紋理綁定到一個(gè)紋理目標(biāo)上
if (load_texture("/Users/kqp12_27/Desktop/Xcode-OpenGL/Mouse copy 12/Mouse/ear.bmp", 512, 128, 3, GL_BGR_EXT, GL_NEAREST)) //讀取此bmp文件
{
exit(1);
}
// 第二種紋理
glPixelStorei(GL_UNPACK_ALIGNMENT, 2);
glGenTextures(MaxNrOfTextures, &texture_id);
glBindTexture(GL_TEXTURE_2D, 2);
if (load_texture("/Users/kqp12_27/Desktop/一些課??/計(jì)圖實(shí)驗(yàn)/實(shí)驗(yàn)三/太陽系/moon copy.bmp",88,63, 3, GL_BGR_EXT, GL_NEAREST))
{
exit(1);
}
// 第三種紋理
glPixelStorei(GL_UNPACK_ALIGNMENT, 3);
glGenTextures(MaxNrOfTextures, &texture_id);
glBindTexture(GL_TEXTURE_2D, 3);
if (load_texture("/Users/kqp12_27/Desktop/一些課??/計(jì)圖實(shí)驗(yàn)/實(shí)驗(yàn)三/太陽系/sun.bmp",500, 400, 3, GL_BGR_EXT, GL_NEAREST))
{
exit(1);
}
}
init()函數(shù):
void init(void)
{
//地球
Planet1.size = 0.4f;
Planet1.sections = 16.0f;
Planet1.posX = 0.0f;
Planet1.posY = 0.0f;
Planet1.posZ = 1.4f;
Planet1.OwnAxisAngle = 0.0f;
Planet1.SolarAngle = 60.0f;
Planet1.TextureID = 1;
//月球
Planet2.size = 0.2f;
Planet2.sections = 16.0f;
Planet2.posX = 0.0f;
Planet2.posY = 0.0f;
Planet2.posZ = 1.4f;
Planet2.OwnAxisAngle = 0.0f;
Planet2.SolarAngle = 60.0f;
Planet2.TextureID = 2;
glClearColor(0.0, 0.0, 0.0, 0.0);
glShadeModel(GL_FLAT);
LoadTextures(texture_id1, 1);
glEnable(GL_TEXTURE_2D);
glClearDepth(1.0f); // 設(shè)置深度緩存
glDepthFunc(GL_LEQUAL); // 選擇深度測(cè)試方式
glEnable(GL_DEPTH_TEST); // 開啟深度測(cè)試
glShadeModel(GL_SMOOTH); // 陰暗處理采用平滑方式
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // 最精細(xì)的透視計(jì)算
return;
}
display()函數(shù):
void display(void)
{
// 地球公轉(zhuǎn)
Planet1.SolarAngle += 1.0f * ROTATION_SPEED;
if (Planet1.SolarAngle >= 360) { Planet1.SolarAngle -= 360; }
// 地球自轉(zhuǎn)
Planet1.OwnAxisAngle += 0.5f;
if (Planet1.OwnAxisAngle >= 360) { Planet1.OwnAxisAngle -= 360; }
// 月球公轉(zhuǎn)
Planet2.SolarAngle += 7.0f * ROTATION_SPEED;
if (Planet2.SolarAngle >= 360) { Planet2.SolarAngle -= 360; }
// 月球自轉(zhuǎn)
Planet2.OwnAxisAngle += 1.0f;
if (Planet2.OwnAxisAngle >= 360) { Planet2.OwnAxisAngle -= 360; }
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // 清除顏色和深度緩存
glColor3f(1.0, 0.0, 0.0);
glColor3f(1.0, 1.0, 1.0);
glColor3f(0.7f, 0.7f, 0.7f);
glBegin(GL_LINE_LOOP);
// 繪制軌道
for (int l = 0; l < 360; l++)
{
glVertex3f((float)cos(l * ((float)3.14159 / (float)180)) * Planet1.posZ, 0.0f, (float)sin(l * ((float)3.14159 / (float)180)) * Planet1.posZ);
}
glEnd();
glPushMatrix();
// 地球
// 坐標(biāo)變換,使地球在公轉(zhuǎn)軌道上轉(zhuǎn)
glRotatef(Planet1.SolarAngle, 0, -1, 0); //旋轉(zhuǎn)
glTranslatef(Planet1.posX, Planet1.posY, Planet1.posZ); //平移
glRotatef(Planet1.OwnAxisAngle, 0, -1, 0);
glBindTexture(GL_TEXTURE_2D, 1); //設(shè)置紋理
GLUquadricObj* q = gluNewQuadric();
gluQuadricDrawStyle(q, GLU_FILL);
gluQuadricNormals(q, GLU_SMOOTH);
gluQuadricTexture(q, GL_TRUE);
gluSphere(q, Planet1.size, 50, 40); //畫球
gluDeleteQuadric(q);
glBindTexture(GL_TEXTURE_2D, 0);
// 月球
glRotatef(Planet2.SolarAngle, 0, 1, 0);
glTranslatef(0.5*Planet2.posX, 0.5*Planet2.posY, 0.5*Planet2.posZ);
glRotatef(Planet2.OwnAxisAngle, 0, -1, 0);
glRotatef(90.0, 1.0, 0.0, 0.0);
glBindTexture(GL_TEXTURE_2D, 2);
GLUquadricObj* q2 = gluNewQuadric();
gluQuadricDrawStyle(q2, GLU_FILL);
gluQuadricNormals(q2, GLU_SMOOTH);
gluQuadricTexture(q2, GL_TRUE);
gluSphere(q2, Planet2.size, 50, 40);
gluDeleteQuadric(q2);
glPopMatrix();
glLoadIdentity();
draw_sun(); //繪制太陽
gluLookAt(R * cos(b / 180 * 3.1415926) * sin(a / 180 * 3.1415926), R * sin(b / 180 * 3.1415926), R * cos(b / 180 * 3.1415926) * cos(a / 180 * 3.1415926), 0.0, 0.0, 0.0, cos((90 - b) / 180 * 3.1415926) * sin((a + 180) / 180 * 3.1415926), sin((90 - b) / 180 * 3.1415926), cos((90 - b) / 180 * 3.1415926) * cos((a + 180) / 180 * 3.1415926)); //觀察角度
glutSwapBuffers();
}
調(diào)試:
問題一:開始時(shí)兩個(gè)星球都繞著太陽轉(zhuǎn)。
解決辦法:在第一次變換后不立刻進(jìn)行出棧操作,而是在第一次變換的基礎(chǔ)上再添加一次變換,這樣可以讓月球繞地球轉(zhuǎn)。
問題二:初始化時(shí)兩個(gè)星球的紋理一樣,沒法分別設(shè)置紋理。
解決辦法:通過對(duì)glBindTexture函數(shù)的添加操作,添加了紋理對(duì)象,解決了問題。
B樣條曲線繪制:
流程圖:
主要思想:
動(dòng)態(tài)輸入任意多個(gè)控制點(diǎn)(控制點(diǎn)個(gè)數(shù)大于等于4),采用三次參數(shù)樣條曲線,按照分段拼接的方式生成逼近任意多個(gè)控制點(diǎn)組成的多邊形的光滑曲線。并按照給定的控制點(diǎn)個(gè)數(shù)繪制B樣條曲線。
調(diào)試:
問題一:點(diǎn)擊鼠標(biāo)右鍵時(shí)偶爾會(huì)卡住。
解決辦法:鼠標(biāo)事件里出現(xiàn)了問題,修改后可以正常運(yùn)行了。
代碼:
void Bspline(Point a, Point b, Point c, Point d) {
glPointSize(2);
glColor3d(0, 0, 0);
glBegin(GL_LINE_STRIP);
for (int i = 0; i <= 1000; i++)
{
double t = 0.001 * i;
double r[4];
r[0] = -t * t * t + 3 * t * t - 3 * t + 1;
r[1] = 3 * t * t * t - 6 * t * t + 4;
r[2] = -3 * t * t * t + 3 * t * t + 3 * t + 1;
r[3] = t * t * t;
double x = 0, y = 0;
x += r[0] * a.x + r[1] * b.x + r[2] * c.x + r[3] * d.x;
y += r[0] * a.y +r[1] * b.y + r[2] * c.y + r[3] * d.y;
x /= 6.0;
y /= 6.0;
glVertex2d(x,y);
}
glEnd();
}
void Display()
{
glClear(GL_COLOR_BUFFER_BIT);
//畫點(diǎn)
glPointSize(7);
glColor3d(0, 0, 1);
glBegin(GL_POINTS);
for (int i = 0; i < p.size(); i++)
glVertex2d(p[i].x, p[i].y);
glEnd();
//畫線
glLineWidth(2);
glColor3d(1, 0, 1);
glBegin(GL_LINE_STRIP);
for (int i = 0; i < p.size(); i++)
glVertex2d(p[i].x, p[i].y);
glEnd();
if (sta == 1 && p.size() >= 3)
for (int i = 0; i < p.size() - 3; i++)
Bspline(p[i], p[i + 1], p[i + 2], p[i + 3]);
glFlush();
}
void Mouse(int button, int state, int x, int y)
{
if (sta == 0 && button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
{
Point t;
t.x = x; t.y = y;
p.push_back(t);
glutPostRedisplay();
}
if (sta == 0 && button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN) {
sta = 1;
glutPostRedisplay();
}
}
void Keyboard(unsigned char key, int x, int y)
{
if (key == 'd')
{
glClearColor(1, 1, 1, 0);
glClear(GL_COLOR_BUFFER_BIT);
p.clear();
sta = 0;
glutPostRedisplay();
}
}
五、 實(shí)驗(yàn)結(jié)果總結(jié)
地球公轉(zhuǎn)&自轉(zhuǎn):(視頻見附件地球.mov)
?太陽系:(視頻見附件太陽系.mov)
?太陽系(選):(視頻見附件太陽系(選).mov)【這其實(shí)是我從git上偷了一個(gè) 555】
B樣條曲線:
2個(gè)控制點(diǎn)重合:
??????? 效果:曲線在該點(diǎn)附近與兩點(diǎn)間形成的直線基本重合,在該點(diǎn)則有一定的距離和弧度。
(只有一個(gè)位置是2個(gè)控制點(diǎn)重合)
應(yīng)用:
- 用于繪制基本重合于連接相鄰兩點(diǎn)線段,但在拐點(diǎn)處的曲率于控制點(diǎn)的位置有關(guān)的線段;
- 用于在局部繪制出類似“圓角”的形狀。
3個(gè)控制點(diǎn)重合:
??????? 效果:曲線在該點(diǎn)附近與兩點(diǎn)間形成的直線基本重合,曲線也與該點(diǎn)重合。
(只有一個(gè)位置是3個(gè)控制點(diǎn)重合)
應(yīng)用:
- 繪制與直接連接的線段相同的線段;
- 在局部繪制類似“尖角”的形狀。
(所有位置都是3個(gè)控制點(diǎn)重合)
六、 附錄
- 其他解決方案/設(shè)想:無。
-
參考資料:
- 教材、PPT。
- B-Spline樣條曲線及其性質(zhì)_BRAND-NEO的博客-CSDN博客_準(zhǔn)均勻b樣條曲線
- OpenGL學(xué)習(xí)筆記 之三 (簡(jiǎn)單示例 太陽月亮地球)_weixin_38167262的博客-CSDN博客
- 用上周的作業(yè):畫一個(gè)太陽、地球、月亮的運(yùn)動(dòng)模型來剖析OpenGL中變換乃至整個(gè)繪制的秘密_Luo Xiao C的博客-CSDN博客
- 回答思考題
Q:在OpenGL中提供給了哪幾類函數(shù)能修改矩陣工作棧的數(shù)據(jù)?
A:Opengl中常用兩個(gè)變換堆棧,一個(gè)是glMatrixMode(GL_MODELVIEW),它一開始時(shí)候棧頂是一個(gè)單位矩陣,一般堆棧大小是32個(gè)矩陣。一個(gè)是glMatrixMode(GL_PROJECTION),正交或者透視投影,一開始時(shí)候沒有棧頂單位矩陣所以需要glLoadIdentity()單位矩陣到棧頂,投影堆棧大小一般是2個(gè),要2個(gè)目的是一個(gè)程序中既可以實(shí)現(xiàn)透視投影,也可以切換到正交投影(例如繪制文本)。 如果glPushMatrix()太多大于堆棧容量那么會(huì)報(bào)錯(cuò),如果glPopMatrix()小于等于一個(gè)那么也會(huì)報(bào)錯(cuò) 。glMatrixMode(GL_TEXTURE)是紋理堆棧,也有相應(yīng)的變換矩陣。
Q:OpenGL中提供了哪幾種二次曲面模型?怎樣調(diào)用使用?
A:圓面、扇形、圓柱、圓錐、球等。創(chuàng)建二次曲面聲明類型的指針GLUquadricObj*。利用上述指針,利用二次曲面模型的類,如gluCylinde(GLUquadric* quad, GLdouble base, GLdouble top,GLdouble height,GLint slices,,GLint stacks)圓柱,設(shè)置相應(yīng)的參數(shù)來創(chuàng)建該二次曲面的對(duì)象,設(shè)置二次曲面的繪制風(fēng)格,設(shè)置法線風(fēng)格,設(shè)置二次曲面的繪制方向,設(shè)置紋理,調(diào)用二次曲面的繪制函數(shù)。
Q:B樣條曲線對(duì)比Bezier曲線的算法有哪些好處?
A:B樣條方法是在保留Bezier方法的優(yōu)點(diǎn),同時(shí)克服其由于整體表示帶來不具有局部性質(zhì)的缺點(diǎn),及解決在描述復(fù)雜形狀時(shí)帶來的連接問題下提出來的,當(dāng)控制點(diǎn)個(gè)數(shù)多時(shí)控制多邊形對(duì)曲線的控制不會(huì)減弱;可以對(duì)曲線進(jìn)行局部修改。
完整代碼:
項(xiàng)目一:(太陽系)
#define GL_SILENCE_DEPRECATION
//include\gl
#include <stdlib.h>
#include <iostream>
#include <GLUT/glut.h>
#include <math.h>
#define ROTATION_SPEED 0.1
static int year = 0, day = 0;
GLuint texture_id1;
int start = 0;
int ori_x;
int ori_y;
struct Planet
{
float size, sections, posX, posY, posZ, SolarAngle, OwnAxisAngle;
int TextureID;
};
struct Planet Planet1;
struct Planet Planet2;
struct Planet Planet3;
float R = 8;
float a = 0;
float b = 0;
int load_texture(const char* file_name, int width, int height, int depth, GLenum colour_type, GLenum filter_type)
{
GLubyte* raw_bitmap;
FILE* file;
//if ((file = fopen_s(file_name, "rb")) == NULL)
if ((file = fopen(file_name, "rb")) == NULL)
{
return 1;
}
raw_bitmap = (GLubyte*)malloc(width * height * depth * (sizeof(GLubyte)));
if (raw_bitmap == NULL)
{
fclose(file);
return 2;
}
fread(raw_bitmap, width * height * depth, 1, file);
fclose(file);
// 設(shè)置過濾類型
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter_type);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter_type);
// 設(shè)置紋理環(huán)境
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
gluBuild2DMipmaps(GL_TEXTURE_2D, 3, width, height, colour_type,
GL_UNSIGNED_BYTE, raw_bitmap);
free(raw_bitmap);
glDisable(GL_TEXTURE_2D);
return 0;
}
void LoadTextures(GLuint texture_id, int MaxNrOfTextures)
{
// 第一種紋理
glPixelStorei(GL_UNPACK_ALIGNMENT, 1); //控制所讀取數(shù)據(jù)的對(duì)齊方式
glGenTextures(MaxNrOfTextures, &texture_id); // 生成紋理的數(shù)量-MaxNrOfTextures 存儲(chǔ)紋理索引-texture_id
glBindTexture(GL_TEXTURE_2D, 1); //將一個(gè)命名的紋理綁定到一個(gè)紋理目標(biāo)上
if (load_texture("/Users/kqp12_27/Desktop/Xcode-OpenGL/Mouse copy 12/Mouse/ear.bmp", 512, 128, 3, GL_BGR_EXT, GL_NEAREST)) //讀取此bmp文件
{
exit(1);
}
// 第二種紋理
glPixelStorei(GL_UNPACK_ALIGNMENT, 2);
glGenTextures(MaxNrOfTextures, &texture_id);
glBindTexture(GL_TEXTURE_2D, 2);
if (load_texture("/Users/kqp12_27/Desktop/一些課??/計(jì)圖實(shí)驗(yàn)/實(shí)驗(yàn)三/太陽系/moon copy.bmp",88,63, 3, GL_BGR_EXT, GL_NEAREST))
{
exit(1);
}
// 第三種紋理
glPixelStorei(GL_UNPACK_ALIGNMENT, 3);
glGenTextures(MaxNrOfTextures, &texture_id);
glBindTexture(GL_TEXTURE_2D, 3);
if (load_texture("/Users/kqp12_27/Desktop/一些課??/計(jì)圖實(shí)驗(yàn)/實(shí)驗(yàn)三/太陽系/sun.bmp",500, 400, 3, GL_BGR_EXT, GL_NEAREST))
{
exit(1);
}
}
void draw_sun(){
glBindTexture(GL_TEXTURE_2D, 3);
GLUquadricObj* q3 = gluNewQuadric();
gluQuadricDrawStyle(q3, GLU_FILL);
gluQuadricNormals(q3, GLU_SMOOTH);
gluQuadricTexture(q3, GL_TRUE);
gluSphere(q3, 0.1002, 50,40);
gluDeleteQuadric(q3);
}
void init(void)
{
//地球
Planet1.size = 0.4f;
Planet1.sections = 16.0f;
Planet1.posX = 0.0f;
Planet1.posY = 0.0f;
Planet1.posZ = 1.4f;
Planet1.OwnAxisAngle = 0.0f;
Planet1.SolarAngle = 60.0f;
Planet1.TextureID = 1;
//月球
Planet2.size = 0.2f;
Planet2.sections = 16.0f;
Planet2.posX = 0.0f;
Planet2.posY = 0.0f;
Planet2.posZ = 1.4f;
Planet2.OwnAxisAngle = 0.0f;
Planet2.SolarAngle = 60.0f;
Planet2.TextureID = 2;
glClearColor(0.0, 0.0, 0.0, 0.0);
glShadeModel(GL_FLAT);
LoadTextures(texture_id1, 1);
glEnable(GL_TEXTURE_2D);
glClearDepth(1.0f); // 設(shè)置深度緩存
glDepthFunc(GL_LEQUAL); // 選擇深度測(cè)試方式
glEnable(GL_DEPTH_TEST); // 開啟深度測(cè)試
glShadeModel(GL_SMOOTH); // 陰暗處理采用平滑方式
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // 最精細(xì)的透視計(jì)算
return;
}
void display(void)
{
// 地球公轉(zhuǎn)
Planet1.SolarAngle += 1.0f * ROTATION_SPEED;
if (Planet1.SolarAngle >= 360) { Planet1.SolarAngle -= 360; }
// 地球自轉(zhuǎn)
Planet1.OwnAxisAngle += 0.5f;
if (Planet1.OwnAxisAngle >= 360) { Planet1.OwnAxisAngle -= 360; }
// 月球公轉(zhuǎn)
Planet2.SolarAngle += 7.0f * ROTATION_SPEED;
if (Planet2.SolarAngle >= 360) { Planet2.SolarAngle -= 360; }
// 月球自轉(zhuǎn)
Planet2.OwnAxisAngle += 1.0f;
if (Planet2.OwnAxisAngle >= 360) { Planet2.OwnAxisAngle -= 360; }
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // 清除顏色和深度緩存
glColor3f(1.0, 0.0, 0.0);
glColor3f(1.0, 1.0, 1.0);
glColor3f(0.7f, 0.7f, 0.7f);
glBegin(GL_LINE_LOOP);
// 繪制軌道
for (int l = 0; l < 360; l++)
{
glVertex3f((float)cos(l * ((float)3.14159 / (float)180)) * Planet1.posZ, 0.0f, (float)sin(l * ((float)3.14159 / (float)180)) * Planet1.posZ);
}
glEnd();
glPushMatrix();
// 地球
// 坐標(biāo)變換,使地球在公轉(zhuǎn)軌道上轉(zhuǎn)
glRotatef(Planet1.SolarAngle, 0, -1, 0); //旋轉(zhuǎn)
glTranslatef(Planet1.posX, Planet1.posY, Planet1.posZ); //平移
glRotatef(Planet1.OwnAxisAngle, 0, -1, 0);
glBindTexture(GL_TEXTURE_2D, 1); //設(shè)置紋理
GLUquadricObj* q = gluNewQuadric();
gluQuadricDrawStyle(q, GLU_FILL);
gluQuadricNormals(q, GLU_SMOOTH);
gluQuadricTexture(q, GL_TRUE);
gluSphere(q, Planet1.size, 50, 40); //畫球
gluDeleteQuadric(q);
glBindTexture(GL_TEXTURE_2D, 0);
// 月球
glRotatef(Planet2.SolarAngle, 0, 1, 0);
glTranslatef(0.5*Planet2.posX, 0.5*Planet2.posY, 0.5*Planet2.posZ);
glRotatef(Planet2.OwnAxisAngle, 0, -1, 0);
glRotatef(90.0, 1.0, 0.0, 0.0);
glBindTexture(GL_TEXTURE_2D, 2);
GLUquadricObj* q2 = gluNewQuadric();
gluQuadricDrawStyle(q2, GLU_FILL);
gluQuadricNormals(q2, GLU_SMOOTH);
gluQuadricTexture(q2, GL_TRUE);
gluSphere(q2, Planet2.size, 50, 40);
gluDeleteQuadric(q2);
glPopMatrix();
glLoadIdentity();
draw_sun(); //繪制太陽
gluLookAt(R * cos(b / 180 * 3.1415926) * sin(a / 180 * 3.1415926), R * sin(b / 180 * 3.1415926), R * cos(b / 180 * 3.1415926) * cos(a / 180 * 3.1415926), 0.0, 0.0, 0.0, cos((90 - b) / 180 * 3.1415926) * sin((a + 180) / 180 * 3.1415926), sin((90 - b) / 180 * 3.1415926), cos((90 - b) / 180 * 3.1415926) * cos((a + 180) / 180 * 3.1415926)); //觀察角度
glutSwapBuffers();
}
void reshape(int w, int h)
{
glViewport(0, 0, (GLsizei)w, (GLsizei)h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0, (GLfloat)w / (GLfloat)h, 0.1, 20.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void keyboard(unsigned char key, int x, int y)
{
switch (key) {
case 'w':
R -= 0.1;
break;
case 's':
R += 0.1;
break;
case 27:
exit(0);
break;
default:
break;
}
}
void processMouse(int button, int state, int x, int y)
{
if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
{
start = 1;
ori_x = x;
ori_y = y;
}
if (button == GLUT_LEFT_BUTTON && state == GLUT_UP)
{
start = 0;
}
}
void onMouseMove(int x, int y)
{
if (start == 1)
{
a -= (x - ori_x) / 2;
b += (y - ori_y) / 2;
ori_x = x;
ori_y = y;
}
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize(1000, 600);
glutInitWindowPosition(100, 100);
glutCreateWindow(argv[0]);
init();
glutDisplayFunc(display);
glutIdleFunc(display);
draw_sun();
glutReshapeFunc(reshape);
glutKeyboardFunc(keyboard);
glutMouseFunc(processMouse);
glutMotionFunc(onMouseMove);
glutMainLoop();
return 0;
}
項(xiàng)目一(選)(git上偷的太陽系):
#define GL_SILENCE_DEPRECATION
#include<stdio.h>
#include<stdlib.h>
#include <GLUT/glut.h>
#include<math.h>
#include<time.h>
#define PI 3.14
float angleMoon=0.0, angleEarth=0.0,angleAstroid=0.0,
angleMars=0.0,
angleMercury=0.0,
angleVenus=0.0,
angleJupiter=0.0,
angleSaturn=0.0,
angleUranus=30.0,
angleNeptune=60.0;
GLfloat sx=0.2,sy=0.2,sz=0.2;
int planet1;
GLfloat black[]={0.0f,0.0f,0.0f,1.0f};
GLfloat white[]={1.0f,1.0f,1.0f,1.0f};
GLfloat blue[]={0.0f,0.0f,0.9f,1.0f};
GLfloat er[]={0.0f,5.0f,0.9f,1.0f};
GLfloat yellow[]={0.7f,0.2f,0.0f,1.0f};
GLfloat qAmb[]={0.1,0.1,0.1,1.0};
GLfloat qDif[]={1.0,1.0,1.0,1.0};
GLfloat qSpec[]={.50,.50,.50,.10};
GLfloat qPos[]={0,0,0,0.1};
GLfloat sc[8]={0.295 , 0.40,0.50, 0.60,0.80,1.0,1.05,1.13};
double ang=2*PI/300;
double angular=2*PI/50;
void initLighting()
{
//glMaterialfv(GL_FRONT,GL_AMBIENT,yellow);
//glMaterialfv(GL_FRONT,GL_SPECULAR,yellow);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT7);
glLightfv(GL_LIGHT7,GL_AMBIENT,qAmb);
glLightfv(GL_LIGHT7,GL_DIFFUSE,qDif);
glLightfv(GL_LIGHT7,GL_SPECULAR,qSpec);
//glMaterialfv(GL_FRONT,GL_DIFFUSE,yellow);
}
void myinit()
{
glClearColor(0.0,0.0,0.0,0.0); //backgroundcolor is green
//gluOrtho2D(0,699,0,699);
glPointSize(1.0);
glLineWidth(2.0);
}
void background()
{
glBegin(GL_QUADS);
glColor3f(0.0,0.00,0.00);
glVertex3f(-01.00,01.00,1);
glColor3f(.20,0.0,0.70);
glVertex3f(01.00,1.00,1);
glColor3f(0,0.0,0.0);
glVertex3f(1.00,-1.00,1);
glColor3f(.70,.10,.20);
glVertex3f(-1.00,-1.00,1);
glEnd();
}
void orbit()
{
glColor3f(0.5,0.5,0.5);
int i=0;
for(i=0;i<8;i++){
glPushMatrix();
if(i==5)
{glRotatef(45,1.0,0.0,0.0);}
else
{glRotatef(63,1.0,0.0,0.0);}
glScalef(sc[i],sc[i],sc[i]);
glBegin(GL_POINTS);
double ang1=0.0;
int i=0;
for(i=0;i<300;i++)
{glVertex2d(cos(ang1),sin(ang1));
ang1+=ang; }
glEnd();
glPopMatrix();
}
}
void draw(void)
{
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
background();
orbit();
glLoadIdentity();
glPushMatrix();
glEnable(GL_DEPTH_TEST);
glEnable(GL_COLOR_MATERIAL);
glPushMatrix();
glColor3f(0.7,0.5,0.0);
glScalef(sx,sy,sz);
glLightfv(GL_LIGHT7,GL_POSITION,qPos);
glMaterialfv(GL_FRONT_AND_BACK,GL_EMISSION,yellow);
glutSolidSphere(1,50,50);
glMaterialfv(GL_FRONT_AND_BACK,GL_EMISSION,black);
glPopMatrix();
glScalef(0.2,0.2,0.2);
glPushMatrix();
glRotatef(angleMercury,0.0,1.0,-0.5);
glTranslatef(1.5,0.0,0.0);
glColor3f(1.0,0.9,0.0);
glScalef(0.08,0.08,0.08);
glutSolidSphere(1,50,50);
glPopMatrix();
glPushMatrix();
glRotatef(angleVenus,0.0,1.0,-0.5);
glTranslatef(2.0,0.0,0.0);
glColor3f(0.9,0.1,0.0);
glScalef(0.1,0.1,0.1);
glutSolidSphere(1,50,50);
glPopMatrix();
glPushMatrix();
glRotatef(angleEarth,0.0,1.0,-0.5);
glTranslatef(2.5,0.0,0.0);
glColor3f(0.0,0.1,0.7);
glScalef(0.23,0.23,0.23);
glutSolidSphere(1,50,50);
glPushMatrix();
glRotatef(angleMoon,0.0,0.1,0.05);
glTranslatef(1.3,0.0,0.0);
glColor3f(1.0,1.0,1.0);
glScalef(0.5,0.5,0.5);
glutSolidSphere(0.5,50,50);
glPopMatrix();//moon made
glPopMatrix();//earth made
glPushMatrix();
glRotatef(angleMars,0.0,1.0,-0.5);
glTranslatef(-3.0,0.0,0.0);
glColor3f(0.05,0.05,0.01);
glScalef(0.17,0.17,0.17);
glutSolidSphere(1,50,50);
glPopMatrix();
glPushMatrix();
glColor3f(3.30,3.30,3.30);
glRotatef(63,1.0,0.0,0.0);
int j=0,i=0,div=90;float siz=2;
float scl[4]={3.3,3.4,3.35,3.2};
for(j=0;j<4;j++)
{glPushMatrix();siz-=0.3;
glPointSize(siz);
glScalef(scl[j],scl[j],scl[j]);
glBegin(GL_POINTS);
double ang1=0.0 -angleAstroid,a=(2*PI)/div;
for(i=0;i<div;i++)
{glVertex2d(cos(ang1),sin(ang1));
ang1+=a; }
div+=10;
glEnd();
glPopMatrix();
}
glPopMatrix();//astroid made
glPushMatrix();
glRotatef(angleJupiter,0.0,1.0,-0.5);
glTranslatef(-4.0,0.0,0.0);
glColor3f(0.4,0.2,0.0);
glScalef(0.5,0.5,0.5);
glutSolidSphere(1,50,50);
glPushMatrix();
glRotatef(angleMoon,1.0,-0.5,0.0);
glTranslatef(0.0,0,1.1);
glColor3f(1.0,1.0,1.0);
glScalef(0.1,0.1,0.1);
glutSolidSphere(0.5,50,50);
glPopMatrix();//moon made
glPopMatrix();
glPushMatrix();
glRotatef(angleSaturn,0.0,1.0,-1.0);
glTranslatef(-5.0,0.0,0.0);
glColor3f(0.9,0.0,0.0);
glScalef(0.4,0.4,0.4);
glutSolidSphere(1,50,50);
glPushMatrix();
glRotatef(45,1.0,0.0,0.0);
glPointSize(3);
glColor3f(5.0,3.0,1.0);
glScalef(1.2,1.2,1.2);
glBegin(GL_POINTS);
double ang1=0.0;
i=0;
for(i=0;i<50;i++)
{glVertex2d(cos(ang1),sin(ang1));
ang1+=angular; }
glEnd();
glPointSize(2);
glPopMatrix();//ring made
glPopMatrix();
glPushMatrix();
glRotatef(angleUranus,0.0,1.0,-0.5);
glTranslatef(5.2,0.0,0.0);
glColor3f(0.0,0.5,0.9);
glScalef(0.23,0.23,0.23);
glutSolidSphere(1,50,50);
glPopMatrix();
glPushMatrix();
glRotatef(angleNeptune,0.0,1.0,-0.5);
glTranslatef(-5.7,0.0,0.0);
glColor3f(0.0,0.0,0.9);
glScalef(0.2,0.2,0.2);
glutSolidSphere(1,50,50);
glPopMatrix();
glPopMatrix();
glFlush();
}
void update(int value){
if((angleMoon>=0 && angleMoon<180) )
{sx-=0.0003;sy-=0.0003;sz-=0.0003;}
else{sx+=0.0003;sy+=0.0003;sz+=0.0003;}
angleMoon+=2;
if(angleMoon>360){
angleMoon-=360;}
angleEarth+=0.7;
if(angleEarth>360){
angleEarth-=360;}
angleMercury+=2;
if(angleMercury>360){
angleMercury-=360;}
angleVenus+=0.9;
if(angleVenus>360){
angleVenus-=360;}
angleMars+=0.5;
if(angleMars>360){
angleMars-=360;}
angleJupiter+=0.2;
if(angleJupiter>360){
angleJupiter-=360;}
angleSaturn+=0.1;
if(angleSaturn>360){
angleSaturn-=360;}
angleUranus+=0.05;
if(angleUranus>360){
angleUranus-=360;}
angleNeptune+=0.02;
if(angleNeptune>360){
angleNeptune-=360;}
angleAstroid+=0.002;
if(angleAstroid>360){
angleAstroid-=360;}
glutPostRedisplay();
glutTimerFunc(20,update,0);
}
int main(int argc, char **argv)
{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);
glutInitWindowPosition(0,0);
glutInitWindowSize(700,700);
glutCreateWindow("Solar System");
initLighting();
myinit();
glutDisplayFunc(draw);
glutTimerFunc(25,update,0);
glutMainLoop();
return 0;
}
項(xiàng)目二(B樣條):
#define GL_SILENCE_DEPRECATION
#include<vector>
#include<GLUT/glut.h>
using namespace std;
int sta = 0;//狀態(tài)顯示
struct Point
{
int x;
int y;
};
vector<Point> p;
void Bspline(Point a, Point b, Point c, Point d) {
glPointSize(2);
glColor3d(0, 0, 0);
glBegin(GL_LINE_STRIP);
for (int i = 0; i <= 1000; i++)
{
double t = 0.001 * i;
double r[4];
r[0] = -t * t * t + 3 * t * t - 3 * t + 1;
r[1] = 3 * t * t * t - 6 * t * t + 4;
r[2] = -3 * t * t * t + 3 * t * t + 3 * t + 1;
r[3] = t * t * t;
double x = 0, y = 0;
x += r[0] * a.x + r[1] * b.x + r[2] * c.x + r[3] * d.x;
y += r[0] * a.y +r[1] * b.y + r[2] * c.y + r[3] * d.y;
x /= 6.0;
y /= 6.0;
glVertex2d(x,y);
}
glEnd();
}
void Display()
{
glClear(GL_COLOR_BUFFER_BIT);
//畫點(diǎn)
glPointSize(7);
glColor3d(0, 0, 1);
glBegin(GL_POINTS);
for (int i = 0; i < p.size(); i++)
glVertex2d(p[i].x, p[i].y);
glEnd();
//畫線
glLineWidth(2);
glColor3d(1, 0, 1);
glBegin(GL_LINE_STRIP);
for (int i = 0; i < p.size(); i++)
glVertex2d(p[i].x, p[i].y);
glEnd();
if (sta == 1 && p.size() >= 3)
for (int i = 0; i < p.size() - 3; i++)
Bspline(p[i], p[i + 1], p[i + 2], p[i + 3]);
glFlush();
}
void Mouse(int button, int state, int x, int y)
{
if (sta == 0 && button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
{
Point t;
t.x = x; t.y = y;
p.push_back(t);
glutPostRedisplay();
}
if (sta == 0 && button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN) {
sta = 1;
glutPostRedisplay();
}
}
void Keyboard(unsigned char key, int x, int y)
{
if (key == 'd')
{
glClearColor(1, 1, 1, 0);
glClear(GL_COLOR_BUFFER_BIT);
p.clear();
sta = 0;
glutPostRedisplay();
}
}
void Reshape(int w, int h)
{
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0, w, h, 0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
int main(int argc, char* argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowPosition(100, 100);
glutInitWindowSize(600, 600);
glutCreateWindow("B樣條曲線");
glClearColor(1, 1, 1, 0);
glutDisplayFunc(Display);
glutReshapeFunc(Reshape);
glutMouseFunc(Mouse);
glutKeyboardFunc(Keyboard);
glutMainLoop();
return 0;
}
???????文章來源:http://www.zghlxwxcb.cn/news/detail-498632.html
有用的話點(diǎn)點(diǎn)贊捏!!文章來源地址http://www.zghlxwxcb.cn/news/detail-498632.html
到了這里,關(guān)于【計(jì)算機(jī)圖形學(xué)】【實(shí)驗(yàn)報(bào)告】太陽系繪制、B樣條曲線繪制(附代碼)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!