在掘金上看到最近的新活動 "代碼吸貓",技術類文章只要和貓有關就行。
對於沒有養貓的程序員,這不是為難人嘛。
不過沒關係,用 OpenGL 圖像渲染給自己造一隻貓吧!!!
模型構造首先需要構造出貓的模型,有能力的話可以直接在三維軟件裡面造一個。
或者像我一樣直接下載免費的貓模型,然後把它導入 Blender 3D 軟件中。

在 Blender 中可以預覽貓模型,或者對它做一下調整,最後在把這個模型導出。
模型加載導出的 obj 文件裡面就記錄了模型的頂點信息,接下來就要用 OpenGL 將它繪製出來。
這裡要用到 assimp 開源庫,它支持多種模型文件的解析操作,通過它將模型解析成一個個 Mesh 。
Mesh 的定義如下:
classMesh{public:/*MeshData*/vector<Vertex>vertices;vector<unsignedint>indices;vector<Texture>textures;unsignedintVAO;//省略部分代碼}Mesh 相當於繪製模型上的一個個網格或者說面片,它包含了該網格的頂點、紋理信息和繪製索引。
而模型 Model 就是由這一系列網格 Mesh 組成的。

如上圖所示,貓模型是由一個個小矩陣組成的,小矩陣就可以理解成 mesh 網格了。
Model 的定義如下:
classModel{public:/*ModelData*/vector<Texture>textures_loaded;vector<Mesh>meshes;//省略部分代碼}在實際繪製的時候,也是由一個一個 Mesh 最終繪製成的。
//drawsthemodel,andthusallitsmeshesvoidDraw(Shadershader){for(unsignedinti=0;i<meshes.size();i++)meshes[i].Draw(shader);}從圖中也可以看到,貓模型的網格數量是很多的,導致加載的時候會很很慢了,加載方法如下:
voidloadModel(stringconst&path){//使用assimp庫進行加載constaiScene*scene=importer.ReadFile(path,aiProcess_Triangulate|aiProcess_FlipUVs|aiProcess_CalcTangentSpace);//檢查是否有錯if(!scene||scene->mFlags&AI_SCENE_FLAGS_INCOMPLETE||!scene->mRootNode)//ifisNotZero{cout<<"ERROR::ASSIMP::"<<importer.GetErrorString()<<endl;return;}//獲取模型所在文件夾directory=path.substr(0,path.find_last_of('/'));//從根節點一個一個節點開始處理processNode(scene->mRootNode,scene);}使用 assimp 處理後會得到一個根節點,然後順着根節點一個一個往下處理就好了。
voidprocessNode(aiNode*node,constaiScene*scene){for(unsignedinti=0;i<node->mNumMeshes;i++){aiMesh*mesh=scene->mMeshes[node->mMeshes[i]];//處理得到的aiMesh並組裝成定義好的Mesh數據結構meshes.push_back(processMesh(mesh,scene));}//處理子節點for(unsignedinti=0;i<node->mNumChildren;i++){processNode(node->mChildren[i],scene);}}可以看到處理過程大量的 for 循環操作,所以後續才會針對模型文件的優化,加快其加載速度。
模型渲染得到了最終的 Model 之後,就可以對它做渲染顯示了。
//model矩陣調整模型顯示位置和方向glm::mat4model=glm::mat4(1.0f);model=glm::translate(model,glm::vec3(tranx_x,tranx_y,tranx_z));model=glm::rotate(model,glm::radians(90.0f),glm::vec3(0.0,0.0,1.0));model=glm::scale(model,glm::vec3(0.5f,0.5f,0.5f));shader.setMatrix4fv("model",glm::value_ptr(model));ourModel.Draw(shader);由於模型自身就帶了一個位置和方向,顯示的時候不一定是我們想要的觀察方位,所以還是要調整一個模型矩陣。
最後渲染就可以看到 貓模型 效果啦。



為了便於觀察,可以處理一下鍵盤或者鼠標事件,修改模型矩陣的值,從不同角度擼貓。
目前的貓模型還只是靜態的,調整的話也只能用鍵盤調整,而且還只是改了 移動、縮放、旋轉這些屬性,貓本身是沒有動的。
想要貓自身能動的話,還需要模型裡面有對應的骨骼動畫才可以了,等後面有了這樣的模型,再繼續迭代 。
OpenGL 相關的文章歡迎閱讀:
推薦閱讀:
RxJava 堆棧異常信息顯示不全,怎麼搞
Android 音視頻開發【特效篇】【一】抖音傳送帶特效
快手線上 OOM 監控方案 - KOOM 分析
Flutter自定義之旋轉木馬 - 帶你回到童年時光
愛奇藝 Xcrash 是怎麼捕獲 crash 的
真牛系列 - 一步步解決 App 隱私違規問題
覺得不錯,點個在看唄~
