2012年6月18日 星期一

[作業五 整合練習]


主題介紹 - 動物賽跑

       在喧嚷的城市中,豬與牛悠閒的在道路中賽跑,究竟是好吃懶做的豬會獲勝,還是西班牙鬥牛會獲勝呢?

讓我們仔細的看下去

程式設計與寫作方法、執行結果呈現

        這次的程式結合本學期課程所學,3D空間游走、3D model匯入、視角切換等等

從跑道的繪製,設置3D model的位置,旋轉角度等等,每一個步驟都是精心策劃

為的就是讓動物們真的在跑道上逼真的移動。另外在程式中按下O可以切換自動視角,有點像是看電影一般的感

覺,這個使用到的函式是gluLookatfun(); 以前都不知道這個這麼好用。其實這次的作品成熟度已經有了,如果

在加上滑鼠事件、碰撞偵測、還有移動的model細部的動作的話就更加完美了。

不過也學到了一件事情,就是隨著model的load 越來越多,程式執行就會越來越慢,所以要想辦法避免不必要

的讀取。

         最後一樣附上作品影片





  
心得與討論


        我自己覺得這次的作業算是蠻有趣的,整個場景看起來有點像是常玩的大富翁,可以蓋房子,又有動物在

跑道上移動,也許如果以後有機會的話可以從這個當做出發點,做個有趣的遊戲提供大家玩,最後我要感謝這

學期老師教了我們許多,讓我們可以寫做出這麼棒的程式。





2012年6月11日 星期一

[作業四 擬真3D空間場景-元智校園]


主題介紹 - 海洋動物園

       在廣闊的校園中,可愛的小豬、聰明伶俐的海豚與驕傲的老鷹活動於元智校園之中,校園的周圍禁是一望無

際的海洋,給人廣闊無邊的感覺。



程式設計與寫作方法、執行結果呈現

         這次的程式主要的重點就是學會如何讀取OBJ

首先,就是要先畫出3D模型,利用Audodesk 的 3ds Max 就可以設計出不錯的模型

再來,利用glm所提供的函式就可以成功的讀取OBJ。

程式代碼大致如下:

{
    GLMmodel *glm_model_pig;
     glm_model_pig= glmReadOBJ( "model/pig.obj" );
     glmUnitize( glm_model_pig );
     glmScale( glm_model_pig, 5 );
     glmFacetNormals( glm_model_pig );
     glmVertexNormals( glm_model_pig, 90 );

     list_id[0] = glmList( glm_model_pig, GLM_MATERIAL | GLM_SMOOTH );

     glmDelete( glm_model_pig );
}

如此就可以將OBJ成功的讀入程式中

再利用glCallList繪出

    glPushMatrix();
glDisable(GL_TEXTURE_2D);
glTranslatef(-5.0f,-5.0f,-20.0f);
    glCallList( list_id[0] );
glPopMatrix();

此外,我在這次的程式還加入的skybox,這個要實作也不困難,

首先一樣利用glm讀入bmp檔,然後再利用texture貼圖

程式碼大致上如下

首先是讀取bmp檔

bool Load_Texture(unsigned int & aTexture, char * fileName) {

if(!fileName) return false; //if no file name is given return

FILE *aFile = NULL;
AUX_RGBImageRec *image_record = NULL;

if((aFile = fopen(fileName, "rb")) == NULL) return false;
WCHAR wsz[64];
swprintf(wsz, L"%S", fileName);
LPCWSTR p = wsz;
image_record = auxDIBImageLoad(p); //Function to load BMP

if(!image_record) return false; //check that BMP loaded

glGenTextures(1, &aTexture); //generates 1 texture name

glPixelStorei (GL_UNPACK_ALIGNMENT, 1); //sets how the pixels of the texture are stored

glBindTexture(GL_TEXTURE_2D, aTexture); //binds the name to the target

//build prefiltered textures at different resolutions
gluBuild2DMipmaps(GL_TEXTURE_2D, 3, image_record->sizeX, 
 image_record->sizeY, GL_RGB, GL_UNSIGNED_BYTE, image_record->data);

//give the texture its attributes
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);

// Now we need to free the image data that we loaded since openGL stored it as a texture
if (image_record) { //if we stored data then free the memory
if (image_record->data) { //check if there is any data
// free(image_record->data); //free the memory
}
// free(image_record); //free the image record
}

return true; //everything should have worked so return true
}

然後再設置Texture

void skyboxInit() 
{

Load_Texture(texture[0],"texture/left.bmp");
Load_Texture(texture[1],"texture/front.bmp");
Load_Texture(texture[2],"texture/right.bmp");
Load_Texture(texture[3],"texture/back.bmp");
Load_Texture(texture[4],"texture/down.bmp");
Load_Texture(texture[5],"texture/up.bmp");
}

然後再呼叫繪出

void skybox()
{
glPushMatrix();
glDisable (GL_LIGHTING);
glColor3f(1.0f,1.0f,1.0f);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texture[0]);
glBegin (GL_QUADS);
glNormal3d (0.0,0.0,1.0); glTexCoord2d (0.0 ,0.0 );
                glVertex3d (-100.0,-10.0,100.0);
                
glNormal3d (0.0,0.0,1.0); glTexCoord2d (1.0 ,0.0 );
                glVertex3d (-100.0,-10.0,-100.0);
                
                glNormal3d (0.0,0.0,1.0);
glTexCoord2d (1.0 ,1.0 );
                glVertex3d (-100.0,100.0,-100.0);
glTexCoord2d (0.0 ,1.0 );
                glVertex3d (-100.0,100.0,100.0);
glEnd ();
glBindTexture(GL_TEXTURE_2D, texture[1]);
glBegin (GL_QUADS);
glNormal3d (0.0,0.0,1.0); glTexCoord2d (0.0 ,0.0 );
                glVertex3d (-100.0,-10.0,100.0);
                
glNormal3d (0.0,0.0,1.0); glTexCoord2d (1.0 ,0.0 );
                glVertex3d (100.0,-10.0,100.0);
                
                glNormal3d (0.0,0.0,1.0);
glTexCoord2d (1.0 ,1.0 );
                glVertex3d (100.0,100.0,100.0);
glTexCoord2d (0.0 ,1.0 );
                glVertex3d (-100.0,100.0,100.0);
glEnd ();
glBindTexture(GL_TEXTURE_2D, texture[3]);
glBegin (GL_QUADS);
glNormal3d (0.0,0.0,1.0); glTexCoord2d (0.0 ,0.0 );
                glVertex3d (-100.0,-10.0,-100.0);
                
glNormal3d (0.0,0.0,1.0); glTexCoord2d (1.0 ,0.0 );
                glVertex3d (100.0,-10.0,-100.0);
                
                glNormal3d (0.0,0.0,1.0);
glTexCoord2d (1.0 ,1.0 );
                glVertex3d (100.0,100.0,-100.0);
glTexCoord2d (0.0 ,1.0 );
                glVertex3d (-100.0,100.0,-100.0);
glEnd ();
glBindTexture(GL_TEXTURE_2D, texture[3]);
glBegin (GL_QUADS);
glNormal3d (0.0,0.0,1.0); glTexCoord2d (0.0 ,0.0 );
                glVertex3d (100.0,-10.0,100.0);
                
glNormal3d (0.0,0.0,1.0); glTexCoord2d (1.0 ,0.0 );
                glVertex3d (100.0,-10.0,-100.0);
                
                glNormal3d (0.0,0.0,1.0);
glTexCoord2d (1.0 ,1.0 );
                glVertex3d (100.0,100.0,-100.0);
glTexCoord2d (0.0 ,1.0 );
                glVertex3d (100.0,100.0,100.0);
glEnd ();
glPopMatrix();

}

如此一來就可以做出不錯的3D立體空間

         一樣附上作品影片


  
心得與討論


        作業四讀入OBJ檔後又加入的天空盒的texture,讓整個程式空間都完整了。


不過在讀取texture的時候,有一些型態的轉換要注意,例如"LPCWSTR",

2012年5月20日 星期日

[作業三 3D空間游走程式練習]


主題介紹 - 糖果屋

       在3D的立體空間中,我將元智一館之外的所有建築物都用彩色的方塊代替,就像是一顆顆的糖果一樣,


美味又可口。


程式設計與寫作方法、執行結果呈現

         這次的程式主要的重點就是學會 glTranslatef( GLdouble eyeX , GLdouble eyeY , 

GLdouble eyeZ , GLdouble centerX , GLdouble centerY , GLdouble centerZ , GLdouble 

upX , GLdouble upY , GLdouble upZ );的使用過,釐清了概念之後就一點也不難了。


         一樣附上作品影片





  
心得與討論


        作業三加上了3D空間的游走,讓畫面空間從以往的視窗,拓展到了整個世界。原本打算用讀obj的方式將

作業完成,不過因為不會使用建模軟體所以就放棄了,有機會會多試試。

2012年3月18日 星期日

[作業一 元智一館]



主題介紹 - 青出於藍

        走著每天上學必經的綠蔭大道,緩步走向左手邊樸素的建築物,這就是元智一館,我們

每天奮戰與學習新知的地方。作品中呈現的藍天白雲,期許著我們可以在這資訊人才的搖籃

裡激發創意,創造出簡單中的不平凡。


程式設計與寫作方法、執行結果呈現

        在進行程式寫作以前,先在網路上找了張元智一館的圖像(圖一),方便設計與參考。由於

是創作,因此首要目標就是將一個個的物件給創造出來。圖片中的主體是一館建築物,再來

是窗戶、燈座、道路、樹木等等。這些物件反覆的利用OpenGL  Primitives 即可完成。

(圖一) 元智大學一館(Yuan Ze University Building 1, Taiwan)


        基本的寫法是將要畫的圖形包在函式 glBegin(GLenum mode) glEnd()之中,glBegin()的

參數 mode 是填入想要畫的Primitive,我們可以利用GL_LINESGL_LINE_LOOP

GL_LINE_STRIP 這類的Primitives畫線,GL_TRIANGLES實做三角形、 GL_QUADS實做長方

形,用GL_POLYGON實做多邊形。

        由於畫布上的物件是一層一層疊上去的,所以一定要搞清楚物件的先後順序,於是可以

得到初步的成果。(圖二)

(圖二)初步的成果


        有了初步的底圖之後,接下來就要為圖形著色,使用的函數是glColor3f(GLfloat  red


GLfloat  green, GLfloat  blue) 傳進去的參數是RGB三原色的比例(最高是1,最低是0),而不是

直接傳256色的色階,這跟以往在寫其它畫圖程式所用的RGB傳值的方式有點不同,所以一開

始在參數的轉換上遇到了一點小困難,往往不知道如何調出自己想要的顏色。後來我使用了

Colorspire + EXCEL來計算我的顏色一切就簡單多了(圖三),只要將在 Colorspire 抓到的RGB值丟進

EXCEL 除以255運算過後,就可以得到RGB顏色的比例。於是我們可以得到最後的成果。

(圖三) Colorspire + EXCEL
(圖四)加了顏色

心得與討論


        作業一是利用基本的 OpenGL Primitives 來完成元智大學一館的繪製,這是一個非常好的

練習,讓我們可以熟悉基本的2D繪圖以及相關參數的設置,另外我在程式的撰寫中也加入了

一些額外的技巧,例如圓形的繪製,雖然圓形不屬於基本的 Primitives ,不過透過簡單的程式

邏輯,讓繪圖增添了不少可能性。