简体   繁体   English

纯opengl变焦相机到鼠标pos

[英]pure opengl zoom camera to mouse pos

Im trying to edit my mouse zoom function to zoom towards the mouse pos in 3d world, I can get the 3d cords of the mouse if i need that just not sure how to do it. 我试图编辑鼠标缩放功能以向3d世界中的鼠标pos缩放,如果我不确定该怎么做,我可以获取鼠标的3d线。

At the moment my zoom just zooms towards the screen center. 此刻,我的缩放只是朝屏幕中心缩放。

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;
}

You may need to do some editing on your code to make sure everything is compatible such as editing the viewgraph. 您可能需要对代码进行一些编辑,以确保所有内容都兼容,例如编辑视图。 But here is a code snippet from my project that does exactly what you are saying. 但是,这是我项目中的代码片段,完全符合您的要求。 I think that the code is pretty self-explanatory, 我认为代码很容易解释,

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
}

I should mention that the function this->Refresh will just cause my screen to update. 我应该提一下this->Refresh函数只会导致我的屏幕更新。 Yours might be different. 您的可能会有所不同。

Also, _cameraX and _cameraY stores the offset of the openGL canvas. 同样,_cameraX和_cameraY存储openGL画布的偏移量。

Here is the constructor for my canvas: 这是我的画布的构造函数:

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);
}

And here is the code that handles updating the position of my view: 这是处理更新视图位置的代码:

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);
}

Let's suppose you have the 3D coordinates of the mouse cursor. 假设您具有鼠标光标的3D坐标。 Undoing the viewport transformation you get these coordinates in NDC space, and also by matrix inversion you can get View space or Model space coordinates. 撤消视口变换,您可以在NDC空间中获得这些坐标,并且通过矩阵求逆,您可以获得视图空间或模型空间的坐标。 Now, you have a vector from camera to these mouse coordinates (in whatever space you like). 现在,您有了从摄像机到这些鼠标坐标的矢量(在您喜欢的任何空间)。 The last step is moving the camera following that vector by an amount depending on mouse wheel-rotation. 最后一步是根据鼠标滚轮的旋转将摄像机跟随该矢量移动一定量。

If you don't have those 3D mouse coordinates... you have a big problem, due to it's not possible to get 3D information from a 2D data. 如果您没有那些3D鼠标坐标...您会遇到很大的问题,因为无法从2D数据中获取3D信息。 You lack the "depth in the screen", Z value in NDC space. 您缺少“屏幕深度”,即NDC空间中的Z值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM