日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

opengl绘制长方体线框_OpenGL绘图实例十之绘制3D机器人

發布時間:2023/12/19 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 opengl绘制长方体线框_OpenGL绘图实例十之绘制3D机器人 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

綜述

通過上一節說的繪制3D圖形基礎,我們應該對繪制3D圖形有了基本的認識,接下來我們就進行一個實例,繪制一個3D機器人。 本節我們要完成的任務有:

1.繪制一個仿真3D機器人(樣式自選,參考例圖),至少包含頭、軀干、四肢三個部分. 2.對機器人填充顏色。 3.增加點光源,使得機器人更加真實。 4.實現交互,使得能夠控制機器人進行旋轉、前進、后退等動作。 鍵盤”w”:前進 鍵盤”s”:后退 鍵盤”a”:順時針旋轉 鍵盤”d”:逆時針旋轉

接下來我們就一步步實現機器人的繪制吧。

繪制球體

繪制球體我們有兩種方法,一個叫glutSolidSphere,另一個叫glutWireSphere,這兩個的區別在于,一個繪制的是實心的球體,另一個繪制的是現狀描繪而成的球體,在繪制過程中,我們可以通過一個參數來對其進行控制。 glutSolidSphere是GLUT工具包中的一個函數,該函數用于渲染一個球體。球體球心位于原點。在OpenGL中默認的原點就是窗口客戶區的中心。 函數原型

1

2

void glutSolidSphere(GLdoubleradius, GLint slices , GLint stacks);

void glutWireSphere(GLdouble radius, GLint slices, GLint stacks );

radius,球體的半徑 slices,以Z軸上線段為直徑分布的圓周線的條數(將Z軸看成地球的地軸,類似于經線) stacks,圍繞在Z軸周圍的線的條數(類似于地球上緯線) 一般而言, 后兩個參數賦予較大的值, 渲染花費的時間要長, 效果更逼真。 然而我們可以發現,這里并沒有定義球中心的參數,所以,我們可以利用平移函數組合實現。即利用glTranslated函數來實現。最后,我們定義的畫球體的方法如下

1

2

3

4

5

6

7

8

9

10

11

//畫球

void drawBall(double R, double x, double y,double z, int MODE) {

glPushMatrix();

glTranslated(x,y,z);

if (MODE==SOLID) {

glutSolidSphere(R,20,20);

} else if (MODE ==WIRE) {

glutWireSphere(R,20,20);

}

glPopMatrix();

}

其中兩個常量定義如下

1

2

#define SOLID 1

#define WIRE 2

在這里我們還用到了上一節所說的PushMatrix和PopMatrix方法。如果不熟悉,請查看上一節的內容。

繪制長方體

同樣地,利用變換平移放縮的方法,再加上類庫的繪制正方體的方法,我們也可以輕松地實現繪制長方體的方法。 正方體怎樣變成長方體,很簡單,拉伸一下就好了。所以,我們用到了glScaled方法。 繪制長方體的方法如下

1

2

3

4

5

6

7

8

9

10

11

12

//畫長方體

void drawSkewed(double l, double w, double h, double x, double y, double z, int MODE) {

glPushMatrix();

glScaled(l, w, h);

glTranslated(x, y, z);

if (MODE==SOLID) {

glutSolidCube(1);

} else if (MODE==WIRE) {

glutWireCube(1);

}

glPopMatrix();

}

這里仍然還是定義了繪圖模式,是線條還是實體。

定義光照

在這里提供一篇博文,講光照講得比較細致 OPENGL光照 那么在這里我就直接貼上光照設置的實現

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

void init() {

//定義光源的顏色和位置

GLfloat ambient[] = { 0.5, 0.8, 0.1, 0.1 };

GLfloat diffuse[] = { 1.0, 1.0, 1.0, 1.0 };

GLfloat position[] = { -80.0, 50.0, 25.0, 1.0 };

//選擇光照模型

GLfloat lmodel_ambient[] = { 0.4, 0.4, 0.4, 1.0 };

GLfloat local_view[] = { 0.0 };

glClearColor(0.0, 0.0, 0.0, 0.0);

glShadeModel(GL_SMOOTH);

//設置環境光

glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);

//設置漫射光

glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);

//設置光源位置

glLightfv(GL_LIGHT0, GL_POSITION, position);

glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);

glLightModelfv(GL_LIGHT_MODEL_LOCAL_VIEWER, local_view);

//啟動光照

glEnable(GL_LIGHTING);

//啟用光源

glEnable(GL_LIGHT0);

}

其中設置了光源顏色,位置等參數。

圖形的移動

在這里我們實現了鼠標的監聽旋轉和鍵盤的監聽旋轉,在這里分別描述如下

1.鼠標監聽

對于鼠標監聽事件,在前面的文章中已經做了說明,如果大家不熟悉可以看下面這篇文章 鼠標監聽 我們要實現的就是在拖動鼠標的時候實現圖形的旋轉功能。 在點擊鼠標時,我們記錄下來點擊的位置,然后在鼠標移動的時候記錄下當前坐標與上一個位置的坐標之差。通過定義一個角度的變量,每次鼠標移動的時候讓整個圖形旋轉角度加上這個差值,然后重新繪制圖形,就可以實現整個圖形的 旋轉了。 鼠標監聽的兩個方法如下,分別是鼠標點擊和鼠標移動。 定義兩個變量,旋轉角度

1

2

int spinX = 0;

int spinY = 0;

然后定義兩個鼠標事件

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

// 鼠標移動事件

void mouseMove(int x, int y){

int dx = x - moveX;

int dy = y - moveY;

printf("dx;%dx,dy:%dy\n",dx,dy);

spinX += dx;

spinY += dy;

glutPostRedisplay();

moveX = x;

moveY = y;

}

//鼠標點擊事件

void mouseClick(int btn, int state, int x, int y){

moveX = x;

moveY = y;

}

恩,通過定義上面的方法,然后在main中加入監聽。

1

2

3

4

//鼠標點擊事件,鼠標點擊或者松開時調用

glutMouseFunc(mouseClick);

//鼠標移動事件,鼠標按下并移動時調用

glutMotionFunc(mouseMove);

display函數中,在繪圖前調用該方法即可

1

2

glRotated(spinX, 0, 1, 0);

glRotated(spinY, 1, 0, 0);

分別是繞y軸和x軸旋轉一定的角度。這樣就可以實現鼠標的監聽了。

2.鍵盤監聽

鍵盤事件也很簡單,同樣是監聽按鍵的按下。其中w、s鍵是用來控制機器人的遠近的。 定義一個變量叫 dis,代表遠近 鍵盤事件函數如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

//鍵盤事件

void keyPressed(unsigned char key, int x, int y) {

switch (key) {

case 'a':

spinX -= 2;

break;

case 'd':

spinX += 2;

break;

case 'w':

des += 2;

break;

case 's':

des -= 2;

break;

}

glutPostRedisplay();

}

在main函數中加入監聽

1

2

//鍵盤事件

glutKeyboardFunc(keyPressed);

display函數中加入如下的變換

1

2

3

glRotated(spinX, 0, 1, 0);

glRotated(spinY, 1, 0, 0);

glTranslated(0, 0, des);

這樣通過上述方法,我們便可以實現鼠標和鍵盤的監聽了。

裁切物體

在這里我們可能要畫一個半圓,那么最方便的方法就是裁切了,利用下面的函數,我們可以方便地實現。

void glClipPlane(GLenum plane, const GLdouble *equation);

定義一個裁剪平面。equation參數指向平面方程Ax + By + Cz + D = 0的4個系數。 equation=(0,-1,0,0),前三個參數(0,-1,0)可以理解為法線向下,只有向下的,即Y<0的才能顯示,最后一個參數0表示從z=0平面開始。這樣就是裁剪掉上半平面。 equation=(0,1,0,0)表示裁剪掉下半平面, equation=(1,0,0,0)表示裁剪掉左半平面, equation=(-1,0,0,0)表示裁剪掉右半平面, equation=(0,0,-1,0)表示裁剪掉前半平面, equation=(0,0,1,0)表示裁剪掉后半平面 代碼示例如下

1

2

3

4

5

GLdouble eqn[4]={0.0,0.0,-1.0,0.0};

glClipPlane(GL_CLIP_PLANE0,eqn);

glEnable(GL_CLIP_PLANE0);

glutSolidSphere(headR,slices,slices);

glDisable(GL_CLIP_PLANE0);

首先我們必須要定義一個GLdouble數組,然后利用glClipPlane方法來設置,然后開啟裁切,最后關閉裁切。 利用類似的方法我們可以寫出繪制半球的方法如下

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

//畫半球

void drawHalfBall(double R, double x, double y,double z, int MODE) {

glPushMatrix();

glTranslated(x,y,z);

GLdouble eqn[4]={0.0, 1.0, 0.0, 0.0};

glClipPlane(GL_CLIP_PLANE0,eqn);

glEnable(GL_CLIP_PLANE0);

if (MODE==SOLID) {

glutSolidSphere(R,20,20);

} else if (MODE ==WIRE) {

glutWireSphere(R,20,20);

}

glDisable(GL_CLIP_PLANE0);

glPopMatrix();

}

恩,通過上述方法,我們可以方便地繪制出一個半球體。

繪制機器人

有了上述的鋪墊,我們繪制機器人簡直易如反掌,同樣還可以實現各式各樣的監聽。 主要就是位置的確定了。 display函數如下

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

void display(void) {

//清除緩沖區顏色

glClear(GL_COLOR_BUFFER_BIT);

//定義白色

glColor3f(1.0, 1.0, 1.0);

//圓點放坐標中心

glLoadIdentity();

//從哪個地方看

gluLookAt(-2.0, -1.0, 20.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);

glPushMatrix();

glRotated(spinX, 0, 1, 0);

glRotated(spinY, 1, 0, 0);

glTranslated(0, 0, des);

//頭

drawBall(2, 0, 1, 0, SOLID);

//身體

drawSkewed(5, 4.4, 4, 0, -0.75, 0, SOLID);

//肩膀

drawHalfBall(1, 3.5, -2.1, 0, SOLID);

drawHalfBall(1, -3.5, -2.1, 0, SOLID);

//胳膊

drawSkewed(1, 3, 1, 3.5, -1.3, 0, SOLID);

drawSkewed(1, 3, 1, -3.5, -1.3, 0, SOLID);

//手

drawBall(1, 3.5, -6.4, 0, SOLID);

drawBall(1, -3.5, -6.4, 0, SOLID);

//腿

drawSkewed(1.2, 3, 2, 1, -2.4, 0, SOLID);

drawSkewed(1.2, 3, 2, -1, -2.4, 0, SOLID);

//腳

drawSkewed(1.5, 1, 3, 0.9, -9.2, 0, SOLID);

drawSkewed(1.5, 1, 3, -0.9, -9.2, 0, SOLID);

glPopMatrix();

glutSwapBuffers();

}

恩,通過調用這個函數我們便可以完成機器人的繪制了。

完整代碼

在這里提供完整代碼示例,僅供參考

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

#include

#include

#include

#define SOLID 1

#define WIRE 2

int moveX,moveY;

int spinX = 0;

int spinY = 0;

int des = 0;

void init() {

//定義光源的顏色和位置

GLfloat ambient[] = { 0.5, 0.8, 0.1, 0.1 };

GLfloat diffuse[] = { 1.0, 1.0, 1.0, 1.0 };

GLfloat position[] = { -80.0, 50.0, 25.0, 1.0 };

//選擇光照模型

GLfloat lmodel_ambient[] = { 0.4, 0.4, 0.4, 1.0 };

GLfloat local_view[] = { 0.0 };

glClearColor(0.0, 0.0, 0.0, 0.0);

glShadeModel(GL_SMOOTH);

//設置環境光

glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);

//設置漫射光

glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);

//設置光源位置

glLightfv(GL_LIGHT0, GL_POSITION, position);

glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);

glLightModelfv(GL_LIGHT_MODEL_LOCAL_VIEWER, local_view);

//啟動光照

glEnable(GL_LIGHTING);

//啟用光源

glEnable(GL_LIGHT0);

}

//畫球

void drawBall(double R, double x, double y,double z, int MODE) {

glPushMatrix();

glTranslated(x,y,z);

if (MODE == SOLID) {

glutSolidSphere(R,20,20);

} else if (MODE ==WIRE) {

glutWireSphere(R,20,20);

}

glPopMatrix();

}

//畫半球

void drawHalfBall(double R, double x, double y,double z, int MODE) {

glPushMatrix();

glTranslated(x,y,z);

GLdouble eqn[4]={0.0, 1.0, 0.0, 0.0};

glClipPlane(GL_CLIP_PLANE0,eqn);

glEnable(GL_CLIP_PLANE0);

if (MODE == SOLID) {

glutSolidSphere(R,20,20);

} else if (MODE ==WIRE) {

glutWireSphere(R,20,20);

}

glDisable(GL_CLIP_PLANE0);

glPopMatrix();

}

//畫長方體

void drawSkewed(double l, double w, double h, double x, double y, double z, int MODE) {

glPushMatrix();

glScaled(l, w, h);

glTranslated(x, y, z);

if (MODE == SOLID) {

glutSolidCube(1);

} else if (MODE ==WIRE) {

glutWireCube(1);

}

glPopMatrix();

}

void display(void) {

//清除緩沖區顏色

glClear(GL_COLOR_BUFFER_BIT);

//定義白色

glColor3f(1.0, 1.0, 1.0);

//圓點放坐標中心

glLoadIdentity();

//從哪個地方看

gluLookAt(-2.0, -1.0, 20.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);

glPushMatrix();

glRotated(spinX, 0, 1, 0);

glRotated(spinY, 1, 0, 0);

glTranslated(0, 0, des);

//頭

drawBall(2, 0, 1, 0, SOLID);

//身體

drawSkewed(5, 4.4, 4, 0, -0.75, 0, SOLID);

//肩膀

drawHalfBall(1, 3.5, -2.1, 0, SOLID);

drawHalfBall(1, -3.5, -2.1, 0, SOLID);

//胳膊

drawSkewed(1, 3, 1, 3.5, -1.3, 0, SOLID);

drawSkewed(1, 3, 1, -3.5, -1.3, 0, SOLID);

//手

drawBall(1, 3.5, -6.4, 0, SOLID);

drawBall(1, -3.5, -6.4, 0, SOLID);

//腿

drawSkewed(1.2, 3, 2, 1, -2.4, 0, SOLID);

drawSkewed(1.2, 3, 2, -1, -2.4, 0, SOLID);

//腳

drawSkewed(1.5, 1, 3, 0.9, -9.2, 0, SOLID);

drawSkewed(1.5, 1, 3, -0.9, -9.2, 0, SOLID);

glPopMatrix();

glutSwapBuffers();

}

//鼠標點擊事件

void mouseClick(int btn, int state, int x, int y) {

moveX = x;

moveY = y;

GLfloat ambient[] = { (float)rand() / RAND_MAX, (float)rand() / RAND_MAX, (float)rand() / RAND_MAX, 0.1 };

//設置環境光

glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);

//啟用光源

glEnable(GL_LIGHT0);

}

//鍵盤事件

void keyPressed(unsigned char key, int x, int y) {

switch (key) {

case 'a':

spinX -= 2;

break;

case 'd':

spinX += 2;

break;

case 'w':

des += 2;

break;

case 's':

des -= 2;

break;

}

glutPostRedisplay();

}

// 鼠標移動事件

void mouseMove(int x, int y) {

int dx = x - moveX;

int dy = y - moveY;

printf("dx;%dx,dy:%dy\n",dx,dy);

spinX += dx;

spinY += dy;

glutPostRedisplay();

moveX = x;

moveY = y;

}

void reshape(int w, int h) {

//定義視口大小

glViewport(0, 0, (GLsizei) w, (GLsizei) h);

//投影顯示

glMatrixMode(GL_PROJECTION);

//坐標原點在屏幕中心

glLoadIdentity();

//操作模型視景

gluPerspective(60.0, (GLfloat) w/(GLfloat) h, 1.0, 20.0);

glMatrixMode(GL_MODELVIEW);

}

int main(int argc, char** argv) {

//初始化

glutInit(&argc, argv);

//設置顯示模式

glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);

//初始化窗口大小

glutInitWindowSize(500, 500);

//定義左上角窗口位置

glutInitWindowPosition(100, 100);

//創建窗口

glutCreateWindow(argv[0]);

//初始化

init();

//顯示函數

glutDisplayFunc(display);

//窗口大小改變時的響應

glutReshapeFunc(reshape);

//鼠標點擊事件,鼠標點擊或者松開時調用

glutMouseFunc(mouseClick);

//鼠標移動事件,鼠標按下并移動時調用

glutMotionFunc(mouseMove);

//鍵盤事件

glutKeyboardFunc(keyPressed);

//循環

glutMainLoop();

return 0;

}

僅供參考,如有問題,敬請指正。 運行結果如下 恩,大體就是這樣。

總結

本次實驗做的比較匆忙,只研究了一個晚上的時間,所以有些地方還是不太完善,希望發出來對小伙伴們有所啟發,有所幫助。如果有問題,歡迎同我交流。謝大家!

總結

以上是生活随笔為你收集整理的opengl绘制长方体线框_OpenGL绘图实例十之绘制3D机器人的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。