OpenSceneGraph for Android編譯

OpenSceneGraph是一款多平臺的3D場景渲染引擎API,以下簡稱為了OSG,OSG的官網(wǎng)只提供了源碼,想使用的話必須自己手動編譯。這里以官方的3.6.5版為例講解如何編譯出能在Android平臺使用的so包,并成功的運行官方的Demo程序。

官方推薦編譯最好在Linux環(huán)境下進行,但因為我的Android Studio卻是運行在Windows 10下的,所以最好的辦法就是給Windows10裝了個Linux子系統(tǒng),進入“程序和功能”>“啟用和關閉Windows功能”。然后在拉到底部勾選“適用于Linux的Windows子系統(tǒng)”,等上幾分鐘后這個功能就裝完了。


linux.png

然后在Windows10的應用市場Microsoft Store里搜索Ubuntu并安裝就可以了,這樣裝出來的Ubuntu是沒有圖形界面只有字符界面的,但已經(jīng)能滿足編譯的需要了。

首次進入Ubuntu時會要求你創(chuàng)建一個用戶號,然后對Ubuntu該升級的升級,改安裝的安裝,主要是把cmake gcc這些程序都要裝上。

sudo apt-get update
sudo apt-get upgrade
sudo apt-get install cmake -y
sudo apt install build-essential -y

然后去Github上下載最新的3.6.5的壓縮包:https://github.com/openscenegraph/OpenSceneGraph/tree/OpenSceneGraph-3.6.5
然后對壓縮包進行解壓,為了便于之后將其復制到Ubuntu下使用,我就直接解壓到c盤并且把目錄命名為了OpenSceneGraph。

由于OSG的編譯還需要用到第三方的代碼包3rdParty,但可惜的是官網(wǎng)并并不提供下載,需要我們自己到網(wǎng)上去下載,然后將下載的壓縮包解壓到OpenSceneGraph\3rdParty目錄下。

接著我們需要下載Android NDK,可以直接從官網(wǎng)上下載:
https://developer.android.google.cn/ndk/downloads/index.html?hl=zh-cn
下載完畢后依舊是解壓到C盤。

OSG和NDK都下載解壓完了之后就可以復制到Ubuntu系統(tǒng)上了,這里我推薦用命令方式復制:

sudo cp -r /mnt/c/OpenSceneGraph /home/xrf/
sudo cp -r /mnt/c/android-ndk-r21c /home/xrf/

在OSG365目錄下新一個build目錄用以存放編譯后的文件,并授予全部的權限,如果忘記授權的話可能會因為權限不夠而報錯。

cd OpenSceneGraph
mkdir build
cd ../..
sudo chmod -R 777 osg365/

接著直接在build目錄下開始編譯

cmake ../ -DANDROID_NDK=/home/xrf/Android/android-ndk-r21e -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE=/home/xrf/Android/android-ndk-r21e/build/cmake/android.toolchain.cmake -DANDROID_STL=c++_static -DCMAKE_CXX_FLAGS="-std=c++11 -frtti -fexceptions -stdlib=libc++ -DUSE_ZLIB" -DANDROID_TOOLCHAIN=clang -DANDROID_PLATFORM=android-19 -DANDROID_ABI=armeabi-v7a -DCMAKE_INSTALL_PREFIX="./armeabi-v7a" -DOPENGL_PROFILE="GLES2" -DDYNAMIC_OPENTHREADS=OFF -DDYNAMIC_OPENSCENEGRAPH=OFF

參數(shù)中的DANROID_PLATFORM表示的是Android API最低支持的版本號。
DANDROID_ABI有的是armeabi-v7a,這個是arm的32位版本,如果想要64位的可以換成arm64-v8a。


cmake命令完成

然后用make命令開始生成靜態(tài)庫文件,這個過程大約要一兩個小時,中途會看到一些warning級別的警告,這都不用擔心,只要能進行到100%就可以,否則就可能是3rdParty包的某些文件出了問題,建議重新下載出問題的代碼文件。

全部完成后記得執(zhí)行make install命令,這個命令結束后會在build目錄下多出一個armeabi-v7a目錄,里包含了include、src和obj三個子目錄。接著再用系統(tǒng)命令把armeabi-v7a目錄復制到Windows的C盤下;

sudo cp -r armeabi-v7a/ /mnt/c/

至此與Ubuntu相關的操作就結束了。概括起來就是我們在Ubuntu下用cmake、make、make install完成了OSG靜態(tài)庫文件的編譯。

接著該是Android Studio出場的時候了,首先導入OSG的示例項目osgAndroidExampleG2。這個Demo是以NDK方式創(chuàng)建的,而且配置的路徑都是針對Linux環(huán)境設置的,所以需要手動修改。
Application.mk內容如下:

#ANDROID APPLICATION MAKEFILE
APP_BUILD_SCRIPT := $(call my-dir)/Android.mk
#APP_PROJECT_PATH := $(call my-dir)

APP_OPTIM := release

APP_PLATFORM    := android-19
APP_STL         := c++_static
APP_CPPFLAGS    := -fexceptions -frtti
APP_ABI         := armeabi-v7a
APP_MODULES     := osgNativeLib

APP_PLATFORM指定的最低本要和Cmake命令里的DANDROID_PLATFORM一致,然后再修改Android.mk內容:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := osgNativeLib
### Main Install dir
OSG_ANDROID_DIR := C:/osg365
NDK_ROOT        := C:/Users/你的目錄/AppData/Local/Android/Sdk/ndk/21.4.7075529
LIBDIR          := $(OSG_ANDROID_DIR)/obj/local/armeabi

ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
    LOCAL_ARM_NEON  := true
    LIBDIR          := $(OSG_ANDROID_DIR)/obj/local/armeabi-v7a
endif

### Add all source file names to be included in lib separated by a whitespace

LOCAL_C_INCLUDES:= $(OSG_ANDROID_DIR)/include
LOCAL_CFLAGS    := -fdata-sections -ffunction-sections -DANDROID
LOCAL_CPPFLAGS  := -frtti -fno-exceptions -fdata-sections -ffunction-sections -DANDROID

LOCAL_LDLIBS    := -llog -lGLESv2 -lz
LOCAL_SRC_FILES := osgNativeLib.cpp OsgMainApp.cpp OsgAndroidNotifyHandler.cpp
LOCAL_C_INCLUDES += $(NDK_ROOT)/sources/cxx-stl/llvm-libc++/include
LOCAL_C_INCLUDES += $(NDK_ROOT)/sources/cxx-stl/llvm-libc++/libs/armeabi-v7a

LOCAL_ALLOW_UNDEFINED_SYMBOLS := true

LOCAL_LDFLAGS   := -L $(LIBDIR) \
-l$(OSG_ANDROID_DIR)/lib/osgPlugins-3.6.5/libosgdb_dds.a \
-l$(OSG_ANDROID_DIR)/lib/osgPlugins-3.6.5/libosgdb_openflight.a \
-l$(OSG_ANDROID_DIR)/lib/osgPlugins-3.6.5/libosgdb_tga.a \
-l$(OSG_ANDROID_DIR)/lib/osgPlugins-3.6.5/libosgdb_rgb.a \
-l$(OSG_ANDROID_DIR)/lib/osgPlugins-3.6.5/libosgdb_osgterrain.a \
-l$(OSG_ANDROID_DIR)/lib/osgPlugins-3.6.5/libosgdb_osg.a \
-l$(OSG_ANDROID_DIR)/lib/osgPlugins-3.6.5/libosgdb_ive.a \
-l$(OSG_ANDROID_DIR)/lib/osgPlugins-3.6.5/libosgdb_deprecated_osgviewer.a \
-l$(OSG_ANDROID_DIR)/lib/osgPlugins-3.6.5/libosgdb_deprecated_osgvolume.a \
-l$(OSG_ANDROID_DIR)/lib/osgPlugins-3.6.5/libosgdb_deprecated_osgtext.a \
-l$(OSG_ANDROID_DIR)/lib/osgPlugins-3.6.5/libosgdb_deprecated_osgterrain.a \
-l$(OSG_ANDROID_DIR)/lib/osgPlugins-3.6.5/libosgdb_deprecated_osgsim.a \
-l$(OSG_ANDROID_DIR)/lib/osgPlugins-3.6.5/libosgdb_deprecated_osgshadow.a \
-l$(OSG_ANDROID_DIR)/lib/osgPlugins-3.6.5/libosgdb_deprecated_osgparticle.a \
-l$(OSG_ANDROID_DIR)/lib/osgPlugins-3.6.5/libosgdb_deprecated_osgfx.a \
-l$(OSG_ANDROID_DIR)/lib/osgPlugins-3.6.5/libosgdb_deprecated_osganimation.a \
-l$(OSG_ANDROID_DIR)/lib/osgPlugins-3.6.5/libosgdb_deprecated_osg.a \
-l$(OSG_ANDROID_DIR)/lib/osgPlugins-3.6.5/libosgdb_serializers_osgvolume.a \
-l$(OSG_ANDROID_DIR)/lib/osgPlugins-3.6.5/libosgdb_serializers_osgtext.a \
-l$(OSG_ANDROID_DIR)/lib/osgPlugins-3.6.5/libosgdb_serializers_osgterrain.a \
-l$(OSG_ANDROID_DIR)/lib/osgPlugins-3.6.5/libosgdb_serializers_osgsim.a \
-l$(OSG_ANDROID_DIR)/lib/osgPlugins-3.6.5/libosgdb_serializers_osgshadow.a \
-l$(OSG_ANDROID_DIR)/lib/osgPlugins-3.6.5/libosgdb_serializers_osgparticle.a \
-l$(OSG_ANDROID_DIR)/lib/osgPlugins-3.6.5/libosgdb_serializers_osgmanipulator.a \
-l$(OSG_ANDROID_DIR)/lib/osgPlugins-3.6.5/libosgdb_serializers_osgfx.a \
-l$(OSG_ANDROID_DIR)/lib/osgPlugins-3.6.5/libosgdb_serializers_osganimation.a \
-l$(OSG_ANDROID_DIR)/lib/osgPlugins-3.6.5/libosgdb_serializers_osg.a \
-l$(OSG_ANDROID_DIR)/lib/libosgViewer.a \
-l$(OSG_ANDROID_DIR)/lib/libosgVolume.a \
-l$(OSG_ANDROID_DIR)/lib/libosgTerrain.a \
-l$(OSG_ANDROID_DIR)/lib/libosgText.a \
-l$(OSG_ANDROID_DIR)/lib/libosgShadow.a \
-l$(OSG_ANDROID_DIR)/lib/libosgSim.a \
-l$(OSG_ANDROID_DIR)/lib/libosgParticle.a \
-l$(OSG_ANDROID_DIR)/lib/libosgManipulator.a \
-l$(OSG_ANDROID_DIR)/lib/libosgGA.a \
-l$(OSG_ANDROID_DIR)/lib/libosgFX.a \
-l$(OSG_ANDROID_DIR)/lib/libosgdb.a \
-l$(OSG_ANDROID_DIR)/lib/libosgAnimation.a \
-l$(OSG_ANDROID_DIR)/lib/libosgUtil.a \
-l$(OSG_ANDROID_DIR)/lib/libosg.a \
-l$(OSG_ANDROID_DIR)/lib/libOpenThreads.a

include $(BUILD_SHARED_LIBRARY)

OSG_ANDROID_DIR指的是之前從Ubuntu復制出來的armeabi-v7a目錄,為了便于管理而改名成了osg365。
NDK_ROOT指的是Windows版的NDK,注意NDK的版本要和Ubuntu使用的版本一致,不然會出報錯。
此外也要注意路徑中用的斜杠是“/”。

然后刪除AndroidManifest.xml里的uses-sdk節(jié)點,因為節(jié)點里的內容可以在app模塊的build.gradle里配置。

接著就開始配置app的build.gradle文件,并實現(xiàn)Android Studio對C/C++代碼的自動提示功能

android {
    compileSdkVersion 30
    buildToolsVersion "30.0.3"

    defaultConfig {
        applicationId "com.anroid.nativecxx"
        minSdkVersion 19
        targetSdkVersion 30
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        ndk {
            moduleName "osgNativeLib"
            abiFilters "armeabi-v7a"
        }
    }

    ... 

    packagingOptions {
        pickFirst 'lib/armeabi-v7a/libosgNativeLib.so'
    }
    sourceSets.main{
        jni.srcDirs = []
        jniLibs.srcDir "src/main/libs"
    }
    externalNativeBuild {
        ndkBuild {
            path file('src/main/jni/Android.mk')
        }
    }
    ndkVersion '21.4.7075529'
}

修改local.properties用于指定ndk的目錄,注意把路徑改成你的本地路徑

ndk.dir=C\:\\Users\\你的目錄\\AppData\\Local\\Android\\Sdk\\ndk\\21.4.7075529
sdk.dir=C\:\\Users\\你的目錄\\AppData\\Local\\Android\\Sdk

最后記得在Windows的“環(huán)境變量”下配置ndk的路徑到path下,配完后重啟下Android Studio后,選中jni并打開“Terminal”窗口輸入ndk-build。一切成功后就可以在src/main/libs下看到生成的so文件了。


ndk_build成功

so文件被稱為動態(tài)鏈接文件,相當于Windows下的dll文件,Java會將so文件作為函數(shù)庫引入,并將定義為native類型的方法和so內的相關函數(shù)鏈接起來。

為了方便看到編譯后的效果,需要從官網(wǎng)下載示例文件,這里有cow.osg為例。先將這個文件用DeviceFileExplorer上傳到app的files目錄下,再修改代碼:

    @Override
    protected void onResume() {
        super.onResume();
        mView.onResume();
        String address = getFilesDir()+File.separator+"cow.osg";
        osgNativeLib.loadObject(address);
    }

然后編譯一下就可以看到效果了。


運行效果
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容