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实现立体显示_第1张图片

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

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

 

代码:

/* * @(#)$Id: SteroShow.cpp [4/24/2008 RenYaFei] [email protected] $ * @(#)基于OpenGL的立体显示实现 * Author: Dizuo.Hangzhou. * All Rights Reserved. */ #include #include 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; }

相关立体显示链接:http://local.wasp.uwa.edu.au/~pbourke/projection/stereorender/

你可能感兴趣的:(OpenGL,OpenGL技术专栏)