OpenGL实现立体显示

立体显示原理:设没有立体显示的模型视图矩阵ModelView为Mv,投影矩阵为Mp,则、物体空间的任何一点为P,则变换到屏幕坐标P*=Mp×Mv×P;注意前面已经说过opengl里面坐标列优先,所以矩阵都是右乘。

左眼和右眼的变换都是由中间的变换矩阵变换而来,则立体显示中左眼的变换矩阵公式为:

P(L)*=Ms(L) × Mp(L) × Mt(L) × Mv(L) × P;

右眼的矩阵变换公式为:

P(R)*=Ms(R) × Mp(R) × Mt(R) × Mv(R) × P;

其中Ms,Mt是立体显示需要而增加的变换。

程序里面有几个参数,现实世界眼睛到屏幕的距离Fd,两眼之间的距离Sd,比例尺R,如图:

OpenGL实现立体显示

如上图:没有立体显示,视点位于就是中间的蓝色位置,立体显示就是将左眼(红色),右眼(绿色)的视图分开绘制。

程序中左眼用红色去画,右眼同时用绿色和蓝色绘制。

代码:

/*
 * @(#)$Id: SteroShow.cpp [4/24/2008 RenYaFei] [email protected] $
 * @(#)基于OpenGL的立体显示实现
 * Author: Dizuo.Hangzhou.
 * All Rights Reserved.
 */
#include <GL/glut.h>
#include <math.h>
void init(void)
{
    GLfloat mat_diffuse[] = { 1.0, 1.0, 0.0 };
    GLfloat mat_specular[] = {0.8, 0.8, 0.0, 1.0};
    GLfloat mat_shininess[] = { 300. };
    GLfloat light_position[] = { 1.0, 1.0, 1.0, 0.0 };
    GLfloat light_diffuse[] = { 1.0, 1.0, 0.0 };
    GLfloat light_ambient[] = {0.7, 0.2, 0.2, 1.0};

    glClearColor (0.0, 0.0, 0.0, 0.0);
    glShadeModel (GL_SMOOTH);

    glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
    glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
    glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
    glLightfv(GL_LIGHT0, GL_POSITION, light_position);
    glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);
    glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);

    glEnable(GL_LIGHTING);
    glEnable(GL_LIGHT0);
    glEnable(GL_DEPTH_TEST);
}
/**//*----------------------------------------------------------------------------
*    初始化参数   
*/
GLfloat PI=3.1415926;
GLfloat Fd=5.0;            //fusion distance
GLfloat RealScreenToEyeDistance=1.0;
GLfloat R=Fd/RealScreenToEyeDistance;    //比例尺 R =  Fd / RealScreenToEyeDistance
GLfloat Sd=0.05;                        //两眼之间的距离
GLfloat aspect=1.0;                        //gluLookAt函数里面的参数
GLfloat fovy=60.0;                        //张角
GLfloat f=1/tan( (fovy*PI)/(2*180) );    //f=ctg(fovy/2);

//列优先的矩阵模型视图矩阵,投影矩阵
GLfloat LeftModelViewMatrix[16]={
    1.0, 0.0, 0.0, 0.0,
    0.0, 1.0, 0.0, 0.0,
    0.0, 0.0, 1.0, 0.0,
    Sd*R/2.0, 0.0, 0.0, 1.0
};

GLfloat LeftProjectMatrix[16]={
    1.0, 0.0, 0.0, 0.0,
    0.0, 1.0, 0.0, 0.0,
    0.0, 0.0, 1.0, 0.0,
    -(Sd*f) / (2.0*Fd*aspect), 0.0, 0.0, 1.0   
};

GLfloat RightModelViewMatrix[16]={
    1.0, 0.0, 0.0, 0.0,
    0.0, 1.0, 0.0, 0.0,
    0.0, 0.0, 1.0, 0.0,
    -Sd*R/2.0, 0.0, 0.0, 1.0
};

GLfloat RightProjectMatrix[16]={
    1.0, 0.0, 0.0, 0.0,
    0.0, 1.0, 0.0, 0.0,
    0.0, 0.0, 1.0, 0.0,
    (Sd*f) / (2.0*Fd*aspect), 0.0, 0.0, 1.0   
};

//for the use of rotating
static GLfloat spin = 0.0;

void display(void)
{
    GLfloat matrix[16]={0.};

    glColorMask(1.0, 1.0,1.0,1.0);
    glClearColor(0.0,0.0,0.0,1.0);
    glClearDepth(1.0);

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glColor3f(1.0, 1.0, 1.0);

    //---------------------------------------------------------------------------------------------
    //Left Viewport
    glMatrixMode(GL_PROJECTION);
    glPushMatrix();
    glGetFloatv(GL_PROJECTION_MATRIX, matrix);
    glLoadIdentity();
    glMultMatrixf(LeftProjectMatrix);
    glMultMatrixf(matrix);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    glTranslated(0.0, 0.0, -Fd);
    glPushMatrix();   
    {
        glGetFloatv(GL_MODELVIEW_MATRIX, matrix);
        glLoadIdentity();
        glMultMatrixf(LeftModelViewMatrix);       
        glMultMatrixf(matrix);                   
        glColorMask(1.0, 0.0, 0.0, 1.0);
        /**//*
        *  物体的坐标Vp
        *  变换到屏幕坐标:Vp'= LeftProjectMatrix×Mp × LeftModelViewMatrix×Mv × Mr×Vp
        */
        glPushMatrix();
        {
            glRotatef(spin, 0.0, 1.0, 0.0);                                                              glutSolidTeapot(1.0);           
        }
        glPopMatrix();
    }
    glPopMatrix();
    glMatrixMode(GL_PROJECTION);
    glPopMatrix();
    glFlush();   

    //---------------------------------------------------------------------------------------------
    //Right Viewport
    glMatrixMode(GL_PROJECTION);
    glPushMatrix();
    glGetFloatv(GL_PROJECTION_MATRIX, matrix);
    glLoadIdentity();
    glMultMatrixf(RightProjectMatrix);
    glMultMatrixf(matrix);

    glMatrixMode(GL_MODELVIEW);   
    glPushMatrix();
    {
        glGetFloatv(GL_MODELVIEW_MATRIX, matrix);
        glLoadIdentity();
        glMultMatrixf(RightModelViewMatrix);
        glMultMatrixf(matrix);
           
        glColorMask(0.0, 1.0, 1.0, 1.0);
        glClearDepth(1.0);
        glClear(GL_DEPTH_BUFFER_BIT);
        /**//*
        *  物体的坐标Vp
        *    变换到屏幕坐标:Vp'= RightProjectMatrix×Mp× RightModelViewMatrix×Mv × Mr×Vp
        */
        glPushMatrix();
        {
            glRotatef(spin, 0.0, 1.0, 0.0);
            glutSolidTeapot(1.0);
            //glutSolidSphere(1.0, 20, 5);
        }
    }
    glPopMatrix();

    glMatrixMode(GL_PROJECTION);
    glPopMatrix();
    glFlush ();

    glutSwapBuffers();
}

void reshape (int w, int h)
{
    glViewport (0, 0, (GLsizei) w, (GLsizei) h);
    glMatrixMode (GL_PROJECTION);
    glLoadIdentity();
    //投影矩阵:Mp
    gluPerspective(fovy, (GLfloat)w/(GLfloat)h, 1.0, 20.0);   
}
void spinDisplay(void)
{
    spin = spin + 1.0;
    if (spin > 360.0)
        spin = spin - 360.0;
    glutPostRedisplay();
}

int main(int argc, char** argv)
{
    glutInit(&argc, argv);
    glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
    glutInitWindowSize (500, 500);
    glutInitWindowPosition (100, 100);
    glutCreateWindow (argv[0]);
    init ();
    glutDisplayFunc(display);
    glutReshapeFunc(reshape);
    glutIdleFunc(spinDisplay);
    glutMainLoop();
    return 0;
}

相关阅读

相关推荐