In my program I am trying to select an object on right mouse click event using glReadPixels method. Window for rendering is created using wxWidgets (by extending wxFrame and wxGLCanvas). However, I am getting wrong values. He is tutorial that I used
I was suggested to use this approach as it seems faster and easier than ray casting.
My code:
#include "MyGLCanvas.h"
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
BEGIN_EVENT_TABLE(MyGLCanvas, wxGLCanvas)
EVT_PAINT(MyGLCanvas::paintEvent)
EVT_CHAR(MyGLCanvas::onKeyPressed)
EVT_LEFT_DOWN(MyGLCanvas::onLeftMouseDown)
EVT_LEFT_UP(MyGLCanvas::onLeftMouseUp)
EVT_RIGHT_DOWN(MyGLCanvas::onRightMouseDown)
EVT_RIGHT_UP(MyGLCanvas::onRightMouseUp)
EVT_KEY_UP(MyGLCanvas::onKeyUp)
EVT_MOUSEWHEEL(MyGLCanvas::onMouseWheel)
END_EVENT_TABLE()
MyGLCanvas::MyGLCanvas(wxFrame* parent, GLuint width, GLuint height) : wxGLCanvas(parent, wxID_ANY, 0, wxDefaultPosition, wxSize(width, height), 0, wxT("GLCanvas"), wxNullPalette) // parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0, wxT("GLCanvas")
{
windowHeight = height;
windowWidth = width;
this->WarpPointer(windowWidth / 2, windowHeight / 2); // places mouse in the middle of screen
fpsCamera = new FPSCamera(glm::vec3(0.0f, 0.0f, 5.0f));
renderTimer = new RenderTimer(this);
renderTimer->Start();
glContext = new wxGLContext(this, NULL);
SetCurrent(*glContext);
init();
}
MyGLCanvas::~MyGLCanvas()
{
glDeleteProgram(shaderProgram);
delete mesh;
delete renderTimer;
delete glContext;
delete fpsCamera;
}
int MyGLCanvas::init()
{
glewExperimental = GL_TRUE;
if (glewInit() != GLEW_OK)
{
std::cerr << "Glew initialization failed " << std::endl;
return -1;
}
glEnable(GL_DEPTH_TEST);
glViewport(0, 0, windowWidth, windowHeight);
mesh = new Mesh();
mesh->loadOBJ();
return 0;
}
void MyGLCanvas::paintEvent(wxPaintEvent& evt)
{
wxPaintDC dc(this);
draw(dc);
}
void MyGLCanvas::paintNow()
{
wxClientDC dc(this);
draw(dc);
}
void MyGLCanvas::onLeftMouseDown(wxMouseEvent& event)
{
xLastPosition = wxGetMousePosition().x;
yLastPosition = wxGetMousePosition().y;
Bind(wxEVT_MOTION, &MyGLCanvas::onMouseMove, this, wxID_ANY);
}
void MyGLCanvas::onLeftMouseUp(wxMouseEvent& event)
{
Unbind(wxEVT_MOTION, &MyGLCanvas::onMouseMove, this, wxID_ANY);
}
void MyGLCanvas::onRightMouseDown(wxMouseEvent& event)
{
GLuint index;
glReadPixels(wxGetMousePosition().x, windowHeight - wxGetMousePosition().y - 1, 1, 1, GL_STENCIL_INDEX, GL_UNSIGNED_INT, &index);
wxMessageOutputDebug().Printf("index = %i", index);
}
void MyGLCanvas::onRightMouseUp(wxMouseEvent& event)
{
wxMessageOutputDebug().Printf("Right mouse up!!");
}
void MyGLCanvas::onMouseMove(wxMouseEvent& event)
{
if (event.Entering())
{
SetFocus();
}
GLdouble dxMouse, dyMouse;
dxMouse = xLastPosition - wxGetMousePosition().x;
dyMouse = yLastPosition - wxGetMousePosition().y;
xLastPosition = wxGetMousePosition().x;
yLastPosition = wxGetMousePosition().y;
fpsCamera->rotate((GLfloat)dxMouse * MOUSE_SENSITIVITY, (GLfloat)dyMouse * MOUSE_SENSITIVITY);
event.Skip();
}
void MyGLCanvas::onKeyPressed(wxKeyEvent& event)
{
switch (event.GetKeyCode())
{
case (119): // lower case w
{
fpsCamera->move(mouseSpeed * fpsCamera->getLook());
mouseSpeed += 0.1f;
break;
}
case (97): // lower case a
{
fpsCamera->move(mouseSpeed * -fpsCamera->getRight());
mouseSpeed += 0.1f;
break;
}
case (115): // lower case s
{
fpsCamera->move(mouseSpeed * -fpsCamera->getLook());
mouseSpeed += 0.1f;
break;
}
case (100): // lower case d
{
fpsCamera->move(mouseSpeed * fpsCamera->getRight());
mouseSpeed += 0.1f;
break;
}
case (120): // lower case x
{
fpsCamera->move(mouseSpeed * -fpsCamera->getUp());
mouseSpeed += 0.1f;
break;
}
case (121): // lower case y
{
fpsCamera->move(mouseSpeed * fpsCamera->getUp());
mouseSpeed += 0.1f;
break;
}
default:
break;
}
}
void MyGLCanvas::onKeyUp(wxKeyEvent& event)
{
mouseSpeed = 0.1;
}
void MyGLCanvas::onMouseWheel(wxMouseEvent& event)
{
GLdouble fov;
if (event.GetWheelRotation() > 0)
{
fov = fpsCamera->getFOV() + ZOOM_SENSITIVITY;
}
else
{
fov = fpsCamera->getFOV() - ZOOM_SENSITIVITY;
}
fov = glm::clamp(fov, 1.0, 120.0);
fpsCamera->setFOV((GLfloat)fov);
}
void MyGLCanvas::draw(wxDC& dc)
{
glm::vec3 modelPos = glm::vec3(0.0f, -10.0f, -50.0f);
glm::mat4 model, view;
model = glm::translate(model, modelPos);
view = fpsCamera->getViewMatrix();
projection = glm::perspective(glm::radians(fpsCamera->getFOV()), (float)(windowWidth / windowHeight), 0.1f, 100.0f);
glm::mat4 trans;
// trans = glm::rotate(trans, degree, glm::vec3(0.0f, 1.0f, 0.0f));
trans = glm::rotate(trans, 30.0f, glm::vec3(0.0f, 1.0f, 0.0f));
trans = glm::scale(trans, glm::vec3(0.01, 0.01, 0.01));
ShaderProgram shaderProgram;
shaderProgram.loadShaders("basic.vert", "basic.frag");
glClearStencil(0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
shaderProgram.use();
shaderProgram.setUniform("transform", trans);
shaderProgram.setUniform("model", model);
shaderProgram.setUniform("view", view);
shaderProgram.setUniform("projection", projection);
shaderProgram.setUniform("color", glm::vec3(0.310f, 0.747f, 0.185f));
glEnable(GL_STENCIL_TEST);
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
glStencilFunc(GL_ALWAYS, 1, -1);
mesh->draw();
glDisable(GL_STENCIL_TEST);
//degree += 0.05f;
SwapBuffers();
}
RenderTimer::RenderTimer(MyGLCanvas* canvas) : wxTimer()
{
RenderTimer::m_canvas = canvas;
}
void RenderTimer::Notify()
{
m_canvas->Refresh(false);
};
void RenderTimer::Start()
{
wxTimer::Start();
};
Related
I started working on a github project (a logic gate simulator) with gtkmm and epoxy. I have an optimus laptop with debian buster and nvidia-bumblebee drivers installed and everything works fine except that if I start the program using optirun or primusrun, neither the glArea->queue_render, nor glArea->queue_draw function seems to work. I have to resize the window in order to rerender the glArea widget. Also sometimes when I restart the system and compile the program it won't start with bumblebee at all and outputs the following error:
311-0-no gl implementation is available
It might be something with my system, but optirun and primusrun usually work fine.
Any Idea what might be the cause of this problem?
the renderer class:
#ifndef RENDERER_DATA_H
#define RENDERER_DATA_H
#include <glm/mat4x4.hpp>
#include <glm/vec3.hpp>
#include <glm/vec2.hpp>
struct scene{ //viewport data
glm::mat4 proj;
glm::mat4 view;
glm::mat4 model;
glm::mat4 mvp;
float zoom = 1.0f;
glm::vec2 dim;
glm::vec3 pos = {0, 0, 1.0f};
};
struct pointer{ //mouse data
int button;
int x, y;
};
struct keyboard{ //keyboard data
};
#endif
#ifndef RENDERER_H
#define RENDERER_H
/*
This is the renderer of the viewport
*/
#include "viewport/shader.hpp"
#include "viewport/vertexbuffer.hpp"
#include "viewport/indexbuffer.hpp"
#include "viewport/vertexarray.hpp"
#include "viewport/objects/grid.hpp"
#include <gtkmm-3.0/gtkmm.h>
#include <gtkmm-3.0/gtkmm/glarea.h>
#include <glm/glm.hpp>
//#include <glm/gtx/transform.hpp>
#include <glm/gtc/matrix_transform.hpp>
//#include <gdkmm-3.0/gdkmm/glcontext.h>
//#include <glibmm-2.4/glibmm/refptr.h>
//#include <epoxy/gl.h>
//#include <epoxy/glx.h>
#include <iostream>
class Renderer{
public:
Renderer(Gtk::GLArea*); //constructor connects the following callbacks:
void realize(); //called when widget glArea is created
void unrealize(); //called when widget glArea is destroyed
void resize(int width, int height); //called when the glArea is resized
bool render(const Glib::RefPtr<Gdk::GLContext>&); //called when the viewport should render itself
bool mouse_move(GdkEventMotion* event); //called when both mouse button pressed and mouse moved
bool mouse_scroll(GdkEventScroll* event); //called when the mouse is wheel is rotated
bool button_press(GdkEventButton* button); //called when a button is pressed
bool button_release(GdkEventButton* button); //called when a button is released
private:
Gtk::GLArea* glArea; //pointer to the glArea widget, created in ui object
GLuint vao;
IndexBuffer* ibptr;
VertexBuffer* vbptr;
VertexArray* vaptr;
VertexBufferLayout* vblptr;
Shader* shader_program;
Grid* grid;
pointer mouse; //mouse variable obj
scene viewport; //viewport variable obj
void update_view(); //This function is resposible for paning and zooming the viewport
glm::vec3 mouse_translate(glm::vec3); //translates screen coords to world coords
};
#endif //
implementation:
//#include <ui.hpp>
#include "./renderer.hpp"
Renderer::Renderer(Gtk::GLArea* glarea)
/*:glArea(glarea)*/{
glArea = glarea;
glArea->add_events(Gdk::BUTTON_MOTION_MASK | Gdk::BUTTON1_MOTION_MASK | Gdk::BUTTON2_MOTION_MASK | Gdk::BUTTON3_MOTION_MASK | Gdk::BUTTON_PRESS_MASK | Gdk::POINTER_MOTION_HINT_MASK | Gdk::SCROLL_MASK);
glArea->signal_realize().connect(sigc::mem_fun(*this, &Renderer::realize));
glArea->signal_unrealize().connect(sigc::mem_fun(*this, &Renderer::unrealize), false);
glArea->signal_render().connect(sigc::mem_fun(*this, &Renderer::render), false);
glArea->signal_resize().connect(sigc::mem_fun(*this, &Renderer::resize));
glArea->signal_motion_notify_event().connect(sigc::mem_fun(*this, &Renderer::mouse_move));
glArea->signal_scroll_event().connect(sigc::mem_fun(*this, &Renderer::mouse_scroll));
glArea->signal_button_press_event().connect(sigc::mem_fun(*this, &Renderer::button_press));
glArea->signal_button_release_event().connect(sigc::mem_fun(*this, &Renderer::button_release));
}
void Renderer::realize(){
std::clog<<"realize"<<std::endl;
//glArea->set_required_version(4, 5);
glArea->make_current();
glArea->set_auto_render(true);
std::clog<<"make current"<<std::endl;
//std::clog<<epoxy_gl_version()<<"\n";
//std::clog<<epoxy_glsl_version()<<"\n";
glArea->make_current();
std::cout<<glGetString(GL_VERSION)<<std::endl;
std::cout<<"realize\n";
try{
glArea->throw_if_error();
std::clog<<glGetString(GL_VERSION)<<"\n";
std::clog<<glGetString(GL_VENDOR)<<"\n";
char path[] = "./src/res/shaders";
shader_program = new Shader(path);
shader_program->bind();
//shader_program = Shader::create_shader_program(nullptr);
//glUseProgram(shader_program);
GLfloat pos[] = {
-0.5f, -0.5f, -1,
0.5f, -0.5f, -1,
0.5f, 0.5f, -1,
-0.5f, 0.5f, -1
};
GLuint ind[] = {
0, 1, 2,
2, 3, 0
};
vaptr = new VertexArray();
//glGenVertexArrays(1, &vao);
//glBindVertexArray(vao);
vbptr = new VertexBuffer(pos, 4 * 3 * sizeof(GLfloat));
vblptr = new VertexBufferLayout;
vblptr->add(3, GL_FLOAT);
//vblptr->add(3, GL_FLOAT);
//vblptr->add(2, GL_FLOAT);
vaptr->addBuffer(*vbptr, *vblptr);
//glEnableVertexAttribArray(0);
//glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 3, 0);
ibptr = new IndexBuffer(ind, 6);
//int location = epoxy_glGetUniformLocation(shader_program->get_program(), "u_Color");
//glUniform4f(location, 0.2f, 0.3f, 0.8f, 1.0f);
//glm::vec4 data = {0.2f, 0.3f, 0.8f, 1.0f};
shader_program->set_uniform4f ("u_Color", {0.2f, 0.3f, 0.8f, 1.0f});
//viewport.proj = glm::ortho(-width/height/2, width/height/2, -height/width/2, height/width/2);
//shader_program->set_uniform_mat4f ("mvp", viewport.proj);
//glBindVertexArray(0);
//glUseProgram(0);
//glBindBuffer(GL_ARRAY_BUFFER, 0);
//glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}catch(const Gdk::GLError& gle){
std::cerr << "An error occured making the context current during realize:" << std::endl;
std::cerr << gle.domain() << "-" << gle.code() << "-" << gle.what() << std::endl;
}
grid = new Grid(glm::vec3(-3.0, 0.0, -1.0), glm::vec3(3.0, 0.0, -1.0));
}
void Renderer::unrealize(){
glArea->make_current();
delete vbptr;
delete ibptr;
delete vaptr;
delete vblptr;
delete shader_program;
try
{
glArea->throw_if_error();
}
catch(const Gdk::GLError& gle)
{
std::cerr << "An error occured making the context current during unrealize" << std::endl;
std::cerr << gle.domain() << "-" << gle.code() << "-" << gle.what() << std::endl;
}
}
void Renderer::resize(int width, int height){
viewport.dim.x = width;
viewport.dim.y = height;
}
bool Renderer::render(const Glib::RefPtr<Gdk::GLContext>& context ){
std::clog<<"render\n";
update_view();
//glArea->attach_buffers();
glClear(GL_COLOR_BUFFER_BIT);
grid->draw();
grid->m_shader->set_uniform_mat4f("mvp", viewport.mvp);
grid->draw();
shader_program->bind();
vaptr->bind();
//ibptr->bind();
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr);
glBindVertexArray(0);
glUseProgram(0);
return true;
}
bool Renderer::mouse_move(GdkEventMotion* event){
glm::vec3 diff = mouse_translate(glm::vec3(mouse.x, mouse.y, 0.0)) - mouse_translate(glm::vec3(event->x, event->y, 0.0));
std::clog<<diff.x<<" "<<diff.y<<"\n";
if(mouse.button == 1){
viewport.pos = viewport.pos - diff;
std::clog<<viewport.pos .x<<" "<<viewport.pos.y<<" "<<viewport.pos.z<<"\n";
//glArea->queue_draw();
//glArea->queue_draw();
glArea->queue_render();
//glArea->signal_render();
}
mouse.x = event->x;
mouse.y = event->y;
return true;
}
bool Renderer::mouse_scroll(GdkEventScroll* event){
if(event->direction == GDK_SCROLL_DOWN && viewport.zoom>1){
viewport.zoom = viewport.zoom - 0.1;
}else if(event->direction == GDK_SCROLL_UP && viewport.zoom<10){
viewport.zoom = viewport.zoom + 0.1;
}
glArea->queue_render();
std::clog<<viewport.zoom<<"\n";
return true;
}
bool Renderer::button_press(GdkEventButton* event){
std::clog<<event->button<<"\n";
mouse.button = event->button;
mouse.x = event->x;
mouse.y = event->y;
//if(event->mouse.button == 1){ //left mouse button
//
//}
return true;
}
bool Renderer::button_release(GdkEventButton* button){
mouse.button = 0;
return true;
}
void Renderer::update_view(){
std::clog<<"update view\n";
viewport.view = glm::translate(glm::mat4(1.0f), glm::vec3(viewport.pos.x, -viewport.pos.y, -viewport.pos.z));
viewport.model = glm::translate(glm::mat4(1.0f), glm::vec3( 0, 0, 1.0));
if(viewport.dim.x<viewport.dim.y){
viewport.proj = glm::ortho(-viewport.dim.x/viewport.dim.y/viewport.zoom, viewport.dim.x/viewport.dim.y/viewport.zoom, -1.0f/viewport.zoom, 1.0f/viewport.zoom);
}else{
viewport.proj = glm::ortho(-1.0f/viewport.zoom, 1.0f/viewport.zoom, -viewport.dim.y/viewport.dim.x/viewport.zoom, viewport.dim.y/viewport.dim.x/viewport.zoom);
}
viewport.mvp = viewport.proj * viewport.view * viewport.model;
shader_program->bind();
shader_program->set_uniform_mat4f ("mvp", viewport.mvp);
}
glm::vec3 Renderer::mouse_translate(glm::vec3 pos){
return glm::unProject(pos, viewport.model, viewport.proj, glm::vec4(0.0f, 0.0f, viewport.dim.x, viewport.dim.y));
}
Full project on github: LinuxGameGeek/logix
OpenGL is poorly integrated with GTK+3, for example on OS X, you'll have this error displayed because OpenGL is simply not implemented. Maybe this is the same case for you
In addition in gtkmm-3.18 a bug (fixed since this version) displaying this error when GLArea class was derived. But this is not your case.
If that may help you I have a similar application mixing OpenGL/GTKmm in Lecrapouille/SimTaDyn I guess this will give you the same error.
#include <stdio.h> // this library is for standard input and output
#include "glut.h"// this library is for glut the OpenGL Utility Toolkit
#include <math.h>
float squareX = 0.0f;
float squareY = -0.3f;
float squareZ = 0.0f;
static int flag = 1;
void drawShape(void) {
glTranslatef(squareX, squareY, squareZ);
glBegin(GL_POLYGON);
glColor3f(1.0, 0.0, 0.0);
glVertex2f(162, 50);
glVertex2f(162, 10);
glVertex2f(220, 10);
glVertex2f(220, 50);
glVertex2f(162, 50);
glEnd();
}
void initRendering() {
glEnable(GL_DEPTH_TEST);
}
// called when the window is resized
void handleResize(int w, int h) {
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0f, (float)w, 0.0f, (float)h, -1.0f, 1.0f);
}
void drawScene() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
drawShape();
glutSwapBuffers();
}
// make the square go up
void update(int value) {
if (flag) {
squareY += 1.0f;
if (squareY > 400.0) {
flag = 0;
}
}
glutPostRedisplay();
glutTimerFunc(25, update, 0);
}
// make the square go right
/* void update(int value) {
if (flag) {
squareX += 1.0f;
if (squareX > 400.0) {
flag = 0;
}
}
glutPostRedisplay();
glutTimerFunc(25, update, 0);
} */
int main(int argc, char** argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(400, 400);
glutCreateWindow("Moving Square");
initRendering();
glutDisplayFunc(drawScene);
glutReshapeFunc(handleResize);
glutTimerFunc(25, update, 0);
glutMainLoop();
return(0);
}
I have uploaded this code before but this time I made the square go all the way up. The code just moves the square up, but I don't know how to position it on the left once it reaches the top, so then I can make it move to the right. I have uploaded a demonstration on how I want it to look below.
Preview:
What I want it to do next:
I recommend to initialize the variables squareX, squareY and squareZ with the start position of the rectangle:
float squareX = 162.0f;
float squareY = 0.0f;
float squareZ = 0.0f;
Do not draw a rectangle specific position, but draw a rectangle on the position (0,0) with a length (width, height). Let the model matrix (set by glTranslatef), do the job of the positioning:
void drawShape(void)
{
float width = 58.0f;
float height = 40.0f;
glTranslatef(squareX, squareY, squareZ);
glBegin(GL_POLYGON);
glColor3f(1.0, 0.0, 0.0);
glVertex2f(0, 0);
glVertex2f(width, 0);
glVertex2f(width, height);
glVertex2f(0, height);
glVertex2f(0, 0);
glEnd();
}
Use a variable state, which has stated the direction of the current movement:
int state = 1; // 0: stop; 1: move up; 2: move right
If the rectangle a certain position has reached, then the state has to be changed and a the new start position can be set. At the final position, the rectangle can stop or the process can even be restarted:
void update(int value)
{
if (state == 1) // 1 : move up
{
squareY += 1.0f;
if (squareY > 400.0)
{
state = 2;
squareX = 0.0f;
squareY = 180.0f;
}
}
else if (state == 2) // 2 : move right
{
squareX += 1.0f;
if (squareX > 400.0)
{
state = 0;
// restart
//state = 1;
//squareX = 162.0f;
//squareY = 0.0f;
}
}
glutPostRedisplay();
glutTimerFunc(25, update, 0);
}
I want to rotate my triangle in OpenGL, and running program on Raspberry Pi.
I can draw triangle and move it.
But I have no idea to rotate it..
Nothing rotates.
#include <cstdio>
#include <ctime>
#include <cmath>
#include <string>
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <GLES2/gl2.h>
#include <GLES/gl.h>
#include <bcm_host.h>
EGLDisplay Disp;
EGLSurface Surface;
EGLContext Context;
int ScrWidth, ScrHeight;
float MVPMatrix[16];
float ProjectionMatrix[16];
float ViewMatrix[16];
using namespace std;
class Shader
{
private:
string VertexShaderFile;
string FragmentShaderFile;
GLuint Load(GLenum type, string FileName)
{
(Compile shader)
}
GLuint Program;
bool Linked;
public:
Shader(string FileNameV, string FileNameF)
{
Linked = false;
VertexShaderFile = FileNameV;
FragmentShaderFile = FileNameF;
}
bool Load()
{
(Link vertex/fragment shader)
}
void Use()
{
glUseProgram(Program);
}
int GetAttrLoc(const char *Name)
{
glGetAttribLocation(Program, Name);
}
int GetUniformLoc(const char *Name)
{
return glGetUniformLocation(Program, Name);
}
~Shader()
{
if(Linked)
{
Linked = false;
glDeleteProgram(Program);
}
}
};
class Triangle
{
private:
const int COORDS_PER_VERTEX = 3;
const int vertexCount = 9 / COORDS_PER_VERTEX; //9: Length of triangleCoords
const int vertexStride = COORDS_PER_VERTEX * 4; // 4 bytes per vertex
static float TriangleCoords [];
float Color[4];
float XOff;
float YOff;
float ZOff;
Shader *S;
public:
Triangle()
{
XOff = YOff = ZOff = 0;
S = new Shader("Shaders/test.vsh", "Shaders/test.fsh");
if (!S->Load())
{
delete S;
S = NULL;
}
}
void SetColor(int R, int G, int B, int A)
{
Color[0] = R / 255.0;
Color[1] = G / 255.0;
Color[2] = B / 255.0;
Color[3] = A / 255.0;
}
void SetXYZ(int X, int Y, int Z)
{
(Sets position)
}
bool Draw()
{
float TriangleCoords[] = { // in counterclockwise order:
-0.0 + XOff, 0.622008459 + YOff, 0.0 + ZOff, // top
-0.5 + XOff, -0.311004243 + YOff, 0.0 + ZOff, // bottom left
0.5 + XOff, -0.311004243 + YOff, 0.0 + ZOff // bottom right
};
printf("%f\n", TriangleCoords[1]);
//glMatrixMode(GL_PROJECTION);
if (S == NULL)
return false;
S->Use();
// Load the vertex data
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, TriangleCoords);
// get handle to shape's transformation matrix
// Pass the projection and view transformation to the shader
//UniformMatrix4fv(S->GetUniformLoc("uMVPMatrix"), 1, false, MVPMatrix);
glUniform4fv(S->GetUniformLoc("vColor"), 1, Color);
glEnableVertexAttribArray(0);
//glPushMatrix();
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
float X = LocalTime->tm_hour / 23.0;
float Y = LocalTime->tm_min / 59.0;
float Z = LocalTime->tm_sec / 59.0;
glTranslatef(0, 0, 1);
glRotatef(60, 1.f, 0.f, 0.f);
glRotatef(30, 0.f, 1.f, 0.f);
glRotatef(30, 0.f, 0.f, 1.f);
glDrawArrays(GL_TRIANGLES, 0, 3);
//glPopMatrix();
return true;
}
};
bool InitDisplay()
{
bcm_host_init();
Disp = eglGetDisplay(EGL_DEFAULT_DISPLAY);
if(eglInitialize(Disp, NULL, NULL) != EGL_TRUE)
{
printf("Display initialize error.\n");
return false;
}
printf("Display initialized.\n");
static const EGLint AttrList[] =
{
EGL_RED_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_BLUE_SIZE, 8,
EGL_ALPHA_SIZE, 8,
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
EGL_NONE
};
EGLConfig Config;
int ConfigCount;
if(eglChooseConfig(Disp, AttrList, &Config, 1, &ConfigCount) != EGL_TRUE)
{
printf("Display choose config error.\n");
return false;
}
printf("Display config chosen. %d configs.\n", ConfigCount);
//if(eglBindAPI(EGL_OPENGL_ES_API) != EGL_TRUE)
//{
// printf("Bind API error.\n");
// return false;
//}
//printf("API bound.\n");
static const EGLint ContextAttr[] =
{
EGL_CONTEXT_CLIENT_VERSION, 2,
EGL_NONE
};
if((Context = eglCreateContext(Disp, Config, EGL_NO_CONTEXT, ContextAttr)) == EGL_NO_CONTEXT)
{
printf("Create context error.\n");
return false;
}
printf("Context created.\n");
if(graphics_get_display_size(0 /* LCD */, &ScrWidth, &ScrHeight) < 0)
{
printf("Get screen size error.\n");
return false;
}
printf("Got screen size. %dx%d\n", ScrWidth, ScrHeight);
DISPMANX_DISPLAY_HANDLE_T DispmanDisp;
DispmanDisp = vc_dispmanx_display_open(0 /* LCD */);
printf("Dispmanx - Display opened.\n");
DISPMANX_UPDATE_HANDLE_T DispmanUpdate;
DispmanUpdate = vc_dispmanx_update_start(0);
printf("Dispmanx - Update started.\n");
DISPMANX_ELEMENT_HANDLE_T DispmanElement;
VC_RECT_T DestRect;
VC_RECT_T SrcRect;
DestRect.x = 0;
DestRect.y = 0;
DestRect.width = ScrWidth;
DestRect.height = ScrHeight;
SrcRect.x = 0;
SrcRect.y = 0;
SrcRect.width = ScrWidth << 16;
SrcRect.height = ScrHeight << 16;
DispmanElement= vc_dispmanx_element_add(
DispmanUpdate,
DispmanDisp,
0/*layer*/,
&DestRect,
0/*src*/,
&SrcRect,
DISPMANX_PROTECTION_NONE,
0 /*alpha*/,
0/*clamp*/,
0/*transform*/
);
printf("Dispmanx - Element added.\n");
static EGL_DISPMANX_WINDOW_T NativeWindow;
NativeWindow.element = DispmanElement;
NativeWindow.width = ScrWidth;
NativeWindow.height = ScrHeight;
vc_dispmanx_update_submit_sync(DispmanUpdate);
printf("Dispmanx - Sync submited.\n");
if((Surface = eglCreateWindowSurface(Disp, Config, &NativeWindow, NULL)) == EGL_NO_SURFACE)
{
printf("Create surface error.\n");
return false;
}
printf("Surface created\n");
if(eglMakeCurrent(Disp, Surface, Surface, Context) != EGL_TRUE)
{
printf("Make onnection between context and surface error.\n");
return false;
}
printf("Connection made between context and surface.\n");
glEnable(GL_CULL_FACE);
glMatrixMode(GL_MODELVIEW);
printf("Graphics system ready.\n");
return true;
}
void makeFrustum(float fovY, float aspectRatio, float front, float back)
{
const float DEG2RAD = 3.14159265 / 180;
float tangent = tan(fovY / 2 * DEG2RAD); // tangent of half fovY
float height = front * tangent; // half height of near plane
float width = height * aspectRatio; // half width of near plane
// params: left, right, bottom, top, near, far
glFrustumf(-width, width, -height, height, front, back);
}
void DrawLoop()
{
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
glViewport(0, 0, ScrWidth, ScrHeight);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
makeFrustum(45.0, ScrWidth / (float)ScrHeight, 1, 500);
glEnableClientState(GL_VERTEX_ARRAY);
Triangle T1;
Triangle T2;
Triangle T3;
Triangle T4;
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.f, 0.f, -50.f);
while (1)
{
time_t Time;
time(&Time);
tm *LocalTime = localtime(&Time);
printf("%d:%d:%d\n", LocalTime->tm_hour, LocalTime->tm_min, LocalTime->tm_sec);
float R = LocalTime->tm_hour / 23.0;
float G = LocalTime->tm_min / 59.0;
float B = LocalTime->tm_sec / 59.0;
T1.SetColor(255, 0, 0, 255);
T1.SetXYZ(B * ScrWidth, B * ScrHeight, 0);
//glClearColor(0, 0, 0, 1.0);
//glClear(GL_COLOR_BUFFER_BIT);
if (!T1.Draw() || !T2.Draw() || !T3.Draw() || !T4.Draw())
{
return;
}
glFlush();
eglSwapBuffers(Disp, Surface);
}
}
int main()
{
if(!InitDisplay())
{
printf("Display initialize error.\n");
return false;
}
DrawLoop();
return 0;
}
What should I do to rotate triangle?
I referenced working code, but it still doesn't rotates.
You're trying to use OpenGL ES 1.1 functions (glLoadIdentity, glMatrixMode, glTranslatef, glRotatef, etc) in an OpenGL ES 2.0 context - this won't work. You can use either OpenGL ES 1.1 OR OpenGL ES 2.0, but you can't use both at the same time from the same context.
I would suggest sticking with OpenGL ES 2.0 using shaders, and learning the OpenGL ES 2.0 way of doing things, as this is how all of the newer APIs work.
To do translation and rotation you need to encode it into an MVP matrix and pass this as a uniform to the vertex shader which you use when calculating gl_Position. Some examples here:
https://open.gl/transformations
I never got the concept down on how to get an animation working in OpenGL. I was working on his project trying to get it to work but never got the skier to move. Trying to figure out how to get this fixed.
#include "../shared/gltools.h" // OpenGL toolkit
#define PI 3.14159265
float a = -5;//maybe
float b = 29;
float c = 27;
float d = 28.25;
float e = 28.5;
bool lookUp;
bool setback;
bool lookDown;
bool lookLeft;
bool lookRight;
bool walkForward;
bool walkBackward;
bool strafeLeft;
bool strafeRight;
float xTranslation;
float yTranslation;
float zTranslation;
float yRotationAngle;
float zRotationAngle;
float xRotationAngle;
int mouseLastx;
int mouseLasty;
float sunRotationAngle=0;
float sunRadius = 150.0;
float day=0;
float dusk=1;
// Light values and coordinates
GLfloat lightPos[] = { 0.0f, 30.0f, 0.0f, 1.0f };
GLfloat lightPos2[] = { 0.0f, 0.0f, 40.0f, 1.0f };
GLfloat specular[] = { 1.0f, 1.0f, 1.0f, 1.0f};
GLfloat specular2[] = { 0.0f, 1.0f, 0.0f, 1.0f};
GLfloat diffuse[] = { 1.0f, 1.0f, 1.0f, 1.0f};
GLfloat diffuse2[] = { 0.0f, 0.3f, 0.0f, 1.0f};
GLloat specref[] = { 1.0f, 1.0f, 1.0f, 1.0f };
GLfloat ambientLight[] = { 0.5f, 0.5f, 0.5f, 1.0f};
GLfloat spotDir[] = { 0.0f, 0.0f, -1.0f };
void mouseMovement(int x, int y)
{
int mouseDiffx=x-mouseLastx;
int mouseDiffy=y-mouseLasty;
mouseLastx=x;
mouseLasty=y; //set lasty to the current y position
xRotationAngle += (GLfloat) mouseDiffy;
yRotationAngle += (GLfloat) mouseDiffx;
if (xRotationAngle>=90)
xRotationAngle=90;
if (xRotationAngle<=-90)
xRotationAngle=-90;
//cout << "x:" << x << "y:" << y << endl;
}
void drawcabin()
{
glColor3ub(0, 0, 0);
glBegin(GL_TRIANGLES);
//glTranslatef(0,-5,0); // move view left
//glNormal3f(-3,0.7,-1.7);
//glutSolidCube(5.0f);
glNormal3d(0,0.7,0.7);
glVertex3d(0,6,0);
glVertex3d(-3,3.5,-2);
glVertex3d(2,3.5,-2);
glNormal3d(2,-1,1);
glVertex3d(0,6,0);
glVertex3d(-3,3.5,-2);
glVertex3d(2,3.5,-2);
glTranslatef(0,-5,0); // move view left
glNormal3d(-3,0.7,-1.7);
glEnd();
glColor3ub(185, 0, 0);
glutSolidCube(5.0f);
}
void drawskislope()
{
glColor3ub(0, 0, 0);
glBegin(GL_QUADS);
glTranslatef(0,-5,90); // move view left
glColor3ub(185, 122, 87);
glNormal3d(0,5,1);
glVertex3d(10,0,5);
glVertex3d(10,.5,5);
glVertex3d(15,.5,5);
glVertex3d(15,0,5);//small square
glColor3ub(201, 192, 187);
glVertex3d(11.5,.5,5);
glVertex3d(13.5,.5,5);
glVertex3d(13.5,-10,5);
glVertex3d(11.5,-10,5);
//slope start
glTranslatef(0,-5,0); // move view left
// glNormal3d(-3,0.7,-1.7);
glEnd();
}
void drawskier()
{
float a = -5;//maybe
float b = 29;
float c = 27;
float d = 28.25;
float e = 28.5;
glBegin(GL_QUADS);
glTranslatef(0,-5,0); // move view
glColor3ub(185, 122, 87);
glNormal3d(0,5,1);
//Do While loop
// do
// {
// to move skier do a loop and update a in the translate
glTranslatef(0,a,0); // move view
glVertex3d(c,0,5);//10
glVertex3d(c,.1,5);//10
glVertex3d(b,.1,5);//15
glVertex3d(b,0,5);//skis on skier
glNormal3d(0,5,1);
glVertex3d(d,0,5);
glVertex3d(d,1.35,5);
glVertex3d(e,1.35,5);
glVertex3d(e,0,5);//body on skier
glutSwapBuffers;
// }while(b>15); //try to animate
glEnd();
glFlush();
b=b-1;
c=c-1;
d=d-1;
e=e-1;
glutPostRedisplay();
glTranslatef(30,3,0); // move view left
glColor3ub(168, 220, 109);
glutSolidSphere(.5,7,8); //sphere-head
glPushMatrix();
glTranslatef(3.5,-100,2);
glutSolidSphere(25,15,15); //sphere
glPopMatrix();
}
void updatescene()
{
}
///////////////////////////////////////////////////////////
// Called to draw scene
void RenderScene(void)
{
GLUquadricObj *pObj; // Quadric Object
pObj = gluNewQuadric();
gluQuadricNormals(pObj, GLU_SMOOTH);
GLfloat horizontalMovement=1;
GLfloat verticalMovement=0;
horizontalMovement=cos(xRotationAngle*PI/180);
verticalMovement=-sin(xRotationAngle*PI/180);
// Reset Model view matrix stack
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
horizontalMovement=cos(xRotationAngle*PI/180);
verticalMovement=-sin(xRotationAngle*PI/180);
if (lookDown)
{
xRotationAngle+=1;
if (xRotationAngle>=90)
xRotationAngle=90;
}
if (lookUp)
{
xRotationAngle-=1;
if (xRotationAngle<=-90)
xRotationAngle=-90;
}
if (lookRight)
{
yRotationAngle+=1;
if (yRotationAngle>=360)
yRotationAngle=0;
}
if (lookLeft)
{
yRotationAngle-=1;
if (yRotationAngle<=-360)
yRotationAngle=0;
}
if (walkForward)
{
zTranslation+=cos(yRotationAngle*PI/180)*horizontalMovement;
xTranslation-=sin(yRotationAngle*PI/180)*horizontalMovement;
yTranslation-=verticalMovement;
}
if (walkBackward)
{
zTranslation-=cos(yRotationAngle*PI/180)*horizontalMovement;
xTranslation+=sin(yRotationAngle*PI/180)*horizontalMovement;
yTranslation+=verticalMovement;
}
if (strafeRight)
{
zTranslation+=cos((yRotationAngle+90)*PI/180);
xTranslation-=sin((yRotationAngle+90)*PI/180);
}
if (strafeLeft)
{
zTranslation-=cos((yRotationAngle+90)*PI/180);
xTranslation+=sin((yRotationAngle+90)*PI/180);
}
if (setback)
{
zTranslation=0;
xTranslation=0;
yTranslation=0;
}
// Reset Model view matrix stack
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glRotatef(xRotationAngle,1,0,0);
glRotatef(zRotationAngle,0,0,1);
glRotatef(yRotationAngle,0,1,0);
glTranslatef(xTranslation,yTranslation,zTranslation);
//glRotatef(-15,1,0,0);
//glRotatef(90,0,1,0);
glTranslatef(0,-0.50,-10);
glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
sunRotationAngle++;
// Clear the window with current clearing color
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor3d(0,0,0);
glLineWidth(2);
//snow
glColor3ub(255, 255, 255);
glBegin(GL_QUADS);
glNormal3f(0,1,0);
for (int i=-100;i<=200;i+=10) //x
for (int j=-100;j<=200;j+=10)//z
{
float y1=(-j)*.25;
float y2=(-j+10)*.25;
glVertex3d(i+10,y2,-100);
glVertex3d(i,y2,-100);
glVertex3d(i,y1,-100);
glVertex3d(i+10,y1,-100);
}
glEnd();
glPushMatrix();
glTranslatef(-10,14,-50);
drawcabin();
drawskislope();
drawskier();
glPopMatrix();
// Flush drawing commands
glutSwapBuffers();
glutPostRedisplay();
//GLfloat horizontalMovement=1;
// GLfloat verticalMovement=0;
}
void TimerFunction(int value)
{
// Redraw the scene with new coordinates
glutPostRedisplay();
updatescene();
glutTimerFunc(16,TimerFunction, 1);
}
///////////////////////////////////////////////////////////
// Setup the rendering context
void SetupRC(void)
{
lookUp=false;
lookDown=false;
lookLeft=false;
lookRight=false;
walkForward=false;
walkBackward=false;
strafeLeft=false;
strafeRight=false;
yRotationAngle=0;
xRotationAngle=0;
zRotationAngle=0;
xTranslation=0;
yTranslation=0;
zTranslation=0;
// White background
glClearColor(0.5f,0.95f, 1.0f, 1.0f );
// Set drawing color to green
glColor3f(0.0f, 1.0f, 0.0f);
// Set color shading model to flat
glShadeModel(GL_SMOOTH);
// Clock wise wound polygons are front facing, this is reversed
// because we are using triangle fans
glFrontFace(GL_CCW);
glEnable (GL_DEPTH_TEST);
}
void ChangeSize(int w, int h)
{
//GLfloat nRange = 100.0f;
// Prevent a divide by zero
if(h == 0)
h = 1;
// Set Viewport to window dimensions
glViewport(0, 0, w, h);
// Reset projection matrix stack
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
// Establish clipping volume (left, right, bottom, top, near, far)
GLfloat fAspect;
fAspect = (GLfloat)w / (GLfloat)h;
//glOrtho(-10,10,-10,10,0,1000);
gluPerspective(45,fAspect,0.1,1000);
// Reset Model view matrix stack
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
// Respond to arrow keys by moving the camera frame of reference
void SpecialKeys(int key, int x, int y)
{
if(key == GLUT_KEY_UP)
lookUp=true;
if(key == GLUT_KEY_DOWN)
lookDown=true;
if(key == GLUT_KEY_LEFT)
lookLeft=true;
if(key == GLUT_KEY_RIGHT)
lookRight=true;
// Refresh the Window
glutPostRedisplay();
}
void SpecialKeysUp(int key, int x, int y)
{
if(key == GLUT_KEY_UP)
lookUp=false;
if(key == GLUT_KEY_DOWN)
lookDown=false;
if(key == GLUT_KEY_LEFT)
lookLeft=false;
if(key == GLUT_KEY_RIGHT)
lookRight=false;
// Refresh the Window
glutPostRedisplay();
}
void keyboardFunc(unsigned char key, int x, int y)
{
switch(key)
{
case 'w':
walkForward=true;
break;
case 's':
walkBackward=true;
break;
case 'a':
strafeLeft=true;
break;
case 'd':
strafeRight=true;
break;
case 'r':
setback=true;
break;
default:
break;
}
}
void keyboardUpFunc(unsigned char key, int x, int y)
{
switch(key)
{
case 'w':
walkForward=false;
break;
case 's':
walkBackward=false;
break;
case 'a':
strafeLeft=false;
break;
case 'd':
strafeRight=false;
break;
default:
break;
}
}
///////////////////////////////////////////////////////////
// Main program entry point
int main(int argc, char* argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(500,500);
glutCreateWindow("Assignment 2");
glutReshapeFunc(ChangeSize);
glutDisplayFunc(RenderScene);
glutSpecialFunc(SpecialKeys);
glutSpecialUpFunc(SpecialKeysUp);
glutKeyboardUpFunc(keyboardUpFunc);
glutKeyboardFunc(keyboardFunc);
glutPassiveMotionFunc(mouseMovement);
SetupRC();
glutMainLoop();
return 0;
}
My general approach is to use a glutTimerFunc() callback to post a redisplay event every 16 milliseconds or so (~60 FPS).
Then in the glutDisplayFunc() callback you can grab the new GLUT_ELAPSED_TIME to calculate a delta-time (dt) from the last frame.
With dt in hand you can update any number of variables such as angles or translation offsets. You'll want to use dt instead of fixed increment values to decouple your animation speed from your framerate.
Then back in the glutDisplayFunc() callback you draw a new frame using the updated state variables.
This is an example that uses the method above to rotate a square at about 30 degrees per second:
#include <GL/glut.h>
float angle = 0;
void update( const double dt )
{
// in degrees per second
const float SPEED = 30.0f;
// update angle
angle += ( SPEED * dt );
}
void display()
{
// GLUT_ELAPSED_TIME is in milliseconds
static int prvMs = glutGet( GLUT_ELAPSED_TIME );
const int curMs = glutGet( GLUT_ELAPSED_TIME );
// dt is in seconds
const double dt = ( curMs - prvMs ) / 1000.0;
prvMs = curMs;
// update world state
update( dt );
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
// reset projection/modelview matrices each frame;
// this makes sure we have a known-good matrix
// stack each time through display()
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
glOrtho( -2, 2, -2, 2, -1, 1 );
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
// draw rotated square
glRotatef( angle, 0, 0, 1 );
glBegin( GL_QUADS );
glColor3ub( 255, 0, 0 );
glVertex2i( -1, -1 );
glVertex2i( 1, -1 );
glVertex2i( 1, 1 );
glVertex2i( -1, 1 );
glEnd();
glutSwapBuffers();
}
void timer( int value )
{
glutPostRedisplay();
glutTimerFunc( 16, timer, 0 );
}
int main( int argc, char **argv )
{
glutInit( &argc, argv );
glutInitDisplayMode( GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE );
glutInitWindowSize( 600, 600 );
glutCreateWindow( "GLUT" );
glutDisplayFunc( display );
glutTimerFunc( 0, timer, 0 );
glutMainLoop();
return 0;
}
I'm trying to port my height map visualization program written on c++, from SFML to Qt, so it can be shown on widget and controlled by the GUI elements.
The problem is that when I start an application, a camera starts to roll around its center very fast(actually, it looks like a terrain mesh flying around a camera, like an Earth around the Sun :), without any actions from my side(e.g moving mouse, pressing buttons).
Camera should move forward, back, left, right when I press w,a,s,d and look around when I move the mouse(Just typical FPS camera behavior).
I think that problem are in the program's main loop, because it's no standard while(true){ //do something// } approach in qt, and it's a little confusing.
Here's my code:
OGLWidget class(here I'm drawing stuff. Problem somewhere here I 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 that Terrain and Camera classes are working correct, because I haven't changed code since my SFML project(Except of using QImage instead of sf::Image, but 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 up = 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 is here
_position+_direction, // and looks here : at the same position, plus "direction"
up // Head is up (set to 0,-1,0 to look upside-down)
);
}
Help me fix this issue.
Ok, I figured out the problem with spinning camera. The cause of it was that I hardcoded an aspect ratio in Camera::computeMatrices, and used a resolution of my widget which doesn't match to it:
_projectionMatrix = glm::perspective
(
_initialFoV,
4.0f / 3.0f, //here it is
0.1f,
1000.0f
);
I changed 4.0f / 3.0f on (float)_screenWidth / (float)_screenHeight but it didn't help too.
So then I just changed a resolution of my widget to 800 x 600 and it helped.
The new problem is that it works only on 4/3 dimensions(e.g 800x600, 1024x768).
The best way to correct
_direction = glm::vec3
(
cos(_verticalAngle) * sin(_horizontalAngle),
sin(_verticalAngle),
cos(_verticalAngle) * cos(_horizontalAngle)
);
_direction.normalize();
...