问题
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();
};
来源:https://stackoverflow.com/questions/62487544/i-am-getting-wrong-values-when-calling-glreadpixels