天天看點

NDK OpenGL ES 3.0 開發(二十):3D 模型OpenGLES 3D 模型OBJ 檔案的結構模型加載庫 Assimp

作者:位元組流動

來源:

https://blog.csdn.net/Kennethdroid/article/details/103771970

OpenGLES 3D 模型

NDK OpenGL ES 3.0 開發(二十):3D 模型OpenGLES 3D 模型OBJ 檔案的結構模型加載庫 Assimp

OpenGLES 3D 模型本質上是由一系列三角形在 3D 空間(OpenGL 坐标系)中建構而成,另外還包含了用于描述三角形表面的紋理、光照、材質等資訊。

建構一些規則的 3D 物體,如立方體、球體、椎體等,我們自己可以手動輕易實作,但是在實際開發中往往會用到複雜的 3D 物體,如人體、汽車等,這就需要設計師和專業的模組化工具軟體(像 3DS Max、Maya )來生成。

利用 3D 模組化軟體,設計師可以建構一些複雜的形狀,并将貼圖應用到形狀上去,不需要去關注圖像技術細節。最後在導出模型檔案時,模組化工具會自己生成所有的頂點坐标、頂點法線和紋理坐标。

常用的模型檔案格式有 .obj、.max、.fbx .3ds 等,其中

.obj 

是 Wavefront 科技開發的一種幾何體圖形檔案格式,包含每個頂點的位置、紋理坐标、法線,以及組成面(多邊形)的頂點清單等資料,應用較為廣泛。

OBJ 檔案的結構

本文主要介紹 obj 3D 模型檔案及其附屬檔案 mtl ,下面是 obj 模型檔案的資料結構(為了友善展示部分資料被略過)。

# 3ds Max Wavefront OBJ Exporter v0.97b - (c)2019 guruware
# File Created: 25.01.2019 02:22:51

mtllib earth.mtl

v  -4.4189 340.8998 -4.2436
v  -4.4189 339.2582 -37.6576
v  -7.6941 339.2582 -37.4967
v  -10.9377 339.2582 -37.0156
v  -14.1185 339.2582 -36.2188
v  -17.2059 339.2582 -35.1141
...
# 1986 vertices

vn -0.0000 1.0000 0.0000
vn 0.0000 0.9950 -0.0995
vn -0.0098 0.9950 -0.0991
vn -0.0194 0.9950 -0.0976
vn -0.0289 0.9950 -0.0952
vn -0.0381 0.9950 -0.0920
vn -0.0469 0.9950 -0.0878
...
# 1986 vertex normals

vt 0.0000 1.0000 0.0000
vt 0.0000 0.9688 0.0000
vt 0.0156 0.9688 0.0000
vt 0.0156 1.0000 0.0000
vt 0.0313 0.9688 0.0000
vt 0.0313 1.0000 0.0000
...
# 2143 texture coords

usemtl 01___Default 
s 1
f 1/1/1 2/2/2 3/3/3 
f 1/4/1 3/3/3 4/5/4 
f 1/6/1 4/5/4 5/7/5 
f 1/8/1 5/7/5 6/9/6 
f 1/10/1 6/9/6 7/11/7 
...
      

OBJ 檔案資料結構的簡單說明:

  1. #

    開頭的行表示注釋行;
  2. mtllib

    表示指定該 OBJ 檔案所使用的 mtl 檔案(材質檔案);
  3. v

    開頭的行表示存放的是頂點坐标,後面三個數分别表示一個頂點的(x,y,z)坐标值;
  4. vn

    開頭的行表示存放的是頂點法向量,後面三個數分别表示一個頂點法向量的三維(x,y,z)分量值;
  5. vt

    開頭的行表示存放的是紋理坐标,後面三個數分别表示一個紋理坐标的(s,t,p)分量值,其中 p 分量一般用于 3D 紋理;
  6. usemtl 01___Default

    表示使用指定 mtl 檔案中名為

    01___Default

    的材質;
  7. s 1

    表示開啟平滑渲染;
  8. f

    開頭的行表示存放的是一個三角面的資訊,後面有三組資料分别表示組成三角面的三個頂點的資訊,每個頂點資訊的格式為:頂點位置索引/紋理坐标索引/法向量索引。

mtl 檔案的結構:

# 3ds Max Wavefront OBJ Exporter v0.97b - (c)2019 guruware
# File Created: 25.01.2019 02:22:51

newmtl 01___Default
    Ns 10.0000
    Ni 1.5000
    d 1.0000
    Tr 0.0000
    Tf 1.0000 1.0000 1.0000 
    illum 2
    Ka 0.0000 0.0000 0.0000
    Kd 0.0000 0.0000 0.0000
    Ks 0.0000 0.0000 0.0000
    Ke 0.0000 0.0000 0.0000
    map_Ka 4096_earth.jpg
    map_Kd 4096_earth.jpg
    map_Ke 4096_night_lights.jpg
    map_bump 4096_bump.jpg
    bump 4096_bump.jpg

newmtl 02___Default
    Ns 10.0000
    Ni 1.5000
    d 1.0000
    Tr 0.0000
    Tf 1.0000 1.0000 1.0000 
    illum 2
    Ka 0.5882 0.5882 0.5882
    Kd 0.5882 0.5882 0.5882
    Ks 0.0000 0.0000 0.0000
    Ke 0.0000 0.0000 0.0000
    map_Ka 4096_clouds.jpg
    map_Kd 4096_clouds.jpg
    map_d 4096_clouds.jpg      

mtl 檔案結構說明:

  1. newmtl 01___Default

    表示定義一個名為

    01___Default

  2. Ns

    表示材質的反射指數,反射指數越高則高光越密集,取值範圍在一般為 [0,1000];
  3. Ni

    表示材質的折射值(折射率),一般取值範圍是 [0.001,10] ,取值為 1.0,表示光在通過物體的時候不發生彎曲,玻璃的折射率為 1.5 ;
  4. d

    表示材質的漸隐指數(通透指數),取值為 1.0 表示完全不透明,取值為 0.0 時表示完全透明;
  5. Tr

    表示材質的透明度(與

    d

    的取值相反),預設值為0.0(完全不透明);
  6. Tf

    表示材質的濾光折射率,三維向量表示;
  7. illum

    表示材質的光照模型;
  8. Ka

    表示材質的環境光(Ambient Color)(r,g,b);
  9. Kd

    表示材質的散射光(Diffuse Color)(r,g,b);
  10. Ks

    表示材質的鏡面光(Apecular Color)(r,g,b);
  11. Ke

    表示材質的發射光,它與環境光,散射光和鏡面光并存,代表材質發出的光量;
  12. map_Ka

    表示為材質的環境反射指定紋理檔案(紋理采樣值與環境光相乘作為輸出顔色的一部分權重);
  13. map_Kd

    表示為材質的漫反射指定紋理檔案;
  14. map_Ke

    表示為材質的發射光指定紋理檔案;
  15. map_d

    表示為材質的透明度指定紋理檔案;
  16. bump

    表示指定材質的凹凸紋理檔案,凹凸紋理修改表面法線,用于凹凸紋理的圖像表示相對于平均表面的表面拓撲或高度(沒用過)。

模型加載庫 Assimp

Assimp 全稱為 Open Asset Import Library,可以支援幾十種不同格式的模型檔案的解析(同樣也可以導出部分模型格式),Assimp 本身是 C++ 庫,可以跨平台使用。

Assimp 可以将幾十種模型檔案都轉換為一個統一的資料結構,所有無論我們導入何種格式的模型檔案,都可以用同一個方式去通路我們需要的模型資料。

當導入一個模型檔案時,Assimp 将加載該模型檔案所包含的所有模型和場景資料到一個 scene 對象,為這個模型檔案中的所有場景節點、模型節點都生成一個具有對應關系的資料結構,如下圖所示:

NDK OpenGL ES 3.0 開發(二十):3D 模型OpenGLES 3D 模型OBJ 檔案的結構模型加載庫 Assimp

一個模型往往是由很多小模型組成,這些小模型在 Assimp 中稱之為 Mesh ,Mesh 進行獨立渲染,Mesh 對象本身包含渲染所需的所有相關資料,比如頂點位置、法向量、紋理坐标以及物體的材質。

編譯模型加載庫 Assimp

Assimp 源代碼位址:https://github.com/assimp/assimp

環境準備:

Windows 7 
Android Studio 版本> 2.3.0 (帶有 NDK 和 CMake)
Python 3.5       
  1. 從 Github 下載下傳 Assimp(本文使用的是 assimp-v.5.0.0) 源碼并解壓到一個建立檔案夾 BuildAssimp 中;
  2. 在 BuildAssimp 檔案夾建立一個 make_standalone_toolchain.bat 檔案用于建立編譯所需的工具鍊,該檔案内容如下:
python D:/AndroidSDK/Sdk/ndk-bundle/build/tools/make_standalone_toolchain.py --arch=arm --stl=libc++ --api=24 --install-dir=android-toolchain-24-llvm-arm      

D:/AndroidSDK/Sdk/ndk-bundle/build/tools/make_standalone_toolchain.py

需要換成你本地的 Android SDK 中的工具鍊建構腳本。

輕按兩下腳本,執行完成後,會在目前目錄下(BuildAssimp 檔案夾中)生成一個新的檔案夾 android-toolchain-24-llvm-arm ,它是我們用于編譯 32 位的 assimp 庫用到的工具鍊。

  1. 在 BuildAssimp 檔案夾中建立一個 build_assimp.bat 檔案,用于編譯生成 assimp.so 檔案,其内容如下:
@echo off
cls

REM *NOTE* Change these based on 
SET ASSIMP_DIR=assimp-v.5.0.0
SET OUTPUT_DIR=assimp-build-arm
SET ANDROID_PATH=D:\AndroidSDK\Sdk
SET NDK_PATH=D:\AndroidSDK\Sdk\ndk-bundle
SET NDK_TOOLCHAIN=%~dp0android-toolchain-24-llvm-arm
SET CMAKE_TOOLCHAIN=%NDK_PATH%\build\cmake\android.toolchain.cmake
SET CMAKE_PATH=%ANDROID_PATH%\cmake\3.6.4111459

REM *NOTE* Careful if you don't want rm -rf, I use it for testing purposes.
del /F /S /Q %OUTPUT_DIR%
mkdir %OUTPUT_DIR%

REM pushd doesn't seem to work ):<
cd %OUTPUT_DIR%

if not defined ORIGPATH set ORIGPATH=%PATH%
SET PATH=%CMAKE_PATH%\bin;%ANDROID_PATH%\tools;%ANDROID_PATH%\platform-tools;%ORIGPATH%

cmake ^
      -GNinja ^
      -DCMAKE_TOOLCHAIN_FILE=%CMAKE_TOOLCHAIN% ^
      -DASSIMP_ANDROID_JNIIOSYSTEM=ON ^
      -DANDROID_NDK=%NDK_PATH% ^
      -DCMAKE_MAKE_PROGRAM=%CMAKE_PATH%\bin\ninja.exe ^
      -DCMAKE_BUILD_TYPE=Release ^
      -DANDROID_ABI="armeabi-v7a" ^
      -DANDROID_NATIVE_API_LEVEL=24 ^
      -DANDROID_FORCE_ARM_BUILD=TRUE ^
      -DCMAKE_INSTALL_PREFIX=install ^
      -DANDROID_STL=c++_static ^
      -DCMAKE_CXX_FLAGS=-Wno-c++11-narrowing ^
      -DANDROID_TOOLCHAIN=clang ^

      -DASSIMP_BUILD_TESTS=OFF ^

      ../%ASSIMP_DIR%

cmake --build .

cd ..

pause
      

這裡需要配置你的 Android SDK 和 NDK path 。

NDK OpenGL ES 3.0 開發(二十):3D 模型OpenGLES 3D 模型OBJ 檔案的結構模型加載庫 Assimp

輕按兩下腳本,執行完成後,會在 BuildAssimp 檔案夾下生成一個新的檔案夾 android-toolchain-24-llvm-arm ,編譯通過後會在 android-toolchain-24-llvm-arm/code/ 下生成 32 位的 assimp.so 檔案。

下一節中将會使用 assimp.so 去加載 obj 模型檔案,然後利用 OpenGL ES 渲染模型。

「視訊雲技術」你最值得關注的音視訊技術公衆号,每周推送來自阿裡雲一線的實踐技術文章,在這裡與音視訊領域一流工程師交流切磋。
NDK OpenGL ES 3.0 開發(二十):3D 模型OpenGLES 3D 模型OBJ 檔案的結構模型加載庫 Assimp

繼續閱讀