球体逼近程序中用户自定义归一化函数的奥秘

Posted

技术标签:

【中文标题】球体逼近程序中用户自定义归一化函数的奥秘【英文标题】:The mystery of user defined normalize function in sphere approximation program 【发布时间】:2015-04-30 15:36:51 【问题描述】:

下面的程序使用 normalize 函数将四面体转换为半球体。但是在 normalize 函数中没有调用 OpenGL 函数。只有少数变量的值被改变,甚至没有传递给其他函数。这个函数是如何正常化的?

    #include<stdio.h>
    #include<GL/glut.h>
    #include<math.h>
    GLfloat v[4][3]=0.0,0.0,1.0,0.0,1.0,0.0,-1.0,-0.5,0.0,1.0,-0.5,0.0;
    int n;
    GLfloat theta[3]=0,0,0;
    int axis=2;

    void normalize(GLfloat *pt)
    
        double d=0;
        int i;
        for(i=0;i<3;i++)
            d+=pt[i]*pt[i];
        d=sqrt(d);
        if(d>0)
            for(i=0;i<3;i++)
                pt[i]/=d;
    
    void triangle(GLfloat* a,GLfloat* b,GLfloat* c)
    
    //  glBegin(GL_POLYGON);
        glBegin(GL_LINE_LOOP);
         glVertex3fv(a);
         glVertex3fv(b);
         glVertex3fv(c);
        glEnd( );
    

    void divide_triangle(GLfloat* a,GLfloat* b,GLfloat* c,int m)
    
        GLfloat v1[3],v2[3],v3[3];
        int j;

        if(m>0)
        
            for(j=0;j<3;j++)
            
                v1[j]=(a[j]+b[j])/2;
                v2[j]=(a[j]+c[j])/2;
                v3[j]=(c[j]+b[j])/2;
            

            normalize(v1);         // normalize function called from here
            normalize(v2);
            normalize(v3);

            divide_triangle(a,v1,v2,m-1);
            divide_triangle(c,v2,v3,m-1);
            divide_triangle(b,v3,v1,m-1);
            divide_triangle(v1,v2,v3,m-1);
        
        else
            triangle(a,b,c);
    

    void tetrahedron(int m)
    
    //  glColor3f(0,1,0);                       // green
    //  divide_triangle(v[3],v[2],v[1],m);                      // bottom face of semi-sphere
        glColor3f(1,0,0);                       // red
        divide_triangle(v[0],v[1],v[2],m);
        glColor3f(0,0,1);                       // blue
        divide_triangle(v[0],v[3],v[1],m);
        glColor3f(0,0,0);                       // black
        divide_triangle(v[0],v[2],v[3],m);
    
    void spin()
    
        theta[axis]=theta[axis]+0.05;
        if(theta[axis]>0.06)
            theta[axis]=0;
        glutPostRedisplay();
    
    void mouse(int btn,int state, int x,int y)
    
        if(btn==GLUT_LEFT_BUTTON&&state==GLUT_DOWN)
            axis=0;
        if(btn==GLUT_RIGHT_BUTTON&&state==GLUT_DOWN)
            axis=1;
        if(btn==GLUT_MIDDLE_BUTTON&&state==GLUT_DOWN)
            axis=2;
    

    void display()
    
        glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
        glEnable(GL_DEPTH_TEST);
        glRotatef(theta[0],1,0,0);   // x-axis spin
        glRotatef(theta[1],0,1,0);   // y-axis spin
        glRotatef(theta[2],0,0,1);   // z-axis spin

        tetrahedron(n);
        glFlush( );
    

    void myinit( )
    
        glClearColor(1,1,1,1);
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity( );
        glOrtho(-2,2,-2,2,-2,2);
        glMatrixMode(GL_MODELVIEW);
    

    void main()
    
        printf("No of divisions : ");
        scanf("%d",&n);
        glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB|GLUT_DEPTH);
        glutInitWindowSize(500,500);
        glutCreateWindow("3D SEMI SPHERE APPROXIMATION BY SIERPINSKI GASKET ");
        glutDisplayFunc(display);
        glutIdleFunc(spin);
        glutMouseFunc(mouse);
        myinit( );
        glutMainLoop( );
    

【问题讨论】:

【参考方案1】:

程序有自己的规范化功能。通过找到每条边的中点,将每个三角形面递归地划分为四个大小相等的较小三角形。这些中点位于球体表面的错误位置,因此使用归一化函数将每个插值点从球体中心的半径与现有点的半径相等。递归越深,越接近球体。

我不知道你为什么觉得normalize 函数是个谜。这是缩放三个分量以使其大小为 1(除非全部为 0)的一种完全正常(请原谅双关语)的方式。

递归函数divide_triangle 在最后一行triangle(a,b,c); 中将每个子三角形传递给openGL,此时已达到递归深度限制。在该深度以下,三角形被分割。在那个深度,它们被传递给图形引擎。

【讨论】:

我的问题不是为什么要使用 normalize 函数。我问的问题是,该功能实际上是如何工作的?由于上面的 normalize 函数中没有 OpenGL 函数,它是如何控制三角形的呢? OpenGL 没有垄断地位。该函数通过计算幅度来工作,即向量的三个分量中每个分量的平方和的平方根,然后缩放这些分量中的每一个以使幅度为 1。这就是归一化的工作原理。跨度> @VarunSharma 我为答案添加了更多解释。 感谢您的解释,但它没有回答我的问题。在上面的 normalize(return type void) 函数中,它正在执行计算,但它没有将这些值传递给任何函数。那么计算值(在数组 pt 中)在哪里使用? 向量作为指针传递,并直接修改它们。如果没有达到递归限制,则通过插值创建三个新顶点。每个顶点是一个数组或 x-y-z 坐标。 normalize 函数调整这些值,使向量长度为​​1。然后将 4 个新三角形中的每一个传递给递归。如果达到限制,三角形将通过triangle 传递给openGL 函数。如果不是,则创建另外四个三角形。我不知道我能说清楚多少。

以上是关于球体逼近程序中用户自定义归一化函数的奥秘的主要内容,如果未能解决你的问题,请参考以下文章

matlab程序的归一化问题

matlab中怎样将矩阵归一化处理?

谁能帮我用matlab归一化一组数据,需要运行结果,谢谢

怎样用matlab进行列向量归一化?

matlab归一化和反归一化函数——mapminmax

matlab中啥叫归一化坐标