作者:位元組流動
來源:
https://blog.csdn.net/Kennethdroid/article/details/103771970OpenGLES 3D 模型
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 檔案資料結構的簡單說明:
-
開頭的行表示注釋行;#
-
表示指定該 OBJ 檔案所使用的 mtl 檔案(材質檔案);mtllib
-
開頭的行表示存放的是頂點坐标,後面三個數分别表示一個頂點的(x,y,z)坐标值;v
-
開頭的行表示存放的是頂點法向量,後面三個數分别表示一個頂點法向量的三維(x,y,z)分量值;vn
-
開頭的行表示存放的是紋理坐标,後面三個數分别表示一個紋理坐标的(s,t,p)分量值,其中 p 分量一般用于 3D 紋理;vt
-
表示使用指定 mtl 檔案中名為usemtl 01___Default
的材質;01___Default
-
表示開啟平滑渲染;s 1
-
開頭的行表示存放的是一個三角面的資訊,後面有三組資料分别表示組成三角面的三個頂點的資訊,每個頂點資訊的格式為:頂點位置索引/紋理坐标索引/法向量索引。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 檔案結構說明:
-
表示定義一個名為newmtl 01___Default
01___Default
-
表示材質的反射指數,反射指數越高則高光越密集,取值範圍在一般為 [0,1000];Ns
-
表示材質的折射值(折射率),一般取值範圍是 [0.001,10] ,取值為 1.0,表示光在通過物體的時候不發生彎曲,玻璃的折射率為 1.5 ;Ni
-
表示材質的漸隐指數(通透指數),取值為 1.0 表示完全不透明,取值為 0.0 時表示完全透明;d
-
表示材質的透明度(與Tr
的取值相反),預設值為0.0(完全不透明);d
-
表示材質的濾光折射率,三維向量表示;Tf
-
表示材質的光照模型;illum
-
表示材質的環境光(Ambient Color)(r,g,b);Ka
-
表示材質的散射光(Diffuse Color)(r,g,b);Kd
-
表示材質的鏡面光(Apecular Color)(r,g,b);Ks
-
表示材質的發射光,它與環境光,散射光和鏡面光并存,代表材質發出的光量;Ke
-
表示為材質的環境反射指定紋理檔案(紋理采樣值與環境光相乘作為輸出顔色的一部分權重);map_Ka
-
表示為材質的漫反射指定紋理檔案;map_Kd
-
表示為材質的發射光指定紋理檔案;map_Ke
-
表示為材質的透明度指定紋理檔案;map_d
-
表示指定材質的凹凸紋理檔案,凹凸紋理修改表面法線,用于凹凸紋理的圖像表示相對于平均表面的表面拓撲或高度(沒用過)。bump
模型加載庫 Assimp
Assimp 全稱為 Open Asset Import Library,可以支援幾十種不同格式的模型檔案的解析(同樣也可以導出部分模型格式),Assimp 本身是 C++ 庫,可以跨平台使用。
Assimp 可以将幾十種模型檔案都轉換為一個統一的資料結構,所有無論我們導入何種格式的模型檔案,都可以用同一個方式去通路我們需要的模型資料。
當導入一個模型檔案時,Assimp 将加載該模型檔案所包含的所有模型和場景資料到一個 scene 對象,為這個模型檔案中的所有場景節點、模型節點都生成一個具有對應關系的資料結構,如下圖所示:
一個模型往往是由很多小模型組成,這些小模型在 Assimp 中稱之為 Mesh ,Mesh 進行獨立渲染,Mesh 對象本身包含渲染所需的所有相關資料,比如頂點位置、法向量、紋理坐标以及物體的材質。
編譯模型加載庫 Assimp
Assimp 源代碼位址:https://github.com/assimp/assimp環境準備:
Windows 7
Android Studio 版本> 2.3.0 (帶有 NDK 和 CMake)
Python 3.5
- 從 Github 下載下傳 Assimp(本文使用的是 assimp-v.5.0.0) 源碼并解壓到一個建立檔案夾 BuildAssimp 中;
- 在 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 庫用到的工具鍊。
- 在 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 。
輕按兩下腳本,執行完成後,會在 BuildAssimp 檔案夾下生成一個新的檔案夾 android-toolchain-24-llvm-arm ,編譯通過後會在 android-toolchain-24-llvm-arm/code/ 下生成 32 位的 assimp.so 檔案。
下一節中将會使用 assimp.so 去加載 obj 模型檔案,然後利用 OpenGL ES 渲染模型。
「視訊雲技術」你最值得關注的音視訊技術公衆号,每周推送來自阿裡雲一線的實踐技術文章,在這裡與音視訊領域一流工程師交流切磋。