效果图如上:
步骤:略。
实现代码如下:
1 /********************************************************************** 2 3 VertexArray Tutorial 4 5 June, 10th, 2000 6 7 This tutorial was written by Philipp Crocoll 8 Contact: 9 philipp.crocoll@web.de 10 www.codecolony.de 11 12 Every comment would be appreciated. 13 14 If you want to use parts of any code of mine: 15 let me know and 16 use it! 17 *********************************************************************** 18 19 p : switches between line and point mode 20 21 ***********************************************************************/ 22 23 #include <GL\glut.h> 24 #include <math.h> 25 #include <vector> 26 using namespace std; 27 #define PI 3.1415265359 28 struct SVertex 29 { 30 GLfloat x,y,z; 31 GLfloat r,g,b; 32 }; 33 34 //Data for the sphere vertices: 35 SVertex * Vertices; 36 int NumVertices; //size of the vertex array 37 vector <GLuint> IndexVect; //we first put the indices into this vector, then copy them to the array below 38 GLuint * Indices; 39 int NumIndices; //size of the index array 40 41 GLfloat ChangeY = 0.025;//Indicates how much the y values of the highest and deepest vertex 42 //in the sphere are changed each time it is rendered 43 float yRotated = 0.0; 44 bool PointsOnly = false;//Indicated, if the triangles or only points are drawn 45 46 // 参数1:水平点的个数;参数2:纵向点的个数; 47 void CreateSphere(int PointRows, int PointsPerRow) 48 { 49 NumVertices = (PointRows-2)*PointsPerRow + 2; // 总点数 50 Vertices = new SVertex[NumVertices]; 51 free(Indices); 52 IndexVect.clear(); //to be sure it is empty 清空 53 float x,y,z; 54 int i,j; 55 double r; 56 for (i = 1; i < (PointRows-1); i++) 57 { 58 for (j = 0; j < PointsPerRow; j++) 59 { 60 y = 1.0 - float(i) / float(PointRows-1)*2.0; 61 r = sin (acos(y)); // 这个以Y为轴的圆的半径。 62 x = r * sin(float(j) / float(PointsPerRow)*PI*2.0); // 这个以X为轴的圆与上面的圆的交点的X坐标 63 64 z = r * cos(float(j) / float(PointsPerRow)*PI*2.0); // 这个以Z为轴的圆与上面的圆的交点的Z坐标 65 Vertices[(i-1)*PointsPerRow+j].x = x; 66 Vertices[(i-1)*PointsPerRow+j].y = y; 67 Vertices[(i-1)*PointsPerRow+j].z = z; 68 Vertices[(i-1)*PointsPerRow+j].r = (float)(i) / float(PointRows); 69 Vertices[(i-1)*PointsPerRow+j].g = 0.6; 70 Vertices[(i-1)*PointsPerRow+j].b = (float)(j) / float(PointsPerRow); 71 } 72 73 } 74 //The highest and deepest vertices: // 最值点 --上下各1个。 75 Vertices[(PointRows-2)*PointsPerRow].x = 0.0; 76 Vertices[(PointRows-2)*PointsPerRow].y = 1.0; 77 Vertices[(PointRows-2)*PointsPerRow].z = 0.0; 78 Vertices[(PointRows-2)*PointsPerRow].r = 1.0; 79 Vertices[(PointRows-2)*PointsPerRow].g = 0.7; 80 Vertices[(PointRows-2)*PointsPerRow].b = 1.0; 81 Vertices[(PointRows-2)*PointsPerRow+1].x = 0.0; 82 Vertices[(PointRows-2)*PointsPerRow+1].y = -1.0; 83 Vertices[(PointRows-2)*PointsPerRow+1].z = 0.0; 84 Vertices[(PointRows-2)*PointsPerRow+1].r = 1.0; 85 Vertices[(PointRows-2)*PointsPerRow+1].g = 0.7; 86 Vertices[(PointRows-2)*PointsPerRow+1].b = 1.0; 87 88 for (i = 1; i < (PointRows-2); i++) 89 { 90 for (j = 0; j < (PointsPerRow-1); j++) 91 { // 当PointsPerRow= 8 ,首次赋的值是?? 92 IndexVect.push_back((i-1)*PointsPerRow+j); // 0 1 93 IndexVect.push_back((i-1)*PointsPerRow+j+1); // 1 2 94 IndexVect.push_back((i)*PointsPerRow+j); // 8 9 95 96 IndexVect.push_back((i-1)*PointsPerRow+j+1); // 1 2 97 IndexVect.push_back((i)*PointsPerRow+j+1); // 9 10 98 IndexVect.push_back((i)*PointsPerRow+j); // 8 9 99 } 100 // 连接左右两侧的线结构 101 IndexVect.push_back((i-1)*PointsPerRow+PointsPerRow-1); // 7 102 IndexVect.push_back((i-1)*PointsPerRow); // 0 103 IndexVect.push_back((i)*PointsPerRow+j); // 16 104 105 IndexVect.push_back((i)*PointsPerRow); // 8 106 IndexVect.push_back((i-1)*PointsPerRow); // 0 107 IndexVect.push_back((i)*PointsPerRow+j); // 16 108 } 109 110 //The triangles to the highest and deepest vertices: // 连接三角形的最高和最深的顶点 111 for (j = 0; j< (PointsPerRow-1); j++) 112 { 113 IndexVect.push_back(j); 114 IndexVect.push_back(j+1); 115 IndexVect.push_back((PointRows-2)*PointsPerRow); 116 } 117 IndexVect.push_back(j); 118 IndexVect.push_back(0); 119 IndexVect.push_back((PointRows-2)*PointsPerRow); 120 121 for (j = 0; j< (PointsPerRow-1); j++) 122 { 123 IndexVect.push_back((PointRows-3)*PointsPerRow+j); 124 IndexVect.push_back((PointRows-3)*PointsPerRow+j+1); 125 IndexVect.push_back((PointRows-2)*PointsPerRow+1); 126 } 127 IndexVect.push_back((PointRows-3)*PointsPerRow+j); 128 IndexVect.push_back((PointRows-3)*PointsPerRow); 129 IndexVect.push_back((PointRows-2)*PointsPerRow+1); 130 131 Indices = new GLuint[IndexVect.size()]; //allocate the required memory 132 for (i = 0; i < IndexVect.size(); i++) 133 { 134 Indices[i] = IndexVect[i]; // 复制顶点数组到临时空间。 135 } 136 NumIndices = IndexVect.size(); 137 IndexVect.clear(); //no longer needed, takes only memory 释放空间 138 } 139 140 void DrawSphere(void) 141 { 142 if (!PointsOnly) 143 glDrawElements( GL_TRIANGLES, //mode 三角形 144 NumIndices, //count, ie. how many indices 绘制图元的数量乘上一个图元的顶点数 (*3) 145 GL_UNSIGNED_INT, //type of the index array 索引值的类型 146 Indices); // 指向索引存贮位置的指针 147 else 148 glDrawArrays(GL_POINTS,0,NumVertices); 149 150 } 151 152 void Display(void) 153 { 154 glClear(GL_COLOR_BUFFER_BIT); 155 glLoadIdentity(); 156 glTranslatef(0.0,0.0,-3.2); // 为了显示全部图像 157 glRotatef(yRotated, 0.0, 1.0, 0.0); // 旋转图像 158 DrawSphere(); // 用户自定义绘制函数 159 glFlush(); //Finish rendering 160 glutSwapBuffers(); 161 } 162 163 void Reshape(int x, int y) 164 { 165 if (y == 0 || x == 0) return; //Nothing is visible then, so return 166 //Set a new projection matrix 167 glMatrixMode(GL_PROJECTION); 168 glLoadIdentity(); 169 //Angle of view:40 degrees 170 //Near clipping plane distance: 0.5 171 //Far clipping plane distance: 20.0 172 gluPerspective(60.0,(GLdouble)x/(GLdouble)y,0.5,20.0); 173 glViewport(0,0,x,y); //Use the whole window for rendering 174 glMatrixMode(GL_MODELVIEW); 175 176 } 177 178 static long long times = 0; 179 void Idle(void) 180 { 181 times++; // 延迟 182 if(times>500000) 183 times =0; 184 if(times% 500000== 0) 185 { 186 Vertices[NumVertices-2].y += ChangeY; // 最高点变化 187 Vertices[NumVertices-1].y -= ChangeY;// 最低点变化 188 189 if (Vertices[NumVertices-2].y> 1.5 || Vertices[NumVertices-2].y< 0.5) 190 ChangeY *= -1; // 变化值的取反 191 yRotated += 0.3; // 以Y为轴的旋转角度 192 Display(); 193 } 194 } 195 196 void Keyboard(unsigned char key, int x, int y) 197 { 198 switch(key) 199 { 200 case 'p': 201 PointsOnly = !PointsOnly; 202 break; 203 } 204 } 205 206 int main (int argc, char **argv) 207 { 208 //Initialize GLUT 209 glutInit(&argc, argv); 210 glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB); 211 glutInitWindowSize(300,300); 212 //Create a window with rendering context and everything else we need 213 glutCreateWindow("Vertex Arrays"); 214 //compute the vertices and indices 215 CreateSphere(16,16); 216 //as we do not yet use a depth buffer, we cannot fill our sphere 217 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); 218 //Enable the vertex array functionality: 219 glEnableClientState(GL_VERTEX_ARRAY); // 开启“顶点数组” 220 glEnableClientState(GL_COLOR_ARRAY); // 开启“颜色数组” 221 glVertexPointer( 3, //3 components per vertex (x,y,z) 222 GL_FLOAT, 223 sizeof(SVertex), 224 Vertices); 225 glColorPointer( 3, //3 components per vertex (r,g,b) 226 GL_FLOAT, 227 sizeof(SVertex), 228 &Vertices[0].r); //Pointer to the first color 229 glPointSize(3.0); // 点大小 230 glClearColor(0.0,0.0,0.0,0.0); // 黑色 231 //Assign the two used Msg-routines 232 glutDisplayFunc(Display); 233 glutReshapeFunc(Reshape); 234 glutKeyboardFunc(Keyboard); 235 glutIdleFunc(Idle); 236 //Let GLUT get the msgs 237 glutMainLoop(); 238 return 0; 239 }