纯opengl变焦相机到鼠标pos

时间:2017-03-29 19:41:07

标签: c++ opengl

我试图编辑我的鼠标缩放功能,以便在3d世界中缩放鼠标位置,如果我需要,我可以获得鼠标的3d线,但不知道该怎么做。

目前我的变焦只是缩放到屏幕中心。

void CCamera::OnMouseWheel(float zDelta)
{
    Position -= Reference;

    if(zDelta < 0 && length(Position) < 500.0f)
    {
        Position += Position * 0.1f;
    }

    if(zDelta > 0 && length(Position) > 0.05f)
    {
        Position -= Position * 0.1f;
    }

    Position += Reference;

    CalculateViewMatrix();
}

void CCamera::CalculateViewMatrix()
{
    ViewMatrix = mat4x4(X.x, Y.x, Z.x, 0.0f, X.y, Y.y, Z.y, 0.0f, X.z, Y.z, Z.z, 0.0f, -dot(X, Position), -dot(Y, Position), -dot(Z, Position), 1.0f);
    ViewMatrixInverse = inverse(ViewMatrix);
    ViewProjectionMatrix = ProjectionMatrix * ViewMatrix;
    ViewProjectionMatrixInverse = ViewMatrixInverse * ProjectionMatrixInverse;
}

2 个答案:

答案 0 :(得分:0)

您可能需要对代码进行一些编辑,以确保所有内容都兼容,例如编辑视图。但是这里有一个来自我的项目的代码片段,它正是您所说的。我认为代码非常明显,

void modelDefinition::onMouseWheel(wxMouseEvent &event)
{
    if(event.GetWheelRotation() != 0)
    {
        /* This section of the code was adapted from Agro2D */

        _cameraX += (((2.0 / this->GetSize().GetWidth()) * (event.GetX() - this->GetSize().GetWidth() / 2.0)) / _zoomFactor) * (this->GetSize().GetWidth() / this->GetSize().GetHeight());
        _cameraY += (-(2.0 / this->GetSize().GetHeight()) * (event.GetY() - this->GetSize().GetHeight() / 2.0)) / _zoomFactor;

        if(!_preferences.getMouseZoomReverseState())
        {
            if(event.GetWheelRotation() > 0)
                _zoomFactor *= pow(1.2, -(event.GetWheelDelta()) / 150.0);
            else
                _zoomFactor *= pow(1.2, (event.GetWheelDelta()) / 150.0);
        }
        else
        {
            if(event.GetWheelRotation() < 0)
                _zoomFactor *= pow(1.2, -(event.GetWheelDelta()) / 150.0);
            else
                _zoomFactor *= pow(1.2, (event.GetWheelDelta()) / 150.0);
        }

        /* This will recalculate the new position of the mouse. Assuming that the mouse does not move at all during the process
         * This also enables the feature where the zoom will zoom in/out at the position of the mouse */

        _cameraX -= (((2.0 / this->GetSize().GetWidth()) * (event.GetX() - this->GetSize().GetWidth() / 2.0)) / _zoomFactor) * (this->GetSize().GetWidth() / this->GetSize().GetHeight());
        _cameraY -= (-(2.0 / this->GetSize().GetHeight()) * (event.GetY() - this->GetSize().GetHeight() / 2.0)) / _zoomFactor;
    }

    this->Refresh();// This will force the canvas to experience a redraw event
}

我应该提一下,函数this->Refresh只会导致我的屏幕更新。你的可能会有所不同。

此外,_cameraX和_cameraY存储openGL画布的偏移量。

这是我的画布的构造函数:

modelDefinition::modelDefinition(wxWindow *par, const wxPoint &point, const wxSize &size, problemDefinition &definition) : wxGLCanvas(par, wxID_ANY, NULL, point, size, wxBORDER_DOUBLE | wxBORDER_RAISED)
{
    _geometryContext = new wxGLContext(this);
    wxGLCanvas::SetCurrent(*_geometryContext);

    _localDefinition = &definition;

    _editor.setZoomFactorAddress(_zoomFactor);

    glViewport(0, 0, (double)this->GetSize().GetWidth(), (double)this->GetSize().GetHeight());

    glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
    glMatrixMode(GL_MODELVIEW);// The matrix mode specifies which matrix stack is the target for matrix operations
    glLoadIdentity();// Initial value
    glTranslated((float)this->GetSize().GetWidth() / 2.0f, (float)this->GetSize().GetHeight() / 2.0f, 0.0f);// This will move the camera to the center of the screen

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

    glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0);
    GLenum error = glGetError();
    if(error != GL_NO_ERROR)
    {
    //  wxMessageBox("Error - " + gluErrorString(error));
        return;
    }

    glMatrixMode(GL_MODELVIEW);
}

以下是处理更新我的观点位置的代码:

void modelDefinition::updateProjection()
{
    // First, load the projection matrix and reset the view to a default view
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

    //Reset to modelview matrix
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    /* This section will handle the translation (panning) and scaled (zooming). 
     * Needs to be called each time a draw occurs in order to update the placement of all the components */
    if(_zoomFactor < 1e-9)
        _zoomFactor = 1e-9;

    if(_zoomFactor > 1e6)
        _zoomFactor = 1e6;

    glScaled(_zoomFactor / (this->GetSize().GetWidth() / this->GetSize().GetHeight()), _zoomFactor, 1.0);

    glTranslated(-_cameraX, -_cameraY, 0.0);
}

答案 1 :(得分:0)

假设你有鼠标光标的3D坐标。撤消视口变换可以在NDC空间中获得这些坐标,也可以通过矩阵反转获得视图空间或模型空间坐标。现在,您有一个从相机到这些鼠标坐标的矢量(在您喜欢的任何空间)。最后一步是将摄像机跟随该矢量移动一定量,具体取决于鼠标滚轮的旋转。

如果你没有这些3D鼠标坐标......你有一个很大的问题,因为它无法从2D数据中获取3D信息。你缺乏“屏幕深度”,NDC空间中的Z值。