SharpGL學習筆記(二) 模型變換

来源:http://www.cnblogs.com/hackpig/archive/2016/08/17/5781944.html
-Advertisement-
Play Games

(二) 模型變換 模形變換就是指的在世界坐標系中(world space)做“移動”,“旋轉", "縮放"三種操作。 首先要說明的,在Opengl中,是用4x4矩陣進行坐標變換,OpenGL的4x4矩陣是按列排列的,就像下麵這樣。 所謂的模型變換,就是對這個矩陣進行變換。 描述三維世界你就得先設計三 ...


(二) 模型變換

 

模形變換就是指的在世界坐標系中(world space)做“移動”,“旋轉", "縮放"三種操作。

首先要說明的,在Opengl中,是用4x4矩陣進行坐標變換,OpenGL的4x4矩陣是按列排列的,就像下麵這樣。

所謂的模型變換,就是對這個矩陣進行變換。

 

描述三維世界你就得先設計三維模形。 在設計三維模形的時候,它是們於模形坐標系中的,最終它會放置到世界坐標系統中,如果這個模形設計時處理的好的話,放到世界坐標系中時預設就是模形的中心定位於世界坐標系統的中心處。

這裡有一個延伸的知識點:模形放置到世界坐標系時中心不位於世界坐標系中心處,是怎麼回事?有什麼後果?  這個以後我們會做一個擴展性的討論。

 

上面說的是導入其它設計軟體製作的模形,比如3dsMax製作的模形的情況。如果我們自己用代碼畫的模形,自然是預設就位於世界坐標系統的中心。

這個世界坐標系,就像下圖一樣:

X軸箭頭方向為正,反過來為負

Y軸箭頭方向為正,反過來為負

Z軸箭頭方向正好指向我們的眼睛,因此圖上只是個小點,看不見,它負方向向屏幕裡面。

而下圖中的三維體的中心就剛好們於這個世界坐標系的中心。

 

 下麵的演示代碼在世界坐標系統中畫出一個三角形,再對它做一些變換操作。

  1 using System;
  2 using System.Windows.Forms;
  3 using SharpGL;
  4 
  5 namespace blankTest
  6 {
  7     public partial class Form1 : Form
  8     {
  9         private int mtype = 0;
 10         public Form1()
 11         {
 12             InitializeComponent();
 13 
 14         }
 15 
 16         private void Form1_Load(object sender, EventArgs e)
 17         {
 18 
 19         }
 20 
 21         private void openGLControl1_OpenGLInitialized(object sender, EventArgs e)
 22         {
 23 
 24         }
 25 
 26         private void openGLControl1_Resize(object sender, EventArgs e)
 27         {
 28         
 29         }
 30 
 31         private void openGLControl1_OpenGLDraw(object sender, PaintEventArgs e)
 32         {
 33             SharpGL.OpenGL gl = this.openGLControl1.OpenGL;
 34 
 35             gl.ClearColor(0, 0, 0, 1);
 36             gl.Clear(OpenGL.GL_COLOR_BUFFER_BIT | OpenGL.GL_DEPTH_BUFFER_BIT);
 37 
 38             switch (mtype)
 39             {
 40                 case 0:
 41                     translateSample(gl);
 42                     break;
 43                 case 1:
 44                     rotateSample(gl);
 45                     break;
 46                 case 2:
 47                     scaleSample(gl);
 48                     break;
 49             }
 50             
 51             gl.Finish();
 52             gl.Flush();
 53         }
 54 
 55         private void scaleSample(SharpGL.OpenGL gl)
 56         {
 57             gl.LoadIdentity();
 58             gl.Scale(1f, 1f, 1f);
 59             gl.Translate(0, 0, -9f);
 60             drawPT(gl);
 61 
 62             gl.LoadIdentity();
 63             gl.Scale(5f, 1f, 1f);
 64             gl.Translate(0, 1, -9f);
 65             drawPT(gl);
 66         }
 67 
 68         private void rotateSample(SharpGL.OpenGL gl)
 69         {
 70             gl.LoadIdentity();
 71             gl.Rotate(0,0, 45);
 72             gl.Translate(0, 0, -8f);
 73             drawPT(gl);
 74 
 75             gl.Rotate(0, 0, 45);
 76             gl.Translate(-1, 1,0f);
 77             drawPT(gl);
 78         }
 79 
 80         private void translateSample(SharpGL.OpenGL gl)
 81         {
 82             gl.LoadIdentity();
 83             gl.Translate(0f, 0f, -3f);
 84             drawPT(gl);
 85 
 86             gl.LoadIdentity();
 87             gl.Translate(0f, 1f, -3f);
 88             drawPT(gl);
 89         }
 90 
 91         private void drawPT(SharpGL.OpenGL gl)
 92         {
 93             gl.PointSize(5f);
 94             gl.Begin(OpenGL.GL_TRIANGLES);
 95             {
 96                 gl.Vertex(0.0f, 0f, 0.0f);
 97                 gl.Vertex(-1.0f, -1f, 0.0f);
 98                 gl.Vertex(1.0f, -1f, 0.0f);
 99             }
100             gl.End();
101         }
102 
103         private void btnTranslate_Click(object sender, EventArgs e)
104         {
105             switch (((Button)sender).Name)
106             {
107                 case "btnTranslate":
108                     mtype = 0;
109                     break;
110                 case "btnRotate":
111                     mtype = 1;
112                     break;
113                 case "btnScale":
114                     mtype = 2;
115                     break;
116             }
117         }
118 
119     }
120 }

 三個函數translateSample(),  rotateSample(),scaleSample() 分別演示”平移“,”旋轉“,”縮放”。

我們來談談一些重點的地方:

 

在“平移”函數中,如果沒有gl.LoadIdentity()函數複位坐標系統到原點位置,那麼執行結果會不同,第二條gl.Translate(0f,1f,-3f)將會是相對於上一條gl.Translate的位置(0f,0f,-3f)移動。

而每次繪製三角形之前做一次gl.LoadIdentity(), 相當於每次繪圖時的中心點坐標都從原點算起。

  private void translateSample(SharpGL.OpenGL gl)
        {
            gl.LoadIdentity();
            gl.Translate(0f, 0f, -3f);
            drawPT(gl);

            gl.LoadIdentity();
            gl.Translate(0f, 1f, -3f);
            drawPT(gl);
        }

gl.Translate中的Z軸設置為0,則物體不可見,因為這時候畫出來的三角形,貼著世界坐標系的Z軸。就像你的眼睛貼跟它零距離一般。

你可以想象成攝像機位於世界坐標系統(0,0,0), 走向Z軸的負方向。

為了說明白這點,博主畫了個示意圖如下:

圖中的柵格面就是世界坐標繫上的的網格線,而三維box的底面(紅色面)貼在世界坐標系的Z軸為0的深度上。你得把這個Box向Z軸的負方向走上-1個或者更多個,才可以看見這個Box.

 

 這段程式的運行效果如下:

平移

 

旋轉

 

縮放

 

本節源代碼下載

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 高效計算——RenderScript RenderScript是安卓平臺上很受谷歌推薦的一個高效計算平臺,它能夠自動把計算任務分配到各個可用的計算核心上,包括CPU,GPU以及DSP等,提供十分高效的並行計算能力。可能是由於應用開發時的需求不夠,關於RenderScript的相關文章很少,剛好我在工 ...
  • 框架簡介 這幾年一直在做ASP.NET開發,幾年前做項目都是老老實實一行行的寫代碼,後來發現那些高手基本都會有自己積累起來的代碼庫,現在稱之為開發框架,基礎代碼不用再去堆,主要精力可以集中在業務邏輯實現上。這樣開發效率高了,他們的待遇也會比我高出很多。我也想有自己的房子、車子、妹子,我也想成為開發高 ...
  • 配置的同步涉及到兩個方面:第一,對原始的配置文件實施監控併在其發生變化之後從新載入配置;第二,配置重新載入之後及時通知應用程式進而使後者能夠使用最新的配置。要瞭解配置同步機制的實現原理,先得從認識一個名為ConfigurationReloadToken的類型開始。 ...
  • 臟檢查 Session到底是如何進行臟檢查的呢?當一個Customer對象被加入到Session緩存中時,Session會為Customer對象的值類型的屬性複製一份快照。當Session清理緩存時,會先進行臟檢查,即比較Customer對象的當前屬性與它的快照,來判斷Customer對象的屬性是否 ...
  • Redis五種數據類型之列表類型 Redis五種數據類型之列表類型。你可以存儲一個有序的字元串列表一類數據。比如你想展示你所存儲的所有文章中的前十條,當分頁取下一頁的時候,你也可以取接下來的十條。所以建議你維護一個文章ID的列表。其內部使用雙向鏈表實現,這意味著在你獲取一段頭部和尾部的數據是極快的, ...
  • WCF服務可以承載與iis、winform、console、window服務中,下麵重點介紹以console為載體,對外提供服務(服務滿足web訪問以及soap方式訪問) 1.服務類的實現 wcf服務類一般有兩種實現方式,下麵分別對兩種方式進行介紹: 1.1 使用介面進行實現 1 namespace ...
  • 這篇關於MVC路由及視圖規則本來是昨天要發的,但是本人真的有點懶,終於今天忍無可忍了。初學MVC的時候比現在還菜一點(現在也很菜),想著會用就行,但是有時還是會好奇,為什麼它能找到控制器?為什麼控制器return View();就能找到視圖,而為什麼視圖一定要建在Views文件下?好像說的有點多了, ...
  • 以前使用log4net的時候老是在糾結配置log4net,總會發生配置文件不生效的情況,最後會發現其實是配置文件沒有拷貝到log4net的運行目錄,還真是糾結。現在好了,通過將文件當作嵌入的資源,然後初始化的時候載入下配置文件,這個問題完美解決。下麵方法如下: 1、將配置文件加入到當前.net相關的 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...