Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/134.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 使用glOrtho缩放到鼠标位置_C++_Opengl_Zooming_Mouse - Fatal编程技术网

C++ 使用glOrtho缩放到鼠标位置

C++ 使用glOrtho缩放到鼠标位置,c++,opengl,zooming,mouse,C++,Opengl,Zooming,Mouse,目前,我正在使用glOrtho缩放和平移正在渲染的2D图形 我已将视口设置为标准宽度和高度。然后,我将glOrtho设置为使我的frustrum使屏幕坐标与世界坐标匹配 glViewport(0, 0, window_width,window_height); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0, window_width,window_height,0 , 100, -100); 当我在我的鼠标回调中执行缩放功能

目前,我正在使用glOrtho缩放和平移正在渲染的2D图形

我已将视口设置为标准宽度和高度。然后,我将glOrtho设置为使我的frustrum使屏幕坐标与世界坐标匹配

glViewport(0, 0, window_width,window_height);

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, window_width,window_height,0 , 100, -100);
当我在我的鼠标回调中执行缩放功能时,我用缩放因子乘以平截体边缘

glOrtho( 0 * zoomOut,
window_width * zoomOut,
window_height * zoomOut,
0 * zoomOut, 
100, -100);
我的问题是。。。。如何使用鼠标位置作为中心进行缩放

我试过这个。。。(其中mouseStoreX和mouseStoreY是第一次单击时存储的位置)

这似乎是可行的,但当我点击一个新的按钮时,它会跳转。我想在做鼠标位置存储时,我没有考虑到zoomOut因素

编辑:这是我的最新代码,我仍然在挣扎

void ZoomOrtho(){ //ON MOUSE CLICK.....

if (zooming == false){
keyStore.LMx = keyStore.Mx;   //store mouse pos for next comparison
keyStore.LMy = keyStore.My;
//get mouse pos
mouseStoreX = keyStore.Mx;//mouse pos at this moment
mouseStoreY = keyStore.My;

//get current projection matrices
glGetDoublev( GL_MODELVIEW_MATRIX, modelview );
glGetDoublev( GL_PROJECTION_MATRIX, projection );
glGetIntegerv( GL_VIEWPORT, viewport );
//flip Y for opengl reasons
winY = (float)viewport[3] - winY;
//get world mouse coordinate
gluUnProject( mouseStoreX, mouseStoreY , 0.0, modelview, projection, viewport, &posX_,&posY_, &posZ_);

// calc difference between mouse world pos and centre of 'camera'
dx = posX_ - FS.centerX;
dy = posY_ - FS.centerY;

}
//ON DRAG......
zooming = true;

//do mouse movement detection and increment zoomOut
//#################################################
int xDiff = keyStore.Mx - keyStore.LMx;  //mouse drag difference in screen space just  for incrementing zoom
int yDiff = keyStore.My - keyStore.LMy;  //

if (xDiff > 0 && (zoomFactor >= 0.5 ) )   {
zoomFactor -= zoomInc;
if  (zoomFactor < 0.5 ) {zoomFactor = 0.5;}
}
else if (xDiff < 0 && (zoomFactor <= 2.0 ))  {
zoomFactor += zoomInc;
if (zoomFactor > 2.0){zoomFactor = 2.0;}
}
//#################################################


//fill structure with clipping plane values. zooms ortho projection and keeps mouse pos anchored.
FS.left =  ((FS.centerX - dx - (window_width/2.0))*zoomFactor) +dx;
FS.right = ((FS.centerX -dx + (window_width/2.0))*zoomFactor)+dx ;
FS.bottom = ((FS.centerY -dy + (window_width/2.0))*zoomFactor)+dy;
FS.top =    ((FS.centerY -dy  - (window_width/2.0))*zoomFactor) +dy;

// store last mouse pos for next comparison.
keyStore.LMx = keyStore.Mx;
keyStore.LMy = keyStore.My;

}

void zoomRelease(){

cout << " releasing" << std::endl;
//set zoom to false so we know we are not draggin mouse anymore.
zooming = false;
keyStore.LMx = 0;
keyStore.LMy = 0;

// recenter by taking midpoint between new left and right clipping planes so dx has a reference point
FS.centreX = (FS.right-FS.left)/2.0;

}

void DrawGui(){

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(FS.left, FS.right,FS.bottom, FS.top, 1, -1);

glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
//do drawing

} 
void zoomotho(){//鼠标单击。。。。。
如果(缩放==假){
keyStore.LMx=keyStore.Mx;//存储鼠标位置以便下次比较
keyStore.LMy=keyStore.My;
//获取鼠标位置
mouseStoreX=keyStore.Mx;//此时鼠标位置
mouseStoreY=keyStore.My;
//获取当前投影矩阵
glGetDoublev(GL_模型视图_矩阵,模型视图);
glGetDoublev(GL_投影矩阵,投影);
glGetIntegerv(GL_视口,视口);
//出于opengl的原因翻转Y
winY=(浮动)视口[3]-winY;
//获取世界鼠标坐标
gluUnProject(mouseStoreX、mouseStoreY、0.0、modelview、投影、视口和posX、posY和posZ);
//鼠标世界位置和“相机”中心之间的计算差异
dx=posX_u3;-FS.centerX;
dy=posY_ufs.centerY;
}
//拖拉。。。。。。
缩放=真;
//执行鼠标移动检测和增量缩放
//#################################################
int xDiff=keyStore.Mx-keyStore.LMx;//鼠标拖动屏幕空间中的差异只是为了增加缩放
int-yDiff=keyStore.My-keyStore.LMy//
如果(xDiff>0&(zoomFactor>=0.5)){
zoomFactor-=zoomInc;
如果(zoomFactor<0.5){zoomFactor=0.5;}
}
else如果(xDiff<0&(zoomFactor 2.0){zoomFactor=2.0;}
}
//#################################################
//用剪切平面值填充结构。缩放正交投影并保持鼠标位置固定。
FS.left=((FS.centerX-dx-(窗口宽度/2.0))*zoomFactor)+dx;
FS.right=((FS.centerX-dx+(窗口宽度/2.0))*zoomFactor)+dx;
FS.bottom=((FS.centerY-dy+(窗口宽度/2.0))*zoomFactor)+dy;
FS.top=((FS.centerY-dy-(窗口宽度/2.0))*zoomFactor)+dy;
//存储最后一个鼠标位置以便下次比较。
keyStore.LMx=keyStore.Mx;
keyStore.LMy=keyStore.My;
}
void zoomRelease(){

cout我假设当你进行第二次点击时,你正在将其值存储到mouseStoreXY中。如果是这样,这会导致跳转。你在用旧mouseStoreXY的偏移量绘图,然后突然偏移到新的mouseStoreXY

解决方案是持久存储投影矩阵输入,然后在每一帧上增量修改它们。

试一试:

// g++ main.cpp -o main -lglut -lGL && ./main
#include <GL/glut.h>

double centerX = 0, centerY = 0;
double width = 0, height = 0;
void mouse( int button, int state, int mx, int my )
{
    // flip mouse y axis so up is +y
    my = glutGet( GLUT_WINDOW_HEIGHT ) - my;

    // convert mouse coords to (-1/2,-1/2)-(1/2, 1/2) box
    double x = ( mx / (double)glutGet( GLUT_WINDOW_WIDTH ) ) - 0.5;
    double y = ( my / (double)glutGet( GLUT_WINDOW_HEIGHT ) ) - 0.5;

    if( GLUT_UP == state )
    {
        double preX = ( x * width );
        double preY = ( y * height );

        double zoomFactor = 1.5;
        if( button == GLUT_LEFT_BUTTON )
        {
            // zoom in
            width /= zoomFactor;
            height /= zoomFactor;
        }
        if( button == GLUT_RIGHT_BUTTON )
        {
            // zoom out
            width *= zoomFactor;
            height *= zoomFactor;
        }

        double postX = ( x * width );
        double postY = ( y * height );

        // recenter
        centerX += ( preX - postX );
        centerY += ( preY - postY );
    }

    glutPostRedisplay();
}

void display()
{
    glClear( GL_COLOR_BUFFER_BIT );

    glMatrixMode( GL_PROJECTION );
    glLoadIdentity();
    glOrtho
        (
        centerX - ( width / 2.0 ),
        centerX + ( width / 2.0 ),
        centerY - ( height / 2.0 ),
        centerY + ( height / 2.0 ),
        -1,
        1     
        );

    glMatrixMode( GL_MODELVIEW );
    glLoadIdentity();

    glColor3ub( 255, 0, 0 );
    glBegin( GL_TRIANGLES );
    glVertex2i( 0, 0 );
    glVertex2i( 150, 0 );
    glVertex2i( 0, 150 );
    glVertex2i( 0, 0 );
    glVertex2i( -150, 0 );
    glVertex2i( 0, -150 );
    glEnd();

    glutSwapBuffers();
}

int main( int argc, char **argv )
{
    glutInit( &argc, argv );
    glutInitDisplayMode( GLUT_RGBA | GLUT_DOUBLE );
    glutInitWindowSize( 600, 600 );
    glutCreateWindow( "GLUT" );
    glutDisplayFunc( display );
    glutMouseFunc( mouse );

    width = glutGet( GLUT_WINDOW_WIDTH );
    height = glutGet( GLUT_WINDOW_HEIGHT );    

    glutMainLoop();
    return 0;
}
// g++ main.cpp -o main -lglut -lGL && ./main
#include <GL/glut.h>
#include <cmath>

void getMouseCoords( int mx, int my, double& x, double& y )
{
    // flip mouse y axis so up is +y
    my = glutGet( GLUT_WINDOW_HEIGHT ) - my;

    // convert mouse coords to (-1/2,-1/2)-(1/2, 1/2) box
    x = ( mx / (double)glutGet( GLUT_WINDOW_WIDTH ) ) - 0.5;
    y = ( my / (double)glutGet( GLUT_WINDOW_HEIGHT ) ) - 0.5;
}

int btn;
double baseX, baseY;
double baseWidth, baseHeight;

double centerX = 0, centerY = 0;
double width = 0, height = 0;
void mouse( int button, int state, int mx, int my )
{
    baseWidth = width;
    baseHeight = height;
    btn = button;
    getMouseCoords( mx, my, baseX, baseY );
}

void motion( int mx, int my )
{
    if( btn != GLUT_LEFT_BUTTON )
    {
        return;
    }

    double x, y;
    getMouseCoords( mx, my, x, y );

    double preX = ( baseX * width );
    double preY = ( baseY * height );

    double zoomFactor = exp( baseY - y );
    width = baseWidth * zoomFactor;
    height = baseHeight * zoomFactor;

    double postX = ( baseX * width );
    double postY = ( baseY * height );

    // recenter
    centerX += ( preX - postX );
    centerY += ( preY - postY );

    glutPostRedisplay();
}

void display()
{
    glClear( GL_COLOR_BUFFER_BIT );

    glMatrixMode( GL_PROJECTION );
    glLoadIdentity();
    glOrtho
        (
        centerX - ( width / 2.0 ),
        centerX + ( width / 2.0 ),
        centerY - ( height / 2.0 ),
        centerY + ( height / 2.0 ),
        -1,
        1     
        );

    glMatrixMode( GL_MODELVIEW );
    glLoadIdentity();

    glColor3ub( 255, 0, 0 );
    glBegin( GL_TRIANGLES );
    glVertex2i( 0, 0 );
    glVertex2i( 150, 0 );
    glVertex2i( 0, 150 );
    glVertex2i( 0, 0 );
    glVertex2i( -150, 0 );
    glVertex2i( 0, -150 );
    glEnd();

    glutSwapBuffers();
}

int main( int argc, char **argv )
{
    glutInit( &argc, argv );
    glutInitDisplayMode( GLUT_RGBA | GLUT_DOUBLE );
    glutInitWindowSize( 600, 600 );
    glutCreateWindow( "GLUT" );
    glutDisplayFunc( display );
    glutMouseFunc( mouse );
    glutMotionFunc( motion );

    width = glutGet( GLUT_WINDOW_WIDTH );
    height = glutGet( GLUT_WINDOW_HEIGHT );    

    glutMainLoop();
    return 0;
}
//g++main.cpp-o main-lglut-lGL&&./main
#包括
双中心X=0,中心Y=0;
双宽=0,高=0;
无效鼠标(int按钮、int状态、int mx、int my)
{
//翻转鼠标y轴,使其向上为+y
my=glutGet(GLUT\u窗口\u高度)-my;
//将鼠标坐标转换为(-1/2,-1/2)-(1/2,1/2)框
双x=(mx/(双)glutGet(GLUT_窗口_宽度))-0.5;
双y=(我的/(双)glutGet(GLUT_窗口_高度))-0.5;
if(GLUT_UP==状态)
{
双preX=(x*宽度);
双猎物=(y*高度);
双变焦因子=1.5;
如果(按钮==GLUT\u左按钮)
{
//放大
宽度/=缩放因子;
高度/=动物因子;
}
如果(按钮==GLUT\u右按钮)
{
//缩小
宽度*=缩放因子;
高度*=缩放因子;
}
双postX=(x*宽度);
双立柱y=(y*高度);
//重新居中
centerX+=(前置-后置);
centerY+=(猎物-postY);
}
再发现();
}
无效显示()
{
glClear(GLU颜色缓冲位);
glMatrixMode(GL_投影);
glLoadIdentity();
格洛托
(
centerX-(宽度/2.0),
centerX+(宽度/2.0),
中心-(高度/2.0),
centerY+(高度/2.0),
-1,
1.
);
glMatrixMode(GLU模型视图);
glLoadIdentity();
glColor3ub(255,0,0);
glBegin(GL_三角形);
glVertex2i(0,0);
glVertex2i(150,0);
glVertex2i(0150);
glVertex2i(0,0);
glVertex2i(-150,0);
glVertex2i(0,-150);
格伦德();
glutSwapBuffers();
}
int main(int argc,字符**argv)
{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
glutInitWindowSize(600600);
GLUT(GLUT);
glutDisplayFunc(显示器);
glutMouseFunc(小鼠);
宽度=glutGet(GLUT\u窗口\u宽度);
高度=glutGet(GLUT\u窗口\u高度);
glutMainLoop();
返回0;
}
试一试:

// g++ main.cpp -o main -lglut -lGL && ./main
#include <GL/glut.h>

double centerX = 0, centerY = 0;
double width = 0, height = 0;
void mouse( int button, int state, int mx, int my )
{
    // flip mouse y axis so up is +y
    my = glutGet( GLUT_WINDOW_HEIGHT ) - my;

    // convert mouse coords to (-1/2,-1/2)-(1/2, 1/2) box
    double x = ( mx / (double)glutGet( GLUT_WINDOW_WIDTH ) ) - 0.5;
    double y = ( my / (double)glutGet( GLUT_WINDOW_HEIGHT ) ) - 0.5;

    if( GLUT_UP == state )
    {
        double preX = ( x * width );
        double preY = ( y * height );

        double zoomFactor = 1.5;
        if( button == GLUT_LEFT_BUTTON )
        {
            // zoom in
            width /= zoomFactor;
            height /= zoomFactor;
        }
        if( button == GLUT_RIGHT_BUTTON )
        {
            // zoom out
            width *= zoomFactor;
            height *= zoomFactor;
        }

        double postX = ( x * width );
        double postY = ( y * height );

        // recenter
        centerX += ( preX - postX );
        centerY += ( preY - postY );
    }

    glutPostRedisplay();
}

void display()
{
    glClear( GL_COLOR_BUFFER_BIT );

    glMatrixMode( GL_PROJECTION );
    glLoadIdentity();
    glOrtho
        (
        centerX - ( width / 2.0 ),
        centerX + ( width / 2.0 ),
        centerY - ( height / 2.0 ),
        centerY + ( height / 2.0 ),
        -1,
        1     
        );

    glMatrixMode( GL_MODELVIEW );
    glLoadIdentity();

    glColor3ub( 255, 0, 0 );
    glBegin( GL_TRIANGLES );
    glVertex2i( 0, 0 );
    glVertex2i( 150, 0 );
    glVertex2i( 0, 150 );
    glVertex2i( 0, 0 );
    glVertex2i( -150, 0 );
    glVertex2i( 0, -150 );
    glEnd();

    glutSwapBuffers();
}

int main( int argc, char **argv )
{
    glutInit( &argc, argv );
    glutInitDisplayMode( GLUT_RGBA | GLUT_DOUBLE );
    glutInitWindowSize( 600, 600 );
    glutCreateWindow( "GLUT" );
    glutDisplayFunc( display );
    glutMouseFunc( mouse );

    width = glutGet( GLUT_WINDOW_WIDTH );
    height = glutGet( GLUT_WINDOW_HEIGHT );    

    glutMainLoop();
    return 0;
}
// g++ main.cpp -o main -lglut -lGL && ./main
#include <GL/glut.h>
#include <cmath>

void getMouseCoords( int mx, int my, double& x, double& y )
{
    // flip mouse y axis so up is +y
    my = glutGet( GLUT_WINDOW_HEIGHT ) - my;

    // convert mouse coords to (-1/2,-1/2)-(1/2, 1/2) box
    x = ( mx / (double)glutGet( GLUT_WINDOW_WIDTH ) ) - 0.5;
    y = ( my / (double)glutGet( GLUT_WINDOW_HEIGHT ) ) - 0.5;
}

int btn;
double baseX, baseY;
double baseWidth, baseHeight;

double centerX = 0, centerY = 0;
double width = 0, height = 0;
void mouse( int button, int state, int mx, int my )
{
    baseWidth = width;
    baseHeight = height;
    btn = button;
    getMouseCoords( mx, my, baseX, baseY );
}

void motion( int mx, int my )
{
    if( btn != GLUT_LEFT_BUTTON )
    {
        return;
    }

    double x, y;
    getMouseCoords( mx, my, x, y );

    double preX = ( baseX * width );
    double preY = ( baseY * height );

    double zoomFactor = exp( baseY - y );
    width = baseWidth * zoomFactor;
    height = baseHeight * zoomFactor;

    double postX = ( baseX * width );
    double postY = ( baseY * height );

    // recenter
    centerX += ( preX - postX );
    centerY += ( preY - postY );

    glutPostRedisplay();
}

void display()
{
    glClear( GL_COLOR_BUFFER_BIT );

    glMatrixMode( GL_PROJECTION );
    glLoadIdentity();
    glOrtho
        (
        centerX - ( width / 2.0 ),
        centerX + ( width / 2.0 ),
        centerY - ( height / 2.0 ),
        centerY + ( height / 2.0 ),
        -1,
        1     
        );

    glMatrixMode( GL_MODELVIEW );
    glLoadIdentity();

    glColor3ub( 255, 0, 0 );
    glBegin( GL_TRIANGLES );
    glVertex2i( 0, 0 );
    glVertex2i( 150, 0 );
    glVertex2i( 0, 150 );
    glVertex2i( 0, 0 );
    glVertex2i( -150, 0 );
    glVertex2i( 0, -150 );
    glEnd();

    glutSwapBuffers();
}

int main( int argc, char **argv )
{
    glutInit( &argc, argv );
    glutInitDisplayMode( GLUT_RGBA | GLUT_DOUBLE );
    glutInitWindowSize( 600, 600 );
    glutCreateWindow( "GLUT" );
    glutDisplayFunc( display );
    glutMouseFunc( mouse );
    glutMotionFunc( motion );

    width = glutGet( GLUT_WINDOW_WIDTH );
    height = glutGet( GLUT_WINDOW_HEIGHT );    

    glutMainLoop();
    return 0;
}
//g++main.cpp-o main-lglut-lGL&&./main
#包括
#包括
void getMouseCoords(int-mx、int-my、double&x、double&y)
{
//翻转鼠标y轴,使其向上为+y
my=glutGet(GLUT\u窗口\u高度)-my;
//将鼠标坐标转换为(-1/2,-1/2)-(1/2,1/2)框
x=(mx/(双)glutGet(GLUT_窗口_宽度))-0.5;
y=(我的/(双)glutGet(GLUT_窗口_高度))-0.5;
}
国际电话号码;
双基x,基y;
双底宽,底高;
双中心X=0,中心Y=0;
双宽=0,高=0;
无效鼠标(int按钮、int状态、int mx、int my)
{
baseWidth=宽度;
基准高度=高度;
btn=按钮;
GetMouseCoods(mx、my、baseX、baseY);
}
无效运动(int mx,int my)
{
如果(btn!=GLUT\u左按钮)
{
返回;
}
双x,y;
getMouseCoords(mx,my,x,y);
双preX=(baseX*宽度);
双猎物=(贝西*黑格)
# Translate graphics
glTranslatef(0.0, 0.0, (self.translation[1]/100.0) * (math.tan(self.cameraPosition[0]/self.cameraPosition[1])))
glTranslatef(0.0, (self.translation[0]/100.0) * (math.tan(self.cameraPosition[0]/self.cameraPosition[1])), 0.0)

# Set Perspective
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
gluPerspective(self.zoomFactor, float(width)/float(height), self.nearPlane, self.farPlane)

# Render Scene
glMatrixMode(GL_MODELVIEW)
...Draw stuff here...