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;
}
时间: 2024-10-09 11:40:25