那些曾经的花儿
好静啊,我们的夜~
 

Cg Tutorial》的第四章介绍了场景转换的一些基本概念,并就此给出了一个程序例子,演示了在Cg顶点程序中执行从模型空间到剪切空间的转换。由于顶点程序的模型视点投影距阵参数是uniform类型,因此是通过在应用程序中先手动计算各矩阵(包括平移、旋转、视点以及投影距阵),然后按照转换空间的顺序相乘,最后在传递给顶点程序的顺序来完成的。程序实现时,完全是通过传递参数,然后自己来构造相应的矩阵,这种办法虽然可行,但必须要对各种矩阵的构造原理十分的了解。考虑到OpenGL中,可以使用状态函数glGetFloatv来获取指定的矩阵,因此可以先执行相应的操作,让OpenGL来计算最终的合成矩阵,而我们则可以直接通过状态获取函数来得到最终的矩阵。下面就是基于这种方法的实现:

void getModelViewProjMatrix(float outModelViewProjMatix[16],

                     float fovy,float aspect,float zNear,float ZFar,     /* The Projection Parameter*/

                     double eyex,double eyey,double eyez,                 /* The Eye Position */

                     double centerx,double centery,double centerz,   /* The Center Position*/

                     double upx,double upy,double upz,                    /* The Up Vector*/

                     void (*transformOp)(void)  /* The transform Operation*/)

{

       float projMatrix[16];

       // Get the projection matrix

       getProjectMatrix(projMatrix,fovy,aspect,zNear,ZFar);

       // ModelMatrix = Translate * Rotation * ...

       // ModelViewMatrix = ViewMatrix * ModelMatrix

       // ModelViewProjectionMatrix = ProjectionMatrix * ModelViewMatrix

       // In OpenGL,the order of matrix multiplication is REVERSE to the order of function call

       glMatrixMode(GL_MODELVIEW);

       glPushMatrix();

              glLoadIdentity();

              // Multiple the modelview matrix by projection matrix

              glMultMatrixf(projMatrix);

              //do the transformation operation and camera setting

              gluLookAt(eyex,eyey,eyez,centerx,centery,centerz,upx,upy,upz);

              transformOp();

              //get the modelview matrix

              glGetFloatv(GL_MODELVIEW_MATRIX,outModelViewProjMatix);

       glPopMatrix();

}

此函数用来获取模型视点矩阵与投影矩阵相乘的结果,这个结果就是传递给顶点程序的值。其中(fovy,aspect,zNear,ZFar)调用gluPerspectiv()函数,获取投影矩阵;(eyex, eyey,eyez

centerx,centery,centerz, upx,upy,upz)则用来调用gluLookAt()函数,设置视点矩阵。由于平移、旋转的操作顺序和次数不定,因此在这里是通过函数指针的形式指定。在这个函数中指定的具体的平移和旋转操作。

使用这种方法时,需要考虑到两个问题:

1、 从模型空间到剪切空间的转换顺序:

        

2、 OpenGL中,矩阵相乘的顺序与函数调用的顺序相反:

例如:

               glMatrixMode(GL_MODELVIEW);

               glLoadIdentity();

               glMultMatrixf(N);

               glMultMatrixf(M);

               glMultMatrixf(L);

               glBegin(GL_POINTs);

                      glVertex3f(v);

               glEnd();

在上述代码中,当前矩阵依次为INNMNML。变换后的顶点为NMLv

3、 OpenGL中,使用一维数组存储矩阵时,默认的方式是按列存储的,因此在使用Cg程序时,需要使用cgSetMatrixParameter{f,d}c来传递矩阵参数。

在所有参数设置相同时,试验的结果与书上的结果有一些出入,主要体现在物体在空间的位置不同。为了验证真实的情况,我在只使用OpenGL,不是用Cg程序的条件下绘制,绘制结果同我的一样。下面是在这三种方法下的最终结果:从左到右依次为使用上面方法渲染结果、使用纯OpenGL渲染结果以及书中自带结果
                                     

 不知道这是我的方法有问题,还是书上程序有问题。

posted on 2007-09-14 14:58  soaroc  阅读(1342)  评论(5编辑  收藏  举报