FPS camera rotating by itself. QT 4.8 + OpenGL + C++ -
i'm trying port height map visualization program written on c++, sfml qt, can shown on widget , controlled gui elements.
the problem when start application, camera starts roll around center fast(actually, looks terrain mesh flying around camera, earth around sun :), without actions side(e.g moving mouse, pressing buttons).
camera should move forward, back, left, right when press w,a,s,d , around when move mouse(just typical fps camera behavior).
i think problem in program's main loop, because it's no standard while(true){ //do something// }
approach in qt, , it's little confusing.
here's code:
oglwidget class(here i'm drawing stuff. problem somewhere here think) :
class oglwidget : public qglwidget { q_object public: oglwidget(qwidget *parent = 0); ~oglwidget(void); public: void paintgl(); void initializegl(); void resizegl(); public: void updatecamera(); public slots: void mainloop(); protected: void keypressevent(qkeyevent *e); void keyreleaseevent(qkeyevent *e); private: terrain _terrain; camera _camera; private: int _keypressed; qtimer _timer; qelapsedtimer _elapsedtimer; float _simulationtime; float _fps; }; oglwidget::oglwidget(qwidget *parent) : qglwidget(parent) { _terrain.loadheightmap("normalheightmap256_2.png"); _camera.setscreendimension(this->width(), this->height()); //setting vertical sync qglformat frmt; frmt.setswapinterval(1); setformat(frmt); setmousetracking(true); setfocus(); _simulationtime = 0; _fps = 1.f / 60.f; connect(&_timer, signal(timeout()), this, slot(mainloop())); _timer.start(); _elapsedtimer.start(); } oglwidget::~oglwidget(void) { } void oglwidget::mainloop() { _simulationtime += _elapsedtimer.elapsed(); _elapsedtimer.restart(); while(_simulationtime > _fps) { _simulationtime -= _fps; updatecamera(); } updategl(); } void oglwidget::updatecamera() { qpoint p = mapfromglobal(qcursor::pos()); _camera.computematrices(p.x(), p.y(), _fps, _keypressed); glm::mat4 viewmatrix = _camera.getviewmatrix(); glm::mat4 projectionmatrix = _camera.getprojectionmatrix(); glm::mat4 modelmatrix = glm::mat4(1.0); _terrain.setmvp(projectionmatrix * viewmatrix * modelmatrix); qpoint center = maptoglobal(qpoint(this->width() / 2, this->height() / 2)); qcursor::setpos(center); } void oglwidget::initializegl() { glewexperimental = gl_true; if (glewinit() != glew_ok) { return; } glviewport(0, 0, this->width(), this->height()); _terrain.init(); } void oglwidget::paintgl() { _terrain.draw(); } void oglwidget::resizegl() { glviewport(0, 0, this->width(), this->height()); } void oglwidget::keypressevent(qkeyevent *e) { switch(e->key()) { case qt::key::key_escape: exit(0); break; case qt::key::key_w: _keypressed = key::key_pressed_up; break; case qt::key::key_s: _keypressed = key::key_pressed_down; break; case qt::key::key_a: _keypressed = key::key_pressed_left; break; case qt::key::key_d: _keypressed = key::key_pressed_right; break; } } void oglwidget::keyreleaseevent(qkeyevent *e) { if(e->key() == qt::key::key_w || e->key() == qt::key::key_s || e->key() == qt::key::key_a || e->key() == qt::key::key_d) _keypressed = key_released; }
i'm absolutely sure terrain , camera classes working correct, because haven't changed code since sfml project(except of using qimage instead of sf::image, it's working correct too)
*camera main algorithm: *
void camera::computematrices(int mousexpos, int mouseypos, float deltatime, int keypressed) { _horizontalangle += _mousespeed * deltatime * float(_screenwidth / 2 - mousexpos); _verticalangle += _mousespeed * deltatime * float(_screenheight / 2 - mouseypos); _direction = glm::vec3 ( cos(_verticalangle) * sin(_horizontalangle), sin(_verticalangle), cos(_verticalangle) * cos(_horizontalangle) ); glm::vec3 right = glm::vec3 ( sin(_horizontalangle - 3.14f/2.0f), 0, cos(_horizontalangle - 3.14f/2.0f) ); glm::vec3 = glm::cross( right, _direction ); switch(keypressed) { case key::key_pressed_up: _position += _direction * deltatime * _speed; break; case key::key_pressed_down: _position -= _direction * deltatime * _speed; break; case key::key_pressed_left: _position -= right * deltatime * _speed; break; case key::key_pressed_right: _position += right * deltatime * _speed; break; case key::key_released: break; } _projectionmatrix = glm::perspective(_initialfov, 4.0f / 3.0f, 0.1f, 1000.0f); _viewmatrix = glm::lookat ( _position, // camera here _position+_direction, // , looks here : @ same position, plus "direction" // head (set 0,-1,0 upside-down) ); }
help me fix issue.
ok, figured out problem spinning camera. cause of hardcoded aspect ratio in camera::computematrices
, , used resolution of widget doesn't match it:
_projectionmatrix = glm::perspective ( _initialfov, 4.0f / 3.0f, //here 0.1f, 1000.0f );
i changed 4.0f / 3.0f
on (float)_screenwidth / (float)_screenheight
didn't too.
so changed resolution of widget 800 x 600
, helped.
the new problem it works on 4/3 dimensions(e.g 800x600
, 1024x768
).
Comments
Post a Comment