用Opengl画一个球体

时间:2012-01-22 05:59:23

标签: opengl geometry draw vbo

我通过OpenGL绘制球体。 当“SLIED = STACK”时,该程序可以绘制球体。 但是当“SLIED not equal STACK”时,它不起作用。 我可能错了“索引数组”。

我想使用VBO和DMA(动态内存allocate.use平面数组)。 但如果你有另一个好主意,请教我。

            //#pragma comment(linker, "/SUBSYSTEM:WINDOWS /ENTRY:mainCRTStartup")
            #pragma comment(lib,"glew32.lib")

            #include <gl/glew.h>
            #include <math.h>
            #include <GL/freeglut/freeglut.h>
            #define WIDTH 640
            #define HEIGHT 480
            #define M_PI 3.14159265358979323846

            float angle=0.0f;

            //functions----------------------------------------------//
            void Shere_dma(double radius, int nSlice, int nStack);
            void setSphereData(double radius, int nSlice, int nStack);
            void DrawSphereVBO(void);
            //-------------------------------------------------------//

            //variabless---------------------------------------------//
            int SLICE=0;
            int STACK=0;

            GLuint SVboId[3];
            GLfloat* Svertex;//Vertex
            GLfloat* Snormal;//Normal
            GLfloat* Scolor; //Color

            GLuint* indices_top;    //TOP indices
            GLuint* indices_bottom; //BOTTOM indies
            GLuint* indices_side;   //SIDE indices
            //-------------------------------------------------------//

            //Memory Allocate
            void Shere_dma(double radius, int nSlice, int nStack){
                Svertex = new GLfloat[(nSlice+1)*(nStack+1)*3];
                Snormal = new GLfloat[(nSlice+1)*(nStack+1)*3];
                Scolor = new GLfloat[(nSlice+1)*(nStack+1)*3];

                indices_top = new GLuint[(nSlice+1)*(nStack+1)*3];
                indices_bottom = new GLuint[(nSlice+1)*(nStack+1)*3];
                indices_side = new GLuint[(nSlice+1)*(nStack+1)*4];
            }
            //inputData
            void setSphereData(double radius, int nSlice, int nStack){
                double phi; //Azimuth
                double theta; //long

                int coordinates=0;
                int Slice_current_point_no=0;
                int Slice_next_point_no=0;

                const int x = 0;
                const int y = 1;
                const int z = 2;

                const int p1 = 0;
                const int p2 = 1;
                const int p3 = 2;
                const int p4 = 3;

                //Vertex
                for(int i = 0;i <= nSlice;i++)
                {   
                    phi = 2.0 * M_PI * (double)i / (double)nSlice;
                    for(int j = 0;j <= nStack;j++)
                    {   
                        theta = M_PI * (double)j / (double)nStack;
                        Svertex[coordinates+x] = (float)(radius * sin(theta) * cos(phi));   //x
                        Svertex[coordinates+y] = (float)(radius * sin(theta) * sin(phi));   //y
                        Svertex[coordinates+z] = (float)(radius * cos(theta));              //z

                        Snormal[coordinates+x] = (float)(radius * sin(theta) * cos(phi));   //x
                        Snormal[coordinates+y] = (float)(radius * sin(theta) * sin(phi));   //y
                        Snormal[coordinates+z] = (float)(radius * cos(theta));              //z

                        Scolor[coordinates+x] = 1.0;                                            //x
                        Scolor[coordinates+y] = 0.0;                                            //y
                        Scolor[coordinates+z] = 0.0;                                            //z

                        coordinates += 3;           
                    }
                }

                //TOP
                coordinates = 0;
                Slice_current_point_no = 0;
                Slice_next_point_no    = nSlice;

                for(int i = 0; i < nSlice; i++){

                    indices_top[coordinates+p1] = Slice_current_point_no;
                    indices_top[coordinates+p2] = indices_top[coordinates]+1;
                    indices_top[coordinates+p3] = Slice_next_point_no+2;

                    coordinates+=3;
                    Slice_current_point_no += nSlice+1;
                    Slice_next_point_no    += nSlice+1;
                }

                //BOTTOM
                coordinates =0;
                Slice_current_point_no  = 0;
                Slice_next_point_no     = nSlice;

                for(int i = 0; i < nSlice; i++){

                    indices_bottom[coordinates+p1] = Slice_current_point_no+(nStack-1);
                    indices_bottom[coordinates+p2] = indices_bottom[coordinates]+1;
                    indices_bottom[coordinates+p3] = Slice_next_point_no+(nStack);

                    coordinates+=3;
                    Slice_current_point_no += nSlice+1;
                    Slice_next_point_no    += nSlice+1;
                }
                //↓May be wrong ********************************************************************************//
                //SIDE
                coordinates=0;
                Slice_current_point_no = 0;
                Slice_next_point_no    = nSlice+1;

                for(int i=0; i < nSlice;i++){
                    for(int j=1; j < nStack-1; j++){
                        indices_side[coordinates+p1]    = Slice_current_point_no+j;
                        indices_side[coordinates+p2] = indices_side[coordinates]+1;
                        indices_side[coordinates+p3] = Slice_next_point_no+(j+1);
                        indices_side[coordinates+p4] = Slice_next_point_no+j;
                        coordinates+=4;
                    }
                       Slice_current_point_no += nSlice+1;
                       Slice_next_point_no    += nSlice+1;
                }
                //↑May be wrong ********************************************************************************//
                 glGenBuffers(3,&SVboId[0]);

                 //Vertex
                 glBindBuffer(GL_ARRAY_BUFFER,SVboId[0]);
                 glBufferData(GL_ARRAY_BUFFER,sizeof(GLfloat)*(nSlice+1)*(nStack+1)*3,
                    Svertex,GL_DYNAMIC_DRAW);

                 //Normal
                 glBindBuffer(GL_ARRAY_BUFFER,SVboId[1]);
                 glBufferData(GL_ARRAY_BUFFER,sizeof(GLfloat)*(nSlice+1)*(nStack+1)*3,
                    Snormal,GL_DYNAMIC_DRAW);

                 //Color
                 glBindBuffer(GL_ARRAY_BUFFER,SVboId[2]);
                 glBufferData(GL_ARRAY_BUFFER,sizeof(GLfloat)*(nSlice+1)*(nStack+1)*3,
                     Scolor,GL_STREAM_DRAW);

            }

            //Draw
            void DrawSphereVBO(void)
            {
                int point=0;

                //Enable
                glEnableClientState(GL_VERTEX_ARRAY);
                glEnableClientState(GL_NORMAL_ARRAY);
                glEnableClientState(GL_COLOR_ARRAY);

                //Vertex
                glBindBuffer(GL_ARRAY_BUFFER,SVboId[0]);
                glVertexPointer(3, GL_FLOAT, 0, 0);

                //Normal
                glBindBuffer(GL_ARRAY_BUFFER,SVboId[1]);
                glNormalPointer(GL_FLOAT, 0, 0);

                //Color
                glBindBuffer(GL_ARRAY_BUFFER,SVboId[2]);
                glColorPointer(3,GL_FLOAT, 0, 0);

                //---------------------------------Draw---------------------------------------------------//

                //TOP
                for(int i=0; i<SLICE;i++){
                    glDrawRangeElements(GL_TRIANGLES, point, point+2, 3, GL_UNSIGNED_INT, indices_top+i*3);
                    point+=3;
                }

                //BOTTOM
                point=0;
                for(int i=0; i<SLICE;i++){
                    glDrawRangeElements(GL_TRIANGLES, point, point+2, 3, GL_UNSIGNED_INT, indices_bottom+i*3);
                    point+=3;
                }


                //↓May be wrong ********************************************************************************//
                //SIDE  
                point=0;
                for(int i=0; i< (SLICE*(STACK-2));i++){
                    glDrawRangeElements(GL_QUADS, point, point+3, 4, GL_UNSIGNED_INT, indices_side+i*4);
                    point+=4;
                }
                //↑May be wrong ********************************************************************************//

                //---------------------------------Draw---------------------------------------------------//

                //Disable
                glDisableClientState(GL_COLOR_ARRAY);
                glDisableClientState(GL_NORMAL_ARRAY);
                glDisableClientState(GL_VERTEX_ARRAY);

            }

            void display(void)
            {
             glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
             glViewport(0,0,WIDTH,HEIGHT);
             glMatrixMode(GL_PROJECTION);
             glLoadIdentity();
             gluPerspective(30.0, (double)WIDTH / (double)HEIGHT, 1.0, 1000.0);
             glMatrixMode(GL_MODELVIEW);
             glLoadIdentity();
             gluLookAt(5.0, 5.0,5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);

             glRotatef(angle,0.0f,1.0f,0.0f);

             DrawSphereVBO();

             glutSwapBuffers();
            }
            void idle(void)
            {
             glutPostRedisplay();
             angle+=0.2f;
            }
            void Init(){
             glewInit();
             glClearColor(1.0, 1.0, 1.0, 1.0);
             glEnable(GL_DEPTH_TEST);
             glColorMaterial(GL_FRONT,GL_AMBIENT_AND_DIFFUSE);
             glEnable(GL_COLOR_MATERIAL);
             glEnable(GL_LIGHT0);
             glEnable(GL_LIGHTING);
             glEnable(GL_NORMALIZE);


             SLICE = 5;
             STACK = 5;
             Shere_dma(1,SLICE,STACK);      //MemoryAllocate
             setSphereData(1,SLICE,STACK);  //InputData

            }

            int main(int argc, char *argv[])
            {
             glutInitWindowPosition(100, 100);
             glutInitWindowSize(WIDTH, HEIGHT);
             glutInit(&argc, argv);
             glutCreateWindow("VBO");
             glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
             glutDisplayFunc(display);
             glutIdleFunc(idle);
             Init();
             glutMainLoop();
             return 0;
            }

我参考这段代码。

        void drawSphere(double radius, int nSlice, int nStack)
        {
            int i, j;
            double phi; //
            double theta; //long
            float p[31][31][3]; //Vertex
            float *p1,*p2,*p3,*p4;

            if(nSlice > 30) nSlice = 30;
            if(nStack > 30) nStack = 30;

            //Vertex
            for(i = 0;i <= nSlice;i++)
            {   
                phi = 2.0 * M_PI * (double)i / (double)nSlice;
                for(j = 0;j <= nStack;j++)
                {   
                    theta = M_PI * (double)j / (double)nStack;
                    p[i][j][0] = (float)(radius * sin(theta) * cos(phi));//x
                    p[i][j][1] = (float)(radius * sin(theta) * sin(phi));//y
                    p[i][j][2] = (float)(radius * cos(theta));           //z
                }
            }

            //Top(j=0)
            for(i = 0;i < nSlice; i++)
            {
                p1 = p[i][0];     p2 = p[i][1];
                p3 = p[i+1][1]; 
                glBegin(GL_TRIANGLES);
                    glNormal3fv(p1); glVertex3fv(p1);
                    glNormal3fv(p2); glVertex3fv(p2);
                    glNormal3fv(p3); glVertex3fv(p3);
                glEnd();
            }
            //Bottom
            j=nStack-1;
            for(i = 0;i < nSlice; i++)
            {
                p1 = p[i][j];     p2 = p[i][j+1];
                p3 = p[i+1][j]; 
                glBegin(GL_TRIANGLES);
                    glNormal3fv(p1); glVertex3fv(p1);
                    glNormal3fv(p2); glVertex3fv(p2);
                    glNormal3fv(p3); glVertex3fv(p3);
                glEnd();
            }

            for(i = 0;i < nSlice;i++){
                for(j = 1;j < nStack-1; j++)
                {
                    p1 = p[i][j];     p2 = p[i][j+1];
                    p3 = p[i+1][j+1]; p4 = p[i+1][j];
                    glBegin(GL_QUADS);
                        glNormal3fv(p1); glVertex3fv(p1);
                        glNormal3fv(p2); glVertex3fv(p2);
                        glNormal3fv(p3); glVertex3fv(p3);
                        glNormal3fv(p4); glVertex3fv(p4);
                    glEnd();
                }
            }
        }

2 个答案:

答案 0 :(得分:2)

我已经编写了一个关于生成球体网格的教程 - 它没有附带源代码,但描述了该过程并引导您完成了您将遇到的问题。您可以在以下网址找到该教程:http://sol.gfxile.net/sphere/index.html

答案 1 :(得分:0)

我建议使用球面坐标,使用两个角度phi(仰角)和θ(周围)或使用球体方程:

x2 + y2 + z2 = r2
你把其中一个值保持不变并稍后增加,因为你在第二个值中替换值来找到第三个值。