OpenGLES進階教程8-obj文件和mtl文件解析

教程

OpenGLES入門教程1-Tutorial01-GLKit
OpenGLES入門教程2-Tutorial02-shader入門
OpenGLES入門教程3-Tutorial03-三維變換
OpenGLES入門教程4-Tutorial04-GLKit進階
OpenGLES進階教程1-Tutorial05-地球月亮
OpenGLES進階教程2-Tutorial06-光線
OpenGLES進階教程3-Tutorial07-粒子效果
OpenGLES進階教程4-Tutorial08-幀緩存
OpenGLES進階教程5-Tutorial09-碰碰車
OpenGLES進階教程6-Tutorial10-平截體優(yōu)化
OpenGLES進階教程7-Tutorial11-天空盒效果

距離上一篇教程已經有兩個月了梯投,這兩個月詳細閱讀GPUImage的源碼疲恢,并寫了詳細解析,發(fā)現(xiàn)對OpenGLES的深入了解很有幫助姓迅。
上周一個簡書的朋友問我,如果有一個.obj文件,如何用OpenGL ES把它顯示到iOS屏幕上蒲祈。

  • obj文件如下


之前學習blender的時候,在國外的一個系列教程有提到解析obj文件萝嘁,這篇教程便來介紹如何解析obj和mtl文件梆掸,并用OpenGL ES顯示出來。

概念介紹

1牙言、obj文件

obj文件是一種3D模型文件酸钦。

  • 文件格式


其中

v 幾何體頂點 (Geometric vertices)
vt 貼圖坐標點 (Texture vertices)
vn 頂點法線 (Vertex normals)
f 面 (Face)

2、mtl文件

mtl文件則是obj文件的附屬文件咱枉,描述幾何體的表面屬性卑硫。

  • 文件格式


其中

環(huán)境反射 Ka r g b
漫反射 Kd r g b
鏡反射 Ks r g b
反射指數(shù) Ns exponent 指定材質的反射指數(shù)徒恋,定義了反射高光度
折射值 Ni ptical density 指定材質表面的光密度,即折射值
漸隱指數(shù) d factor 參數(shù)factor表示物體融入背景的數(shù)量

核心思路

新建一個工程欢伏,讀入obj和mtl文件入挣,解析文件內容,寫入到.h/.c文件中硝拧,把.h/.c文件加入新的工程引用径筏。


效果展示

model.gif

具體細節(jié)

1、文件解析

自定義Model結構體來存儲讀取的信息河爹,通過一行行讀入文件匠璧,并用字符串匹配來解析數(shù)據(jù)。

typedef struct Model
{
    int vertices;
    int positions;
    int texels;
    int normals;
    int faces;
    int materials;
}Model;


Model getOBJinfo(string fp)
{
    Model model = {0};
    
    ifstream inOBJ;
    inOBJ.open(fp);
    if (!inOBJ.good()) {
        cout << "error on open " << fp << endl;
        exit(1);
    }
    
    while (!inOBJ.eof()) {
        string line;
        getline(inOBJ, line);
        string type = line.substr(0, 2);
        
        if (type.compare("v ") == 0) {
            model.positions++;
        }
        else if (type.compare("vt") == 0) {
            model.texels++;
        }
        else if (type.compare("vn") == 0) {
            model.normals++;
        }
        else if (type.compare("f ") == 0) {
            model.faces++;
        }
    }
    
    model.vertices = model.faces * 3;
    
    inOBJ.close();
    
    return model;
}

2咸这、文件寫入

把Model中存儲的解析信息夷恍,分別寫入到.h/.c文件中。

void writeCtexels(string fp, string name, Model model, int faces[][10], float texels[][2])
{
    // Append C file
    ofstream outC;
    outC.open(fp, ios::app);
    
    // Texels
    outC << "const float " << name << "Texels[" << model.vertices*2 << "] = " << endl;
    outC << "{" << endl;
    // Texels
    for(int j=0; j<model.materials; j++)
    {
        for(int i=0; i<model.faces; i++)
        {
            if(faces[i][9] == j)
            {
                int vtA = faces[i][1] - 1;
                int vtB = faces[i][4] - 1;
                int vtC = faces[i][7] - 1;
                
                outC << texels[vtA][0] << ", " << texels[vtA][1] << ", " << endl;
                outC << texels[vtB][0] << ", " << texels[vtB][1] << ", " << endl;
                outC << texels[vtC][0] << ", " << texels[vtC][1] << ", " << endl;
            }
        }
    }
    outC << "};" << endl;
    outC << endl;
    
    // Close C file
    outC.close();
}

3媳维、最終文件

Materials 材質
Diffuse 漫反射
Specular 鏡面反射
Normal 法線
Texel 紋理
Position 位置

extern const int starshipVertices;
extern const float starshipPositions[198];
extern const float starshipTexels[132];
extern const float starshipNormals[198];

extern const int starshipMaterials;
extern const int starshipFirsts[3];
extern const int starshipCounts[3];

extern const float starshipDiffuses[3][3];
extern const float starshipSpeculars[3][3];

4酿雪、場景渲染

渲染的過程中,設置好BaseEffect后侄刽,進行渲染指黎;有多組參數(shù)時,要分別設置再渲染州丹。

/**
 *  渲染場景代碼
 */
- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect {
    glClearColor(0.3f, 0.3f, 0.3f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    
    [self setMatrices];
    

    for(int i=0; i<starshipMaterials; i++)
    {
        // 設置材質
        self.baseEffect.material.diffuseColor = GLKVector4Make(starshipDiffuses[i][0], starshipDiffuses[i][1], starshipDiffuses[i][2], 1.0f);
        self.baseEffect.material.specularColor = GLKVector4Make(starshipSpeculars[i][0], starshipSpeculars[i][1], starshipSpeculars[i][2], 1.0f);
        
        [self.baseEffect prepareToDraw];
        
        glDrawArrays(GL_TRIANGLES, starshipFirsts[i], starshipCounts[i]);
    }
    
}

總結

這篇教程有兩個工程醋安,一個負責解析,一個用來渲染墓毒。解析的邏輯簡單但較繁瑣吓揪,可以直接看這里;渲染的邏輯和之前教程類似所计,唯一復雜的部分是光照部分的設置柠辞,可以看這里
另外主胧,blender這個工具非常好用叭首。之前為了學習blender,尋找了很多教程踪栋。demo的解析部分代碼焙格,也是參考教程里面的內容,出處已經找不到夷都。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末间螟,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌厢破,老刑警劉巖荣瑟,帶你破解...
    沈念sama閱讀 206,013評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異摩泪,居然都是意外死亡笆焰,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,205評論 2 382
  • 文/潘曉璐 我一進店門见坑,熙熙樓的掌柜王于貴愁眉苦臉地迎上來嚷掠,“玉大人荞驴,你說我怎么就攤上這事熊楼■昶” “怎么了执泰?”我有些...
    開封第一講書人閱讀 152,370評論 0 342
  • 文/不壞的土叔 我叫張陵计济,是天一觀的道長峭咒。 經常有香客問我,道長幔翰,這世上最難降的妖魔是什么遗增? 我笑而不...
    開封第一講書人閱讀 55,168評論 1 278
  • 正文 為了忘掉前任,我火速辦了婚禮饰及,結果婚禮上燎含,老公的妹妹穿的比我還像新娘屏箍。我一直安慰自己赴魁,他們只是感情好颖御,可當我...
    茶點故事閱讀 64,153評論 5 371
  • 文/花漫 我一把揭開白布秉继。 她就那樣靜靜地躺著尚辑,像睡著了一般杠茬。 火紅的嫁衣襯著肌膚如雪瓢喉。 梳的紋絲不亂的頭發(fā)上栓票,一...
    開封第一講書人閱讀 48,954評論 1 283
  • 那天走贪,我揣著相機與錄音坠狡,去河邊找鬼婴渡。 笑死边臼,一個胖子當著我的面吹牛硼瓣,可吹牛的內容都是我干的堂鲤。 我是一名探鬼主播,決...
    沈念sama閱讀 38,271評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼寓涨!你這毒婦竟也來了?” 一聲冷哼從身側響起糯崎,我...
    開封第一講書人閱讀 36,916評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎薄霜,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 43,382評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 35,877評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 37,989評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖话原,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情诲锹,我是刑警寧澤繁仁,帶...
    沈念sama閱讀 33,624評論 4 322
  • 正文 年R本政府宣布,位于F島的核電站归园,受9級特大地震影響黄虱,放射性物質發(fā)生泄漏。R本人自食惡果不足惜蔓倍,卻給世界環(huán)境...
    茶點故事閱讀 39,209評論 3 307
  • 文/蒙蒙 一悬钳、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦伴奥、人聲如沸袍镀。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,199評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至形导,卻和暖如春环疼,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背朵耕。 一陣腳步聲響...
    開封第一講書人閱讀 31,418評論 1 260
  • 我被黑心中介騙來泰國打工炫隶, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人阎曹。 一個月前我還...
    沈念sama閱讀 45,401評論 2 352
  • 正文 我出身青樓伪阶,卻偏偏與公主長得像煞檩,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子栅贴,可洞房花燭夜當晚...
    茶點故事閱讀 42,700評論 2 345

推薦閱讀更多精彩內容