我正在使用下面的代码在c++中实现opengl中的“缩放到鼠标指针”功能。大部分代码来自OpenGL Google maps style 2D camera / zoom to mouse cursor,但由于GLM (http://glm.g-truc.net/0.9.5/index.html)代码库的更改,我不得不更改一些include语句。
#include <GL/freeglut.h>
#include <iostream>
using namespace std;
#define GLM_SWIZZLE_XYZW
#define GLM_FORCE_RADIANS
#include "glm/glm.hpp"
#include "glm/detail/setup.hpp"
#include "glm/detail/_swizzle.hpp"
#include "glm/detail/_swizzle_func.hpp"
#include "glm/gtc/matrix_transform.hpp"
#include "glm/gtc/type_ptr.hpp"
glm::dvec3 Unproject( const glm::dvec3& win )
{
glm::ivec4 view;
glm::dmat4 proj, model;
glGetDoublev( GL_MODELVIEW_MATRIX, glm::value_ptr( model ) );
glGetDoublev( GL_PROJECTION_MATRIX, glm::value_ptr( proj ) );
glGetIntegerv( GL_VIEWPORT, glm::value_ptr( view ) );
glm::dvec3 world = glm::unProject( win, model, proj, view );
return world;
}
// unprojects the given window point
// and finds the ray intersection with the Z=0 plane
glm::dvec2 PlaneUnproject( const glm::dvec2& win )
{
glm::dvec3 world1 = Unproject( glm::dvec3( win, 0.01 ) );
glm::dvec3 world2 = Unproject( glm::dvec3( win, 0.99 ) );
// u is a value such that:
// 0 = world1.z + u * ( world2.z - world1.z )
double u = -world1.z / ( world2.z - world1.z );
// clamp u to reasonable values
if( u < 0 ) u = 0;
if( u > 1 ) u = 1;
return glm::swizzle< glm::X, glm::Y >( world1 + u * ( world2 - world1 ) );
}
// pixels per unit
const double ppu = 80.0;
glm::dvec2 center( 0 );
double scale = 1.0;
void ApplyCamera()
{
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
const double w = glutGet( GLUT_WINDOW_WIDTH ) / ppu;
const double h = glutGet( GLUT_WINDOW_HEIGHT ) / ppu;
glOrtho( -w/2, w/2, -h/2, h/2, -1, 1 );
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
glScaled( scale, scale, 1.0 );
glTranslated( -center[0], -center[1], 0 );
}
glm::dvec2 centerStart( 0 );
int btn = -1;
void mouse( int button, int state, int x, int y )
{
ApplyCamera();
y = glutGet( GLUT_WINDOW_HEIGHT ) - y;
btn = button;
if( GLUT_LEFT_BUTTON == btn && GLUT_DOWN == state )
{
centerStart = PlaneUnproject( glm::dvec2( x, y ) );
}
if( GLUT_LEFT_BUTTON == btn && GLUT_UP == state )
{
btn = -1;
}
glutPostRedisplay();
}
void motion( int x, int y )
{
y = glutGet( GLUT_WINDOW_HEIGHT ) - y;
if( GLUT_LEFT_BUTTON == btn )
{
ApplyCamera();
glm::dvec2 cur = PlaneUnproject( glm::dvec2( x, y ) );
center += ( centerStart - cur );
}
glutPostRedisplay();
}
void wheel( int wheel, int direction, int x, int y )
{
y = glutGet( GLUT_WINDOW_HEIGHT ) - y;
ApplyCamera();
glm::dvec2 beforeZoom = PlaneUnproject( glm::dvec2( x, y ) );
const double scaleFactor = 0.90;
if( direction == -1 ) scale *= scaleFactor;
if( direction == 1 ) scale /= scaleFactor;
ApplyCamera();
glm::dvec2 afterZoom = PlaneUnproject( glm::dvec2( x, y ) );
center += ( beforeZoom - afterZoom );
glutPostRedisplay();
}
void display()
{
glClearColor( 0, 0, 0, 1 );
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
ApplyCamera();
glBegin( GL_QUADS );
glVertex2i( -1, -1 );
glVertex2i( 1, -1 );
glVertex2i( 1, 1 );
glVertex2i( -1, 1 );
glEnd();
glutSwapBuffers();
}
int main( int argc, char **argv )
{
glutInit( &argc, argv );
glutInitDisplayMode( GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE );
glutInitWindowSize( 600, 600 );
glutCreateWindow( "GLUT" );
glutMouseFunc( mouse );
glutMotionFunc( motion );
glutMouseWheelFunc( wheel );
glutDisplayFunc( display );
glutMainLoop();
return 0;
}错误
error: 'swizzle' is not a member of 'glm'
error: 'X' is not a member of 'glm'
error: 'Y' is not a member of 'glm'都在排队
return glm::swizzle< glm::X, glm::Y >( world1 + u * ( world2 - world1 ) );我知道glm::swizzle显然是错误的,但是glm::detail::_swizzle需要8个参数,而glm::swizzle之前只需要2个参数。新的参数是什么?另外,我不知道如何纠正glm::X和glm::Y。有人能帮帮忙吗?
发布于 2020-06-02 21:36:24
在更新版本的glm中,如果你想要swizzle运算符,你需要在包含glm之前定义GLM_FORCE_SWIZZLE。GLM_SWIZZLE已弃用。
#define GLM_FORCE_SWIZZLE
#include "glm/glm.hpp"然后你可以像这样使用它:
return world1.yx();在一些编译器上,你也可以这样做:
return world1.yx;警告:请注意,如果启用它,将会对性能产生巨大的影响。在Visual Studio2013上,我测量了运行时矩阵乘法的x150速度差异。
使用swizzle操作:每秒450,000次乘法。
不使用swizzle操作:每秒65,000,000次乘法。
https://stackoverflow.com/questions/23882773
复制相似问题