2013-02-19 2 views
3

В настоящее время я использую glOrtho для масштабирования и панорамирования 2D-графика, который я представляю.Масштабирование в положение мыши с использованием glOrtho

У меня настроено окно просмотра стандартной ширины и высоты. Затем я устанавливаю 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 это позиция сохраняется при первом щелчке)

glOrtho((0 -mouseStoreX)* zoomOut + mouseStoreX, 
(window_width - mouseStoreX) * zoomOut + mouseStoreX, 
(window_height - mouseStoreY) * zoomOut + mouseStoreY, 
(0 - mouseStoreY) * zoomOut + mouseStoreY, 
100, -100); 

Это похоже на работу, но усеченной прыгает вокруг, когда я делаю новый щелчок. Я думаю, что где-то я не учитываю фактор zoomOut при сохранении положения мыши.

EDIT * * ** * ** * **** здесь мой последний код, который я до сих пор борется с ...

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 

} 

ответ

0

Я предполагаю, что, когда вы делаете второй щелчок, вы сохраняете его значение в mouseStoreXY. Если это так, это вызывает прыжки. Вы рисовали со смещением старого mouseStoreXY, и вы внезапно смещались на новый.

Решение будет заключаться в постоянном хранении проекционных матричных входов, а затем их постепенном изменении на каждом кадре.

+0

Да, я понимаю это сейчас. Сейчас я пытаюсь отслеживать смещения, но не могу получить его точно на данный момент. Спасибо, ваша помощь. – user2089130

+0

У меня такая же проблема: что это означает, что это происходит постепенно? – paulm

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

спасибо за ваш ответ. Ваша информация полезна, но не совсем то, что я хотел. Я пытаюсь масштабировать, перетаскивая мышь. Теперь я пытаюсь непроектировать координаты экрана в мировые координаты, а затем отбрасывать центральное значение, когда я освобождаю мышь.Цель состоит в том, чтобы перетащить мышь, и точка под мышью будет точкой опоры. – user2089130

+0

У меня сейчас это работает. Я был до того, как непроектировал координаты мыши в мировое пространство, исчисляя смещения и повторное включение после выхода мыши, но все еще получал странные прыжки, которые я не мог отследить. Я думаю, что это было связано не с конкатенированием преобразований. Это решение намного проще. Однако я добавил свою собственную настройку, которая должна была инвертировать zoomfactor (1/zoomfactor), если baseY был отрицательным. – user2089130

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

Да, это именно то поведение. Огромное спасибо. Я должен уметь это работать в моем коде. Я почти понял это, но вы сделали это очень ясно. Я бы купил тебе пинту, хороший сэр! – user2089130

+0

На самом деле я не могу заставить это работать с панорамированием. Я изменил свой код выше, чтобы показать, что я делал ранее. – user2089130

0

Если вы хотите пойти по другому пути и просто использовать glTranslate и gluPerspective, вы можете получение идеальные тот же эффект. Событие мыши для колеса прокрутки (с помощью PyOpenGL) может выглядеть примерно так:

def MouseWheelScroll(self, event): 
    """Called when the mouse's scroll wheel is scrolled up or down. This modifies the zoomFactor 
    which renders the graphics closer or further away on the screen. It also translates the graphics 
    slightly based on the position of the mouse. This creates an effect of zooming to the location 
    of the mouse on the screen. 
    """ 
    scrolledUp = event.GetWheelRotation() # Returns positive for up, negative for down 
    self.x, self.y = event.GetPosition() 

    viewport = glGetIntegerv(GL_VIEWPORT) 
    width = viewport[2] 
    height = viewport[3] 
    centerX = width/2.0 
    centerY = height/2.0 

    # Make sure cursor is on the screen 
    if ((self.x > 0 and self.x < width) and (self.y > 0 and self.y < height)): 
     if (scrolledUp > 0): 
      self.zoomFactor -= 2.0 
      self.translation[0] -= (self.x - centerX) 
      self.translation[1] += (self.y - centerY) 
     else: 
      self.zoomFactor += 2.0 
      self.translation[0] += (self.x - centerX) 
      self.translation[1] += (self.y - centerY) 

     if (self.zoomFactor > 150.0): 
      self.zoomFactor = 150.0 
     elif (self.zoomFactor < 0.1): 
      self.zoomFactor = 0.1 

    self.Refresh(False) 

Вы бы тогда просто нужно перевести графику, настроить перспективу, а затем визуализировать сцену.

# 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... 
Смежные вопросы