2013-02-19 75 views
3

目前我使用glOrtho進行縮放和平移二維圖我繪製鼠標位置。縮放使用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因素。

編輯* * ** * ** * ****這裏是我的最新的代碼,我還在掙扎......

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 2013-02-22 05:57:56

+0

我有同樣的問題 - 這意味着什麼增量? – paulm 2014-02-03 08:59:41

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 2013-02-22 05:54:22

+0

我現在有這個工作。我在將鼠標座標放入世界空間之前,在鼠標釋放之後計算偏移量並重新編輯,但仍然出現了我無法追蹤的奇怪跳轉。我認爲這是由於不連接轉換。這個解決方案更直截了當。但是我做了自己的調整,如果baseY爲負值,那麼就會反轉zoomfactor(1/zoomfactor)。 – user2089130 2013-02-25 22:21:25

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 2013-02-23 12:49:30

+0

其實我實際上無法得到這個與平移工作。我編輯了上面的代碼以顯示我以前在做什麼。 – user2089130 2013-02-26 21:02:54

0

如果你想要去一個不同的路線,只需使用glTranslate和gluPerspective,你可以acheive同樣的效果。 (選用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...