OpenGL漫游模型示例

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/wcl0617/article/details/51352389

OpenGL漫游模型示例:

#include <stdio.h>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtx/transform.hpp>
#include <GLFW/glfw3.h>
#include "TrackballController.h"

#define CIGAMA 0.1

TrackballController* TrackballController::m_inst(0);

TrackballController* TrackballController::Inst()
{
    if(!m_inst)
    {
        m_inst = new TrackballController();
    }

    return m_inst;
}

TrackballController::TrackballController(void)
{
    mOldMouseX=0;
    mOldMouseY=0;
    m_vPtTrans = glm::vec2(0.0f, 0.0f);//鼠标平移距离

    mRotationAangle=0;//旋转角度
    mDistanceToModelCenter = -2.0;

    mRotationAaxis_Local=glm::vec3(1.0f, 0.0f, 0.0f);
    //初始化视图、平移、旋转、缩放矩阵
    mViewMatrix = mTranslationMatrix = mRotationMatrix = mScaleMatrix = glm::mat4(1.0);

    mScrollSpeed = 0.0f;
    m_fScale = 1.0f;//缩放比例

    mMouseButton = -1;//标记鼠标按下的键
    spin_y_old = 0.0f;//模型旋转角度初始化
}


TrackballController::~TrackballController(void)
{
}

void TrackballController::OnMouseMove(int x, int y)
{
    //
    /*if ( abs(x - mOldMouseX) < CIGAMA && abs(y - mOldMouseY) < CIGAMA )
    {
        return;
    }*/

    if ( GLFW_MOUSE_BUTTON_LEFT == mMouseButton )
    {
        GLint viewport[4];
        glGetIntegerv(GL_VIEWPORT,viewport);//获取视口大小
         //转换屏幕坐标为opengl坐标
        glm::vec2 newMouse = scaleMouse( glm::vec2(x, y), glm::vec2(viewport[2],viewport[3]));
        glm::vec2 oldMouse = scaleMouse( glm::vec2(mOldMouseX, mOldMouseY), glm::vec2(viewport[2],viewport[3]));
        //计算平移距离
        glm::vec2 d = (newMouse - oldMouse);
        //y轴方向上移动的距离大于x轴方向上的距离时,平移
        if (abs(mOldMouseX - x) < abs(mOldMouseY - y))
        {
            m_vPtTrans = d;
        }
        else//反之,旋转
        {
            float RotationAangle = 360*(x-mOldMouseX)/m_fWinWidth;
            mRotationMatrix=glm::rotate(mRotationMatrix, RotationAangle,glm::vec3(0.0f,1.0f,0.0f) );

            //spin_y_old = mRotationAangle;
            //SetRotateParameter(newMouse,oldMouse);
        }

        mOldMouseX = x;
        mOldMouseY = y;
        //更新模型矩阵
        UpdateMatrix();
    }       
}

void TrackballController::OnMouseScroll( int value )
{
    if ( value > 0 )
    {
        // 推远模型
        //mDistanceToModelCenter += mScrollSpeed;

        m_fScale *= (1.0f+mScrollSpeed);
    }
    else if ( value < 0 && m_fScale >= mScrollSpeed)
    {
        // 拉近模型
        //mDistanceToModelCenter -= mScrollSpeed;

        m_fScale *= (1.0f-mScrollSpeed);
    }

    //printf("value=%d, mDistanceToModelCenter=%f\n",value, mDistanceToModelCenter);

    UpdateMatrix();
}

void TrackballController::onMouseButton( int action,  int button ,int x,int y)
{
    if (action != GLFW_PRESS)
    {
        mMouseButton = -1;
        return;
    }

    mMouseButton = button;

    mOldMouseX = x;
    mOldMouseY = y;
}

void TrackballController::UpdateMatrix()
{
    //mTranslationMatrix = glm::translate(glm::mat4(1.0f),glm::vec3(0.0f, 0.0f, mDistanceToModelCenter));
    mScaleMatrix = glm::scale(glm::mat4(1.0f),glm::vec3(m_fScale, m_fScale, m_fScale));
    mTranslationMatrix = glm::translate(mTranslationMatrix,glm::vec3(0.0f, m_vPtTrans.y, mDistanceToModelCenter));
    mViewMatrix = mTranslationMatrix * mRotationMatrix * mScaleMatrix;

    m_vPtTrans = glm::vec2(0.0f,0.0f);
    mDistanceToModelCenter = 0.0f;
}

glm::vec2 TrackballController::scaleMouse(glm::vec2 coords, glm::vec2 viewport) 
{
    /*return glm::vec2( static_cast<float>(coords.x*2.0f) / static_cast<float>(viewport.x) - 1.0f, 
                              1.0f - static_cast<float>(coords.y*2.0f) / static_cast<float>(viewport.y) );*/

    return glm::vec2( static_cast<float>(coords.x) / static_cast<float>(viewport.x), 
        1.0f - static_cast<float>(coords.y) / static_cast<float>(viewport.y) );
}

glm::vec3 TrackballController::projectToSphere(glm::vec2 xy) 
{
    static const float sqrt2 = sqrtf(2.f);
    glm::vec3 result;
    float d = glm::length(xy);
    float size_=2;

    if (d < size_ * sqrt2 / 2.f) 
    {
        result.z = sqrtf(size_ * size_ - d*d);
    }
    else 
    {
        float t = size_ / sqrt2;
        result.z = t*t / d;
    }

    result.x = xy.x;
    result.y = xy.y;

    return glm::normalize(result);
}

void TrackballController::SetRotateParameter(glm::vec2 newMouse,glm::vec2 oldMouse)
{
    if (newMouse == oldMouse) 
    {
        return;
    }

    glm::vec3 p1 = projectToSphere(oldMouse);
    glm::vec3 p2 = projectToSphere(newMouse);

    glm::vec3 r_axis_world = glm::cross(p1, p2);
    glm::vec3 d = 0.5f*(p1 - p2);
    mRotationAangle= 180*glm::length(d);

    glm::vec3 r_axis_local_end=glm::vec3(glm::inverse(mViewMatrix)*glm::vec4(r_axis_world,1));
    glm::vec3 r_axis_local_start=glm::vec3(glm::inverse(mViewMatrix)*glm::vec4(0.0,0.0,0.0,1));

    mRotationAaxis_Local=r_axis_local_end-r_axis_local_start;

    mRotationMatrix=glm::rotate(mRotationMatrix, mRotationAangle,mRotationAaxis_Local );//glm::vec3(0,1,0)
}

//初始化场景初始参数
void TrackballController::SetInitialState( glm::vec3 CameraPos, glm::vec3 modelCenter, glm::vec3 modelSize  )
{
    m_fScale = 1.0f;
    mTranslationMatrix = mRotationMatrix = mScaleMatrix = glm::mat4(1.0);
    spin_y_old = 0;

    mDistanceToModelCenter = -1.0 * glm::length( CameraPos - modelCenter );

    mViewMatrix = glm::lookAt(CameraPos, modelCenter, glm::vec3(0.0f,1.0f,0.0f));

    // 根据模型的尺寸,计算出鼠标滚轮对模型的推远与拉近的速度
    float length = glm::length( modelSize );

    mScrollSpeed = length * 0.1f;

    UpdateMatrix();
}

//自动旋转参数设置
void TrackballController::AutoRotateAngle( GLfloat fAngle )
{
    mRotationMatrix=glm::rotate(mRotationMatrix, fAngle-spin_y_old,glm::vec3(0.0f,1.0f,0.0f) );

    spin_y_old = fAngle;
    UpdateMatrix();
}

//设置视口大小
void TrackballController::ReSize( GLfloat fWidth,GLfloat fHeight )
{
    m_fWinWidth = fWidth;
    m_fWinHeight = fHeight;
}
阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页