11鱼炒、OpenGL初探之基礎演練-實現(xiàn)球的自轉(zhuǎn)加公轉(zhuǎn)

實現(xiàn)效果:

能隨著觀察者的不斷移動,都能觀察到小球的公轉(zhuǎn)加自轉(zhuǎn)

最終圖片效果:

圖1效果圖
圖2效果圖

大體實現(xiàn)思路及步驟拆分:

1欲芹、先實現(xiàn)綠色方格地板部分

2卿啡、實現(xiàn)固定自轉(zhuǎn)的紅色大球和一個中型的藍球,以及位置隨機的50個小藍球

3菱父、實現(xiàn)中型藍球繞紅色大球的公轉(zhuǎn)

4颈娜、實現(xiàn)移動觀察者(camera)仍能觀察紅球自轉(zhuǎn)及藍球圍繞紅球公轉(zhuǎn)

下面開始代碼部分


一、先定義一些變量

GLShaderManager shaderManager; // 定義一個著色器管理器

GLMatrixStack modelViewMatrix; // 定義一個模型視圖矩陣

GLMatrixStack projectionMatrix; // 定義一個投影矩陣

GLFrustum viewFrustum; // 視景體

GLGeometryTransform transformPipeline; // 幾何圖形變換管道

GLTriangleBatch ? ?torusBatch;? ? ? ? ? ? //批次類 ?-大球

GLTriangleBatch? ? sphereBatch;? ? ? ? ? ? //批次類 ?-小球

GLBatch? ? ? ? ? ? ? ? floorBatch;? ? ? ? ? //簡單的批次類 ?-地板

//角色幀 照相機角色幀

GLFrame? cameraFrame;

GLFrame? objectFrame;

//**4滞伟、添加附加隨機球

#define NUM_SPHERES50

GLFrame spheres[NUM_SPHERES];

二揭鳞、在主函數(shù)中初始化一些特殊鍵位操作以及設置窗口默認參數(shù),注冊變化函數(shù)

int ?main (int ?argc, ?char* argv[])

{

//1梆奈、設置當前工作目錄野崇,針對MAC OS X? ? /*?? ? `GLTools`函數(shù)`glSetWorkingDrectory`用來設置當前工作目錄。實際上在Windows中是不必要的亩钟,因為工作目錄默認就是與程序可執(zhí)行執(zhí)行程序相同的目錄乓梨。但是在Mac OS X中鳖轰,這個程序?qū)斍肮ぷ魑募A改為應用程序捆綁包中的`/Resource`文件夾。`GLUT`的優(yōu)先設定自動進行了這個中設置扶镀,但是這樣中方法更加安全蕴侣。?? ? */

? ? gltSetWorkingDirectory(argv[0]);

//2.初始化一個GLUT庫

? ? glutInit(&argc, argv);

/* 3、 ? ? 初始化雙緩沖窗口臭觉,其中標志GLUT_DOUBLE昆雀、GLUT_RGBA、GLUT_DEPTH蝠筑、GLUT_STENCIL分別指?? ? 雙緩沖窗口狞膘、RGBA顏色模式、深度測試什乙、模板緩沖區(qū)? ? ??? ?

?--GLUT_DOUBLE`:雙緩存窗口挽封,是指繪圖命令實際上是離屏緩存區(qū)執(zhí)行的,然后迅速轉(zhuǎn)換成窗口視圖臣镣,這種方式辅愿,經(jīng)常用來生成動畫效果;?? ??

--GLUT_DEPTH`:標志將一個深度緩存區(qū)分配為顯示的一部分忆某,因此我們能夠執(zhí)行深度測試点待;?? ??

--GLUT_STENCIL`:確保我們也會有一個可用的模板緩存區(qū)。?? ? 深度褒繁、模板測試后面會細致講到?? ?

?*/

? ? glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);

//3亦鳞、GLUT窗口大小、窗口標題

? ? glutInitWindowSize(800,600);

? ? glutCreateWindow("OpenGL SphereWorld");

/*4棒坏、 ? ? ?GLUT 內(nèi)部運行一個本地消息循環(huán)燕差,攔截適當?shù)南ⅰH缓笳{(diào)用我們不同時間注冊的回調(diào)函數(shù)坝冕。我們一共注冊2個回調(diào)函數(shù):?

? ? 1)為窗口改變大小而設置的一個回調(diào)函數(shù)???

? ? 2)包含OpenGL 渲染的回調(diào)函數(shù)?? ? */

? ? glutReshapeFunc(ChangeSize);//注冊函數(shù)徒探,在窗口改變大小的時候調(diào)用

? ? glutDisplayFunc(RenderScene);//注冊渲染函數(shù)

? ? glutSpecialFunc(SpeacialKeys);//注冊特殊函數(shù)

/* 5、 ? ? 初始化一個GLEW庫,確保OpenGL API對程序完全可用喂窟。?? ? 在試圖做任何渲染之前测暗,要檢查確定驅(qū)動程序的初始化過程中沒有任何問題?? ? */

? ? GLenumerr =glewInit();

? ? if(GLEW_OK!= err) {

? ? ? ? fprintf(stderr,"GLEW Error: %s\n",glewGetErrorString(err));

? ? ? ? return1;

? ? }

//6、設置我們的渲染環(huán)境

? ?SetupRC();

?//7磨澡、這是一個無限執(zhí)行的循環(huán)碗啄,它會負責一直處理窗口和操作系統(tǒng)的用戶輸入等操作。(注意:不會執(zhí)行在glutMainLoop()之后的所有命令稳摄。)

? ? glutMainLoop();?

? ??return?0;

}

三稚字、開始設置我們的渲染環(huán)境

void ? ?SetupRC()

{

? ? //1.設置清屏顏色(背景顏色)

? ? glClearColor(0.0f, 0.0f, 0.0f, 1.0f);

? //2.初始化著色器

?//沒有著色器,在OpenGL 核心框架中是無法進行任何渲染的。初始化一 ?個渲染管理器胆描。目前我們使用固定管線渲染瘫想,后面會用OpenGL著色語言來寫著色器

? ?shaderManager.InitializeStockShaders();

?//3.修改物體的初始坐標,往后移動5.0f的距離也就是z為-5昌讲,z軸垂直屏幕指向我們觀察者為正国夜,z為-5,就是往屏幕里面移動5

? ? objectFrame.MoveForward(5.0f);

? ??//4.開啟深度測試短绸,3D圖像渲染需要開啟深度測試

? ? glEnable(GL_DEPTH_TEST);

? //5.開始設置地板的頂點數(shù)據(jù)

? ?floorBatch.Begin(GL_LINES, 324);??

? for(GLfloat x = -20.0; x <= 20.0f; x+= 0.5) {? ? ? ?

? ? ? floorBatch.Vertex3f(x, -0.55f, 20.0f);? ? ? ?

? ? ? floorBatch.Vertex3f(x, -0.55f, -20.0f); ? ? ? ? ? ? ? ? ? ? ? ?

? ? ? floorBatch.Vertex3f(20.0f, -0.55f, x);? ? ? ?

? ? ? floorBatch.Vertex3f(-20.0f, -0.55f, x);??

? }? ? floorBatch.End();

? //6.設置大球模型

? ??gltMakeSphere(torusBatch, 0.4f, 40, 80);

?//7.設置小球模型

? ??gltMakeSphere(torusBatch, 0.1f, 26, 13);

//8车吹、隨機位置放置小球

? ?for (int i = 0; i < NUM_SPHERES; i++) {?? ? ? ???

? ? ? //y軸不變,X,Z產(chǎn)生隨機值? ? ? ??

? ? ?GLfloat x = ((GLfloat)((rand() % 400) - 200 ) * 0.1f);? ? ??

? ? ?GLfloat z = ((GLfloat)((rand() % 400) - 200 ) * 0.1f);?? ? ? ?? ? ? ??

? ? //在y方向醋闭,將球體設置為0.0的位置礼搁,這使得它們看起來是飄浮在眼睛的高度? ? ? ?

? ? //對spheres數(shù)組中的每一個頂點,設置頂點數(shù)據(jù) ? ? ? ?

? ? spheres[i].SetOrigin(x, 0.0f, z);? ?

?}

四目尖、進行調(diào)用以繪制場景

void ??RenderScene (void)

{

? ? //1.初始化顏色值(地板,大球,小球顏色)

? ? static ??GLfloat ?vFloorColor[] = {0.0f,1.0f,0.0f,1.0f};//地板顏色

? ? static ?GLfloat ? vTorusColor[] = {1.0f,0.0f,0.0f,1.0f};//初始化大球顏色

? ? static ?GLfloat ? vSphereColor[] = {0.0f,0.0f,1.0f,1.0f};//初始化小球顏色

? ??//2.基于時間動畫

? ? static ? ?CStopWatch? ? rotTimer;

? ? float?yRot = rotTimer.GetElapsedSeconds() *60.0f;

? ? //3.清除顏色緩存區(qū)和深度緩沖區(qū),防止殘存的顏色和深度值影響渲染

? ? glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

? ? //4扎运、加入objectFrame瑟曲,用于特殊鍵位操作觀察者位置移動

? ? modelViewMatrix.PushMatrix(objectFrame);

? ??//5.獲取光源位置

? ? M3DVector4fvLightPos = {0.0f,10.0f,5.0f,1.0f};

? ??//6.繪制地面

? ? shaderManager.UseStockShader(GLT_SHADER_FLAT,

?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? transformPipeline.GetModelViewProjectionMatrix(),

?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? vFloorColor);

? ? floorBatch.Draw();

? ? //7.使得大球位置平移(3.0)向屏幕里面

? ? modelViewMatrix.Translate(0.0f, 0.0f, -3.0f);

? ? //8.壓棧(復制棧頂)

? ? modelViewMatrix.PushMatrix();

? ? //9.大球自轉(zhuǎn)

? ? modelViewMatrix.Rotate(yRot,0.0f,1.0f,0.0f);

? ? //10.指定合適的著色器(點光源著色器)? ? shaderManager.UseStockShader(GLT_SHADER_POINT_LIGHT_DIFF, transformPipeline.GetModelViewMatrix(),

?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? transformPipeline.GetProjectionMatrix(), vLightPos, vTorusColor);

? ? torusBatch.Draw();

? ? //11.繪制完畢則出棧Pop

? ? modelViewMatrix.PopMatrix();

? ? //12.畫小球

? ? for(inti =0; i< NUM_SPHERES; i++) {

? ? ? ? modelViewMatrix.PushMatrix();// 壓棧,開始執(zhí)行變換

? ? ? ? modelViewMatrix.MultMatrix(spheres[i]);

? ? ? ? shaderManager.UseStockShader(GLT_SHADER_POINT_LIGHT_DIFF, transformPipeline.GetModelViewMatrix(),

?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? transformPipeline.GetProjectionMatrix(), vLightPos, vSphereColor);

? ? ? ? sphereBatch.Draw();//批次類開啟繪制

? ? ? ? modelViewMatrix.PopMatrix();//出棧

? ? }

? ? //13. 讓一個小籃球圍繞大球公眾自轉(zhuǎn)

? ? modelViewMatrix.Rotate(yRot * -2.0f,0.0f,1.0f,0.0f);//旋轉(zhuǎn)矩陣

? ? modelViewMatrix.Translate(0.8f, 0.0f, 0.0f);//平移

? ? shaderManager.UseStockShader(GLT_SHADER_FLAT,transformPipeline.GetModelViewProjectionMatrix(),vSphereColor);

? ? sphereBatch.Draw();

? ? modelViewMatrix.PopMatrix();//出棧

? ??//14.執(zhí)行緩存區(qū)交換

? ? glutSwapBuffers();

? ? //15 發(fā)送重新渲染

? ? glutPostRedisplay();

}

五豪治、屏幕大小更改或者已經(jīng)初始化

void?ChangeSize(int?nWidth ,int?nHeight)

{

? ? //1.設置視口或者視口大小更改后重新設置視口

? ? glViewport(0,0, nWidth, nHeight);

? ? //2.創(chuàng)建投影矩陣

? ? viewFrustum.SetPerspective(35.0f,float(nWidth)/float(nHeight),1.0f,100.0f);

? ? //viewFrustum.GetProjectionMatrix()? 獲取viewFrustum投影矩陣

? ? //并將其加載到投影矩陣堆棧上

? ? projectionMatrix.LoadMatrix(viewFrustum.GetProjectionMatrix());

? ? //3.設置變換管道以使用兩個矩陣堆棧(變換矩陣modelViewMatrix 洞拨,投影矩陣projectionMatrix)

? ? //初始化GLGeometryTransform 的實例transformPipeline.通過將它的內(nèi)部指針設置為模型視圖矩陣堆棧 和 投影矩陣堆棧實例,來完成初始化

? ? //當然這個操作也可以在SetupRC 函數(shù)中完成负拟,但是在窗口大小改變時或者窗口創(chuàng)建時設置它們并沒有壞處烦衣。而且這樣可以一次性完成矩陣和管線的設置。

? ? transformPipeline.SetMatrixStacks(modelViewMatrix, projectionMatrix);

}

六掩浙、特殊鍵位操作

void?SpeacialKeys(int?key,int?x,int?y){

? ??//設定移動步長

? ? float ? ? ?linear =0.1f;

? ? //設定旋轉(zhuǎn)度數(shù)

? ? float ? ?angular = ?float(m3dDegToRad(5.0f));//角度轉(zhuǎn)弧度

? ? if(key ==GLUT_KEY_UP) {//鍵盤上的方向鍵 ?up鍵

? ? ? ? //MoveForward 平移

? ? ? ? objectFrame.MoveForward(linear);

? ? }

? ? if(key ==GLUT_KEY_DOWN) {//鍵盤上的方向鍵 ?down鍵

? ? ? ? objectFrame.MoveForward(linear);

? ? }

? ??if(key ==GLUT_KEY_LEFT) {//鍵盤上的方向鍵 ?left鍵

? ? ? ? //RotateWorld 旋轉(zhuǎn)

? ? ? ? objectFrame.RotateWorld(angular,0,1,0);

? ? }

? ? if(key ==GLUT_KEY_RIGHT) {//鍵盤上的方向鍵 ?right鍵

? ? ? ? objectFrame.RotateWorld(angular,0,1,0); ? ?}

}

七花吟、最終效果視頻地址優(yōu)酷傳送門:小球自轉(zhuǎn)公轉(zhuǎn)效果圖


[溪浣雙鯉的技術摸爬滾打之路](http://www.reibang.com/p/3fbecd65faae)

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市厨姚,隨后出現(xiàn)的幾起案子衅澈,更是在濱河造成了極大的恐慌,老刑警劉巖谬墙,帶你破解...
    沈念sama閱讀 218,284評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件今布,死亡現(xiàn)場離奇詭異,居然都是意外死亡拭抬,警方通過查閱死者的電腦和手機部默,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,115評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來造虎,“玉大人傅蹂,你說我怎么就攤上這事±勰危” “怎么了贬派?”我有些...
    開封第一講書人閱讀 164,614評論 0 354
  • 文/不壞的土叔 我叫張陵急但,是天一觀的道長。 經(jīng)常有香客問我搞乏,道長波桩,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,671評論 1 293
  • 正文 為了忘掉前任请敦,我火速辦了婚禮镐躲,結果婚禮上,老公的妹妹穿的比我還像新娘侍筛。我一直安慰自己萤皂,他們只是感情好,可當我...
    茶點故事閱讀 67,699評論 6 392
  • 文/花漫 我一把揭開白布匣椰。 她就那樣靜靜地躺著裆熙,像睡著了一般。 火紅的嫁衣襯著肌膚如雪禽笑。 梳的紋絲不亂的頭發(fā)上入录,一...
    開封第一講書人閱讀 51,562評論 1 305
  • 那天,我揣著相機與錄音佳镜,去河邊找鬼僚稿。 笑死,一個胖子當著我的面吹牛蟀伸,可吹牛的內(nèi)容都是我干的蚀同。 我是一名探鬼主播,決...
    沈念sama閱讀 40,309評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼啊掏,長吁一口氣:“原來是場噩夢啊……” “哼蠢络!你這毒婦竟也來了?” 一聲冷哼從身側響起迟蜜,我...
    開封第一講書人閱讀 39,223評論 0 276
  • 序言:老撾萬榮一對情侶失蹤谢肾,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后小泉,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體芦疏,經(jīng)...
    沈念sama閱讀 45,668評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,859評論 3 336
  • 正文 我和宋清朗相戀三年微姊,在試婚紗的時候發(fā)現(xiàn)自己被綠了酸茴。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,981評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡兢交,死狀恐怖薪捍,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤酪穿,帶...
    沈念sama閱讀 35,705評論 5 347
  • 正文 年R本政府宣布凳干,位于F島的核電站,受9級特大地震影響被济,放射性物質(zhì)發(fā)生泄漏救赐。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,310評論 3 330
  • 文/蒙蒙 一只磷、第九天 我趴在偏房一處隱蔽的房頂上張望经磅。 院中可真熱鬧,春花似錦钮追、人聲如沸预厌。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,904評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽轧叽。三九已至,卻和暖如春刊棕,著一層夾襖步出監(jiān)牢的瞬間犹芹,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,023評論 1 270
  • 我被黑心中介騙來泰國打工鞠绰, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人飒焦。 一個月前我還...
    沈念sama閱讀 48,146評論 3 370
  • 正文 我出身青樓蜈膨,卻偏偏與公主長得像,于是被迫代替她去往敵國和親牺荠。 傳聞我的和親對象是個殘疾皇子翁巍,可洞房花燭夜當晚...
    茶點故事閱讀 44,933評論 2 355