opengl构造一个灵活的camera

来源:互联网 发布:网络购物的优点 编辑:程序博客网 时间:2024/05/17 03:45

dx龙书有一章的题目就构建一个灵活的camera.

看了 opengl 以后,对视口变换,投影变换,模型视图变换 的顺序,关系,理解得更清晰了。

其中,视图变换相当于模型变换的逆向变换, glLookAt() 这类直接操作camera的函数,只是封装了一些逆向移动的各种 translate,rotate,scale而已。

于是自己写了一个 camera 类。

其中不足是暂时不会用 opengl 的 api 来直接计算。比如一个 vector 乘以 一个matrix,结果再保存到这个vector中,dx是有 api 的 ,我猜 opengl 可能也有。

只是自己暂时没有找到。 我也没有自己动手写这样一个函数 ,免得将来找到了,发现自己犯傻做了太多的无用功。

 

这个例子,纯属是为了更进一步理解 model-view 变换而写的,重点在 camera.h 和 camera.cpp,

用 camera类的 work() 函数,来取代 glLookAt() 函数。

 

贴出来做个笔记。

 

main.cpp

#include "GLFrame.h"#include <string>using namespace std;const int WINDOW_POS_X = 100;const int WINDOW_POS_Y = 100;const int WINDOW_SIZE_X= 800;const int WINDOW_SIZE_Y = 600;const string WINDOW_NAME = "solar";int main(int arc,char** argv){glutInit( &arc,argv);glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);glutInitWindowPosition( WINDOW_POS_X,WINDOW_POS_Y);glutInitWindowSize(WINDOW_SIZE_X,WINDOW_SIZE_Y);glutCreateWindow( WINDOW_NAME.c_str() );glutDisplayFunc( onPaintGL);glutReshapeFunc( onReshapeGL);//glutTimerFunc(200,onTimerGL,200);glutMouseFunc( onMouseGL);glutKeyboardFunc( onKeyboard );init();glutMainLoop();return 0;}


glFrame.h

#include <GL\glut.h>void init();void onPaintGL();void onReshapeGL(int width,int height);void onMouseGL(int button,int state,int x,int y);void onTimerGL(int value);void onKeyboard(unsigned char key,int x,int y);


logic.cpp

#include "GLFrame.h"#include <iostream>using namespace std;#include "camera.h"int window_width = 0;int window_height = 0;void paintSolar();void paintUI();float cur_revolution_angle = 0.0f;float cur_autobiography_angle = 0.0f;void revolution_earth();void autobiography_earth();//camera logicstatic OGL_CAMERA::Camera g_camera;enum ECameraWorkType{ECWT_OGL_LOOKAT,ECWT_CUSTOM_CAMERA,};ECameraWorkType g_cwt = ECWT_CUSTOM_CAMERA;void init(){glClearColor( 0.0,0.0,0.0,0.0);glShadeModel( GL_FLAT );}void onPaintGL(){glClear( GL_COLOR_BUFFER_BIT );glViewport(0,0,window_width,window_height);glMatrixMode(GL_PROJECTION);glLoadIdentity();gluPerspective(60.0f,(GLfloat)window_width/(GLfloat)window_height,0.1,100);glMatrixMode(GL_MODELVIEW);if( g_cwt == ECWT_OGL_LOOKAT ){glLoadIdentity();gluLookAt(0.0f,0.0f,20.0f,0.0f,0.0f,0.0f,0.0f,1.0f,0.0f);}else if( g_cwt == ECWT_CUSTOM_CAMERA){g_camera.work();}paintSolar();glFlush();}void onReshapeGL(int width,int height){window_width = width;window_height = height;}void onMouseGL(int button,int state,int x,int y){//glutPostRedisplay();}void onKeyboard(unsigned char key,int x,int y){switch(key){case 'c':case 'C':cout << "camera work type changed" << endl;g_cwt==ECWT_OGL_LOOKAT ? g_cwt = ECWT_CUSTOM_CAMERA : g_cwt = ECWT_OGL_LOOKAT; glutPostRedisplay();break;}if( g_cwt == ECWT_CUSTOM_CAMERA ){g_camera.processInput( key );glutPostRedisplay();}}void paintSolar(){glColor3f( 1.0f,0.0f,0.0f);glPushMatrix();{glRotatef(cur_autobiography_angle,0,1,0);glRotatef(90,1,0,0);glutWireSphere(5.0f,10,10);}glPopMatrix();glColor3f( 0.0f,0.0f,1.0f);glPushMatrix();{glRotatef(cur_revolution_angle,0,1,0);glTranslatef(10.0f,0.0f,0.0f);glRotatef(cur_autobiography_angle,0,1,0);glRotatef(90,1,0,0);glutWireSphere(1.0f,10,10);}glPopMatrix();}void revolution_earth(){cur_revolution_angle += 1;cur_revolution_angle = cur_revolution_angle > 360 ? 0 : cur_revolution_angle;}void autobiography_earth(){cur_autobiography_angle += 1.0f;cur_autobiography_angle = cur_autobiography_angle > 360 ? 0 : cur_autobiography_angle;}void onTimerGL(int value){revolution_earth();autobiography_earth();glutPostRedisplay();glutTimerFunc(100,onTimerGL,value);}


 

 camera.h

#ifndefOGL_CAMERA_H#defineOGL_CAMERA_H#include <GL\glut.h>namespace OGL_CAMERA{class Camera{protected:GLdouble _pos[3];GLdouble _pitch;GLdouble _roll;GLdouble _yaw;//GLdouble _up[3];//GLdouble _right[3];//GLdouble _look[3];protected:void doPitch( GLdouble angle );void doRoll( GLdouble angle );void doYaw( GLdouble angle );void doWalk( GLdouble dis );void doStrafe( GLdouble dis );void doFly( GLdouble dis );public:Camera();~Camera();void work();void processInput(unsigned char key);};}//namespace OGL_CAMERA#endif//OGL_CAMERA_H

 

camera.cpp

 

#include "camera.h"using namespace OGL_CAMERA;Camera::Camera(){_pos[0] = 0;_pos[1] = 0;_pos[2] = 20;//_up[3] = 0;_up[1] = 1;_up[2] = 0;//_right[0] = 1.0;_right[1] = 0;_right[2] = 0;//_look[0];_look[1] = 0;_look[2] = -1;_pitch = 0;_yaw = 0;_roll = 0;}Camera::~Camera(){}void Camera::processInput(unsigned char key){static GLdouble angle = 5.0;static GLdouble dis = 0.1;switch(key){//pitchcase 'w':case 'W':doPitch(angle);break;case 's':case 'S':doPitch(-angle);break;//yawcase 'a':case 'A':doYaw(angle);break;case 'd':case 'D':doYaw(-angle);break;//rollcase 'q':case 'Q':doRoll(angle);break;case 'e':case 'E':doRoll(-angle);break;//walkcase 'i':case 'I':doWalk(-dis);break;case 'k':case 'K':doWalk(dis);break;//strafecase 'j':case 'J':doStrafe(-dis);break;case 'l':case 'L':doStrafe(dis);break;//flycase 'u':case 'U':doFly(dis);break;case 'o':case 'O':doFly(-dis);break;}}void Camera::doPitch( GLdouble angle ){_pitch += angle;}void Camera::doRoll( GLdouble angle ){_roll += angle;}void Camera::doYaw( GLdouble angle ){_yaw += angle;}void Camera::doWalk( GLdouble dis ){_pos[2] += dis;}void Camera::doStrafe( GLdouble dis ){_pos[0] += dis;}void Camera::doFly( GLdouble dis ){_pos[1] += dis;}void Camera::work(){glLoadIdentity();//gluLookAt(0.0f,0.0f,10.0f,0.0f,0.0f,0.0f,0.0f,1.0f,0.0f);glRotatef( -_pitch,1.0,0.0,0.0);glRotatef( -_yaw,0.0,1.0,0.0);glRotatef( -_roll,0.0,0.0,1.0);glTranslatef(-_pos[0],-_pos[1],-_pos[2]);}



 

 

原创粉丝点击