關于OpenGL中通過鼠標平移縮放平行投影圖像

前言

這是我第一次在簡書上發表一些個人的筆記或經驗,可能沒什么人看,我也盡量寫清楚一些。(個人的語言表達有些差,當作鍛煉鍛煉,不喜勿噴)
  這個標題我自己都感覺有些啰嗦,大概意思就是:使用C++和開源庫 freeglut 在 Visuai Studio 2015 上編寫的一個可以 通過鼠標操作圖形的縮放,移動等功能的小demo。我這片文章不會詳細介紹OpenGL的一些函數說明,需要大家自行搜索。
  當然在最后,我會提供代碼的下載地址。

正文

1.效果實現的核心思想.

就是為了維護一個矩形的四個數值(left,right,bottom,top)。矩陣左下角為(left,bottom),右上角角為(right,top)。看到這里我想到大家都猜到是“glOrtho”這個函數了,核心就是為了維護這個函數的一個在freeglut的一個封裝”gluOrtho2D“。
  在我的理解中,gluOrtho2D這個函數通常是和”glViewPort“一起使用。
  gluOrtho2D:叫做正射投影,或者叫做平行投影。形象的說就是生成我們了解的正視圖,俯視圖,側視圖類似的圖像。但是它不是將圖形的”正視圖“給畫出來,而是只畫出局部的”正視圖“,這個局部的范圍就是由上面那四個數字確定。
  glViewPort:設置我們的窗口尺寸大小。這個函數和”gluOrtho2D“可以這樣聯系起來:我們有一個能夠拍攝平行投影的數碼相機,我們可以通過”gluOrtho2D“來選取我們要拍攝風景的哪個局部,通過”glViewPort“設置我們通過這個相機獲取照片保存的像素尺寸大小。
  現在,我們就是通過維護這四個數值來達到我們demo的希望的效果。

2.實現平移

首先我們先聲明一個函數:
    void move (int x0 ,int y0 ,int x1 ,int y1)
  注意:我們默認顯示窗口的像素尺寸為( width,height ),且之后的代碼里面出現,定義與此一樣。還有窗口坐標和我們的opengl默認坐標系不一樣。OpenGL默認的是左下角為(0,0),x軸水平向右增加,y軸豎子向上增加。而窗口坐標系 是以左上角為(0,0),x軸水平向右增加,y軸豎子向下增加。
  函數定義說明:坐標(x0,y0)是鼠標拖動時的初始的窗口坐標,坐標(x1,y1)是鼠標拖動后,希望移動到的窗口坐標。
    double _x = -(x1 - x0);
    double _y = +(y1 - y0);
    double c_x = (right - left) / double(width);
    double c_y = (top - bottom) / double(height);
    _x *= c_x;
    _y *= c_y;
    right+=_x;
    left+=_x;
    top+=_y;
    bottom+=_y;
    /*...更新opengl的一些設置包括 gluOrtho2D 和 glViewPort */
  第1,2行是求在窗口坐標中的差值。
  第3,4行是求窗口尺寸和正射投影的尺寸的比例關系
  第5,6行是講窗口坐標平移尺寸映射到正射投影的世界坐標系中。
  第7-10行是更新這四個數值,改變它們達到圖像跟隨鼠標移動的效果
  第11,行,看注釋說明,我們也了解是重新設置OpenGL的一些參數,具體可以看最后的代碼。

3.實現縮放

同樣,我需要先定義下我們的函數
    void scale(int x, int y, double s_x, double s_y)
  對函數的中參數定義如下:
    (x,y)是窗口坐標系的坐標,是我們的縮放的中心。
    (s_x,s_y) 是縮放的比例,小于1.0是縮小,大于1.0是放大,等于1.0 沒有什么變化。
  下面是實現代碼:

auto p = this->getWorldPoint(x, y);
left = p.x-(p.x - left) / s_x;
bottom = p.y-(p.y - bottom) / s_y;
right = p.x+(right  - p.x) / s_x;
top = p.y+(top - p.y) / s_y; 

先通過”getWorldPoint“求出( x,y)在正射投影的世界的對應坐標 p 。接下來為了保證 p 在新的投影矩陣中的相對位置不變。對這四個值進行了單獨更新。后四行代碼,自己可以通過簡單例子推算的。
  有關地方值得注意,我們的這后四行代碼都是除以它們對應的縮放倍數。原因和我們的使用放大鏡類似,假設我們的放大鏡的鏡片面積不變。我改變放大鏡的放大倍數后,我們通過放大鏡看到的真實場景的面積是是變小的,反正依然。所以當我們要放大時,我們就要減小這個正視投影的矩陣大小,反正則增加。

雜項 (未補齊)

1.getWorldPoint(得到窗口坐標對應的世界坐標)
2.代碼下載地址

日志

  1. 于2016年11月05日第一次編寫,添加主要內容。計劃于下次補充一些圖片,和編寫 ”雜項“
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容