国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開APP
userphoto
未登錄

開通VIP,暢享免費電子書等14項超值服

開通VIP
使用Eclipse RCP進(jìn)行桌面程序開發(fā)(六):向OpenGL進(jìn)軍 - 海邊沫沫 - B...
使用Eclipse RCP進(jìn)行桌面程序開發(fā)(一):快速起步
使用Eclipse RCP進(jìn)行桌面程序開發(fā)(二):菜單、工具欄和對話框
使用Eclipse RCP進(jìn)行桌面程序開發(fā)(三):視圖和透視圖
使用Eclipse RCP進(jìn)行桌面程序開發(fā)(四):在Windows中使用Active X控件
使用Eclipse RCP進(jìn)行桌面程序開發(fā)(五):2D繪圖

看完這一篇,我們應(yīng)該可以使用OpenGL繪制如下圖的場景了。該場景是一個旋轉(zhuǎn)的三菱錐矩陣,下面是旋轉(zhuǎn)到不同方位的截圖:






我整整花了一個星期的時間來研究SWT中的OpenGL,遇到的第一個困難是找不到傳說中的GL類和GLU類,最后,通過搜索引擎終于找到了,原來使用Eclipse進(jìn)行OpenGL開發(fā),還需要另外下載OpenGL插件,如下圖:


這里有OpenGL的類庫,還有一個示例,把類庫下載下來,解壓,放到Eclipse的Plugin目錄下,然后在我們的項目中添加依賴項,就可以看到我們需要使用的類了,如下圖:


我們需要對OpenGL編程的一些基本概念有點了解,在OpenGL中,3D場景不是直接繪制到操作系統(tǒng)的窗口上的,而是有一個稱為著色描述表(Rendering Context)的東西,我們這里簡稱它為context,OpenGL的繪圖命令都是在當(dāng)前context上進(jìn)行繪制,然后再把它渲染到操作系統(tǒng)的設(shè)備描述表(Device Context)上,這里,我們可以簡單的理解成把它渲染到窗口控件上(其實也可以渲染到全屏幕)。

在Windows中使用OpenGL編程比較麻煩,因為我們需要設(shè)置一個叫做象素格式的東西,大家只要看看下面的這段C代碼,就知道我為什么說它麻煩了:
static PIXELFORMATDESCRIPTOR pfd=     //pfd 告訴窗口我們所希望的東東
     {
         sizeof(PIXELFORMATDESCRIPTOR),   
//上訴格式描述符的大小
         1,                  // 版本號
         PFD_DRAW_TO_WINDOW |        // 格式必須支持窗口
         PFD_SUPPORT_OPENGL |        // 格式必須支持OpenGL
         PFD_DOUBLEBUFFER,          // 必須支持雙緩沖
         PFD_TYPE_RGBA,           // 申請 RGBA 格式
         bits,                // 選定色彩深度
         000000,          // 忽略的色彩位
         0,                 // 無Alpha緩存
         0,                 // 忽略Shift Bit
         0,                 // 無聚集緩存
         0000,             // 忽略聚集位
         16,                 // 16位 Z-緩存 (深度緩存) 
         0,                 // 無模板緩存
         0,                 // 無輔助緩存
         PFD_MAIN_PLANE,           // 主繪圖層
         0,                 // 保留
         000               // 忽略層遮罩
     }
;
if (!(PixelFormat=ChoosePixelFormat(hDC,&pfd)))   // Windows 找到相應(yīng)的象素格式了嗎?
    {
        KillGLWindow();               
// 重置顯示區(qū)
        MessageBox(NULL,"Can‘t Find A Suitable PixelFormat.",
            
"ERROR",MB_OK|MB_ICONEXCLAMATION);
        
return FALSE;                // 返回 FALSE
    }

if(!SetPixelFormat(hDC,PixelFormat,&pfd))      // 能夠設(shè)置象素格式么?
    {
        KillGLWindow();               
// 重置顯示區(qū)
        MessageBox(NULL,"Can‘t Set The PixelFormat.","ERROR",MB_OK|MB_ICONEXCLAMATION);
        
return FALSE;                // 返回 FALSE
    }

if (!(hRC=wglCreateContext(hDC)))         // 能否取得著色描述表?
    {
        KillGLWindow();              
// 重置顯示區(qū)
        MessageBox(NULL,"Can‘t Create A GL Rendering Context.",
           
"ERROR",MB_OK|MB_ICONEXCLAMATION);
        
return FALSE;               // 返回 FALSE
    }


在SWT中,我們開發(fā)OpenGL應(yīng)用就要簡單得多,這全部要歸功于org.eclipse.swt.opengl包下面的GLCanvas類和GLData類,使用GLCanvas類可以直接創(chuàng)建一個用于OpenGL渲染的控件,至于設(shè)置象素格式這樣復(fù)雜的問題,它已經(jīng)幫我們解決了,不信你看GLCanvas類的構(gòu)造函數(shù)的實現(xiàn)。

GLCanvas類中的幾個方法代表了我一開始提到的OpenGL的幾個基本概念,setCurrent()方法就是為了把該控件的context設(shè)置為OpenGL的當(dāng)前著色描述表,然后使用GL和GLU類中的方法在當(dāng)前context上進(jìn)行繪圖,繪制完圖形以后,再使用GLCanvas類的swapBuffers()方法交換緩沖區(qū),也就是把context中的3D場景渲染到控件上。

寫到這里,大家肯定認(rèn)為一切問題都應(yīng)該迎刃而解了,然而,我卻碰到了另外一個困難,這個困難就是SWT的OpenGL表現(xiàn)怪異,怎么個怪異呢?請看下面視圖類的代碼:
public void createPartControl(Composite parent) {
        
// TODO 自動生成方法存根
        GLData data = new GLData();
        data.depthSize 
= 1;
        data.doubleBuffer 
= true;
        GLCanvas canvas 
= new GLCanvas(parent, SWT.NO_BACKGROUND, data);
        
//設(shè)置該canvas的context為OpenGL的當(dāng)前context
        if(!canvas.isCurrent()){
            canvas.setCurrent();
        }

        
//這里可以進(jìn)行OpenGL繪圖
        
        
//交換緩存,將圖形渲染到控件上
        canvas.swapBuffers();
    }

按道理,我們應(yīng)該可以得到一個經(jīng)典的3D的黑色場景,但是,我得到的卻是這樣的效果:


相當(dāng)?shù)挠魫灠。褪沁@個問題困擾了我至少一個星期。我把官方網(wǎng)站上的示例看了有看,就是找不到問題的關(guān)鍵所在。直到最后,我用了另外一個線程,每100ms都調(diào)用canvas.swapBuffers()把場景渲染一遍問題才解決。由此可見,之所以回出現(xiàn)上面的問題,主要是因為我們渲染的場景很快會被操作系統(tǒng)的其他繪圖操作所覆蓋,只有不斷的渲染我們才能看到連續(xù)的3D圖形。

我是這樣實現(xiàn)讓3D場景連續(xù)渲染的:
public void createPartControl(Composite parent) {
        
// TODO 自動生成方法存根
        GLData data = new GLData();
        data.depthSize 
= 1;
        data.doubleBuffer 
= true;
        GLCanvas canvas 
= new GLCanvas(parent, SWT.NO_BACKGROUND, data);
        
//將繪圖代碼轉(zhuǎn)移到定時器中
        Refresher rf = new Refresher(canvas);
        rf.run();
    }

Refresher類的代碼如下:
class Refresher implements Runnable {
    
public static final int DELAY = 100;
    
    
private GLCanvas canvas;
    
    
public Refresher(GLCanvas canvas) {
        
this.canvas = canvas;
    }

    
    
public void run() {
        
if (this.canvas != null && !this.canvas.isDisposed()) {
            
if(!canvas.isCurrent()){
                canvas.setCurrent();
            }

            
//這里添加OpenGL繪圖代碼
            canvas.swapBuffers();
            
this.canvas.getDisplay().timerExec(DELAY, this);
        }

    }

  
}

問題解決,得到的效果圖如下:


OK,下面的任務(wù)就是完完全全的使用OpenGL的繪圖功能了,不管你的OpenGL教材使用的是什么操作系統(tǒng)什么編程語言,你都能很簡單的把它的概念拿到這里來使用。

使用OpenGL的第一件事,就是要設(shè)置投影矩陣、透視圖和觀察者矩陣,如果你不知道為什么要這么做,請查看OpenGL的基礎(chǔ)教材,在這里,照搬就行了。為了讓我們的控件在每次改變大小的時候都能夠做這些設(shè)置,我們使用事件監(jiān)聽器,如下:
public void createPartControl(Composite parent) {
        
// TODO 自動生成方法存根
        GLData data = new GLData();
        data.depthSize 
= 1;
        data.doubleBuffer 
= true;
        canvas 
= new GLCanvas(parent, SWT.NO_BACKGROUND, data);
        canvas.addControlListener(
new ControlAdapter() {
            
public void controlResized(ControlEvent e) {
                Rectangle rect 
= canvas.getClientArea();
                GL.glViewport(
00, rect.width, rect.height);
                
                
//選擇投影矩陣
                GL.glMatrixMode(GL.GL_PROJECTION);
                
//重置投影矩陣
                GL.glLoadIdentity();
                
//設(shè)置窗口比例和透視圖
                GLU.gluPerspective(45.0f, (float) rect.width / (float) rect.height, 0.1f100.0f);
                
//選擇模型觀察矩陣
                GL.glMatrixMode(GL.GL_MODELVIEW);
                
//重置模型觀察矩陣
                GL.glLoadIdentity();
                
                
//黑色背景
                GL.glClearColor(0.0f0.0f0.0f0.0f);
                
//設(shè)置深度緩存
                GL.glClearDepth(1.0f);
                
//啟動深度測試
                GL.glEnable(GL.GL_DEPTH_TEST);
                
//選擇深度測試類型
                GL.glDepthFunc(GL.GL_LESS);
                
//啟用陰影平滑
                GL.glShadeModel(GL.GL_SMOOTH);
                
//精細(xì)修正透視圖
                GL.glHint(GL.GL_PERSPECTIVE_CORRECTION_HINT, GL.GL_NICEST);
                
//清除屏幕和深度緩存
                GL.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
                
//重置當(dāng)前的模型觀察矩陣
                GL.glLoadIdentity();
            }

        }
);  
        canvas.addDisposeListener(
new DisposeListener() {
            
public void widgetDisposed(DisposeEvent e) {
                dispose();
            }

        }
);


調(diào)用glLoadIdentity()之后,實際上將當(dāng)前點移到了屏幕中心,X坐標(biāo)軸從左至右,Y坐標(biāo)軸從下至上,Z坐標(biāo)軸從里至外。OpenGL屏幕中心的坐標(biāo)值是XY軸上的0.0f點。中心左面的坐標(biāo)值是負(fù)值,右面是正值。移向屏幕頂端是正值,移向屏幕底端是負(fù)值。移入屏幕深處是負(fù)值,移出屏幕則是正值。

glTranslatef(x, y, z)是將當(dāng)前點沿著X,YZ軸移動,當(dāng)我們繪圖的時候,不是相對于屏幕中間,而是相對于當(dāng)前點。

glBegin(GL.GL_TRIANGLES)的意思是開始繪制三角形,glEnd()告訴OpenGL三角形已經(jīng)創(chuàng)建好了。通常當(dāng)我們需要畫3個頂點時,可以使用GL_TRIANGLES。在絕大多數(shù)的顯卡上,繪制三角形是相當(dāng)快速的。如果要畫四個頂點,使用GL_QUADS的話會更方便。但據(jù)我所知,絕大多數(shù)的顯卡都使用三角形來為對象著色。最后,如果想要畫更多的頂點時,可以使用GL_POLYGON

glVertex(x,y,z)用來設(shè)置頂點,如果繪制三角形,這些頂點需要三個一組,如果繪制四邊形,則是四個為一組。如果我們要為頂點著色,就需要glColor3f(r,g,b)方法,記住,每次設(shè)置以后,這個顏色就是當(dāng)前顏色,直到再次調(diào)用該方法重新設(shè)置為止。

最后需要介紹的是glRotatef(Angle,Xvector,Yvector,Zvector)方法,該方法負(fù)責(zé)讓對象圍繞指定的軸旋轉(zhuǎn),Angle參數(shù)指轉(zhuǎn)動的角度,注意是浮點數(shù)哦。

下面是我的視圖類的全部代碼,我把3D繪圖的任務(wù)全部放到了另外一個線程中,并且定義了一個遞歸方法public void drawPyramid(float x, float y, float z, int n)用來繪制三菱錐矩陣。如下:
package cn.blogjava.youxia.views;

import org.eclipse.opengl.GL;
import org.eclipse.opengl.GLU;
import org.eclipse.swt.events.ControlAdapter;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.opengl.GLData;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.part.ViewPart;
import org.eclipse.swt.opengl.GLCanvas;
import org.eclipse.swt.SWT;

public class OpenGLView extends ViewPart {

    GLCanvas canvas;
    @Override
    
public void createPartControl(Composite parent) {
        
// TODO 自動生成方法存根
        GLData data = new GLData();
        data.depthSize 
= 1;
        data.doubleBuffer 
= true;
        canvas 
= new GLCanvas(parent, SWT.NO_BACKGROUND, data);
        canvas.addControlListener(
new ControlAdapter() {
            
public void controlResized(ControlEvent e) {
                Rectangle rect 
= canvas.getClientArea();
                GL.glViewport(
00, rect.width, rect.height);
                
                
//選擇投影矩陣
                GL.glMatrixMode(GL.GL_PROJECTION);
                
//重置投影矩陣
                GL.glLoadIdentity();
                
//設(shè)置窗口比例和透視圖
                GLU.gluPerspective(45.0f, (float) rect.width / (float) rect.height, 0.1f100.0f);
                
//選擇模型觀察矩陣
                GL.glMatrixMode(GL.GL_MODELVIEW);
                
//重置模型觀察矩陣
                GL.glLoadIdentity();
                
                
//黑色背景
                GL.glClearColor(0.0f0.0f0.0f0.0f);
                
//設(shè)置深度緩存
                GL.glClearDepth(1.0f);
                
//啟動深度測試
                GL.glEnable(GL.GL_DEPTH_TEST);
                
//選擇深度測試類型
                GL.glDepthFunc(GL.GL_LESS);
                
//啟用陰影平滑
                GL.glShadeModel(GL.GL_SMOOTH);
                
//精細(xì)修正透視圖
                GL.glHint(GL.GL_PERSPECTIVE_CORRECTION_HINT, GL.GL_NICEST);
                
//清除屏幕和深度緩存
                GL.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
                
//重置當(dāng)前的模型觀察矩陣
                GL.glLoadIdentity();
            }

        }
);  
        canvas.addDisposeListener(
new DisposeListener() {
            
public void widgetDisposed(DisposeEvent e) {
                dispose();
            }

        }
);
        
/*
        
        
*/

        
        
        Refresher rf 
= new Refresher(canvas);
        rf.run();
    }


    @Override
    
public void setFocus() {
        
// TODO 自動生成方法存根

    }


}


class Refresher implements Runnable {
    
public static final int DELAY = 100;
    
    
private GLCanvas canvas;
    
private float rotate = 0.0f;
    
    
public Refresher(GLCanvas canvas) {
        
this.canvas = canvas;
    }

    
    
public void run() {
        
if (this.canvas != null && !this.canvas.isDisposed()) {
            
if(!canvas.isCurrent()){
                canvas.setCurrent();
            }

            
//這里添加OpenGL繪圖代碼
            GL.glLoadIdentity();
            GL.glClear(GL.GL_COLOR_BUFFER_BIT 
| GL.GL_DEPTH_BUFFER_BIT);
            GL.glTranslatef(
04.5f-11);
            
//圍繞y軸轉(zhuǎn)起來
            rotate += 0.5;
            GL.glRotatef(rotate, 
01.0f0);
            
//調(diào)用遞歸函數(shù),繪制三菱錐矩陣
            drawPyramid(0,0,0,4);
            canvas.swapBuffers();
            
this.canvas.getDisplay().timerExec(DELAY, this);
        }

    }

        
        
public void drawPyramid(float x, float y, float z, int n){
            
if(n == 0)return;
            
//畫一個三菱錐
            GL.glBegin(GL.GL_TRIANGLES);
                
//畫背面
                GL.glColor3f(1.0f,0.0f,0.0f);
                GL.glVertex3f( x, y, z);
                GL.glColor3f(
0.0f,1.0f,0.0f);
                GL.glVertex3f(x
+1.0f,y-1.63f,z-0.57f);
                GL.glColor3f(
0.0f,0.0f,1.0f);
                GL.glVertex3f( x
-1.0f,y-1.63f,z-0.57f);
                
//畫底面
                GL.glColor3f(1.0f,0.0f,0.0f);
                GL.glVertex3f( x,y
-1.63f,z+1.15f);
                GL.glColor3f(
0.0f,1.0f,0.0f);
                GL.glVertex3f(x
-1.0f,y-1.63f,z-0.57f);
                GL.glColor3f(
0.0f,0.0f,1.0f);
                GL.glVertex3f( x
+1.0f,y-1.63f,z-0.57f);
                
//畫左側(cè)面
                GL.glColor3f(1.0f,0.0f,0.0f);
                GL.glVertex3f( x,y,z);
                GL.glColor3f(
0.0f,1.0f,0.0f);
                GL.glVertex3f(x
-1.0f,y-1.63f,z-0.57f);
                GL.glColor3f(
0.0f,0.0f,1.0f);
                GL.glVertex3f( x,y
-1.63f,z+1.15f);
                
//畫右側(cè)面
                GL.glColor3f(1.0f,0.0f,0.0f);
                GL.glVertex3f( x,y,z);
                GL.glColor3f(
0.0f,1.0f,0.0f);
                GL.glVertex3f(x,y
-1.63f,z+1.15f);
                GL.glColor3f(
0.0f,0.0f,1.0f);
                GL.glVertex3f( x
+1.0f,y-1.63f,z-0.57f);
            GL.glEnd();
            
//遞歸調(diào)用,畫多個三菱錐
            drawPyramid(x,y-1.63f,z+1.15f,n-1);
            drawPyramid(x
-1.0f,y-1.63f,z-0.57f,n-1);
            drawPyramid(x
+1.0f,y-1.63f,z-0.57f,n-1);
        }

}
本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊舉報。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
OpenGL ES基礎(chǔ)教程
SWT 全接觸
BlogJava - kukooBlog - Eclipse RCP 應(yīng)用系統(tǒng)
OpenGL_Qt學(xué)習(xí)筆記
OpenGL三角形的雙面不同顏色的繪制
VC下配置OPENGL框架
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點擊這里聯(lián)系客服!

聯(lián)系客服