Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> OSG for Android新手教程系列(二)——項目配置

OSG for Android新手教程系列(二)——項目配置

編輯:關於Android編程

在上一篇教程中,主要介紹了如何把OSG源代碼編譯成為能夠在Android項目下使用的函數庫。在這一篇教程中,我將針對如何在自己的Android項目中配置OSG函數庫進行詳細講解。

現階段網上關於OSGfor Android的配置方式教程有很多,但是大部分在實際使用起來都會或多或少的出現一些問題,無法完全照搬,需要一定的修改。而且,對於配置中的那些變量的具體含義,也很少有人能夠進行仔細的講解。這非常不利於新手的學習和理解,往往會造成出現bug後面對滿屏幕的錯誤log完全一臉茫然的情況。

所以我將在這篇教程中詳細介紹系統的介紹如何在Android項目中配置OSG函數庫,並對各個配置變量的含義進行詳細講解。

-------------------------------------------------------------------------------------------------

在一個項目中配置函數庫,是我們在進行項目開發時幾乎都要做的第一件事情。可以說,各種第三方函數庫幫助我們完成了很多通用的常用的功能,使我們從繁雜的基本算法、基本功能中脫離出來,能夠更專心的完成我們需要實現的業務功能。OSG就是一個非常好的開源三維引擎,提供了一套成熟的API用於實現三維場景功能的開發。

 

一、工具准備

OSG是基於C++平台的API,在開發時使用的都是標准的C++。眾所周知,開發Android項目,我們平常使用的都是Java,那麼,如何才能在Java語言中調用OSG的這些C++函數呢?Java中提供了Java本地接口,即JNI(Java Native Interface)。JNI是一個協議,用於溝通Java代碼和本地的C/C++代碼。而Google公司為Android開發了一套用於快速創建native工程的工具集合,即NDK(Native Development Kit)。在本文中,將使用Eclipese+NDK的方式進行配置開發。網上有許多的經驗教程用到了Cygwin。但是,從NDK的r7版本以上就包含了Cygwin,所以本文在配置項目時,並沒有單獨使用Cygwin。

這裡使用的NDK版本是r10d,可以在官方網站上下載,鏈接為:

http://developer.android.com/tools/sdk/ndk/index.html。

當然,由於一些原因,現在很多情況下是連接不上這個網站的,比如我就是。不過現在很多網盤上有共享的可以下載,大家可以自行搜一下。OSG函數庫可以根據我前一篇教程裡講的那樣自己進行編譯,不過時間花費比較大,當然也可以從網上下載別人已經編譯好的OSG函數庫,這樣省時省力。這裡我使用的是3.0.1版本的OSG。需要注意的是,上一篇教程講過,在編譯時根據參數不同,會有兩個版本的OSG庫,分別是GLES1和GLES2,這兩個版本在使用時,配置的參數會有所不同,甚至會對新手來說產生一些莫名其妙的錯誤。具體的區別,我會詳細的說明一下。

 

二、具體配置

首先,為了在項目中使用C/C++,在項目結構上會有一點不同,需要增加一個jni文件夾,其位置在項目的根目錄下,與src等文件夾在同一層。這個文件夾用於存放所有的C/C++文件,以及項目配置文件(.mk後綴)。下面進行詳細講解。

 

1. 配置文件

在OSG for Android項目中,配置文件有兩個,一個是Android.mk,另一個是Application.mk。這兩個文件都是存放在jni文件夾內的,用於在編譯項目時提供配置信息。

首先,我們來看Android.mk文件的配置方式。

 

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := osgNativeLib
#OSG_ANDROID_DIR := D:/MyTools/osggles2_3_0_1
OSG_ANDROID_DIR := D:/MyTools/osggles1_3_0_1
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    := -fno-short-enums
LOCAL_CPPFLAGS  := -DOSG_LIBRARY_STATIC

LOCAL_LDLIBS := -L $(SYSROOT)/usr/lib -llog
#LOCAL_LDLIBS += -L $(SYSROOT)/usr/lib -lGLESv2
LOCAL_LDLIBS += -L $(SYSROOT)/usr/lib -lGLESv1_CM
LOCAL_LDLIBS += -L $(SYSROOT)/usr/lib -lz
LOCAL_LDLIBS += -L $(SYSROOT)/usr/lib -gnustl_static
LOCAL_LDLIBS += -landroid

LOCAL_SRC_FILES :=osgMain.cpp osgNativeLib.cpp modelUtil.cpp AnimationUtil.cpp ExternVariables.cpp

LOCAL_LDFLAGS   := -L $(LIBDIR) -losgdb_dds\
-losgdb_openflight\
-losgdb_tga\
-losgdb_rgb\
-losgdb_osgterrain\
-losgdb_osg\
-losgdb_ive\
-losgdb_deprecated_osgviewer\
-losgdb_deprecated_osgvolume\
-losgdb_deprecated_osgtext\
-losgdb_deprecated_osgterrain\
-losgdb_deprecated_osgsim\
-losgdb_deprecated_osgshadow\
-losgdb_deprecated_osgparticle\
-losgdb_deprecated_osgfx\
-losgdb_deprecated_osganimation\
-losgdb_deprecated_osg\
-losgdb_serializers_osgvolume\
-losgdb_serializers_osgtext\
-losgdb_serializers_osgterrain\
-losgdb_serializers_osgsim\
-losgdb_serializers_osgshadow\
-losgdb_serializers_osgparticle\
-losgdb_serializers_osgmanipulator\
-losgdb_serializers_osgfx\
-losgdb_serializers_osganimation\
-losgdb_serializers_osg\
-losgViewer\
-losgVolume\
-losgTerrain\
-losgText\
-losgShadow\
-losgSim\
-losgParticle\
-losgManipulator\
-losgGA\
-losgFX\
-losgDB\
-losgAnimation\
-losgUtil\
-losg\
-lOpenThreads\
-lgnustl_static\
-lgdal

include $(BUILD_SHARED_LIBRARY)
#include $(BUILD_STATIC_LIBRARY)

  下面對各個配置變量進行詳細講解。

 

LOCAL_PATH:這個變量用於在項目結構樹中查找源文件。在這個例子中,對其配置為$(call my-dir),這是一個宏函數,由編譯系統提供,表示返回當前路徑,也就是包含了這個Android.mk文件的路徑;

include $(CLEAR_VARS):這句配置的意思是清空之前的除了LOCAL_PATH以外的所有LOCAL_XXX的變量配置。可以看出,我們所需要配置的變量都必須在這條配置語句之後進行,不然即使配置了,也會被這句給清空掉;

LOCAL_MODULE:這個變量表示的是該配置文件描述的模塊的名稱,這個名稱是唯一的。而且這個配置變量必須配置。在編譯過程中,編譯系統根據這個變量自動生成庫動態庫的名稱,一般情況下,生成的動態庫會以libxxx.so為名,其中的xxx就是LOCAL_MODULE變量配置時的名稱;

OSG_ANDROID_DIR:這個配置變量表示的是OSG的所在位置,即經過編譯的OSG的位置。在這個例子中,我寫了兩個路徑,其中一個是被#注釋掉的。之前也我提到過,OSG for Android在編譯時根據參數不同,會產生兩個版本,分別是GLES1和GLES2,這兩個版本的OSG在配置時是不同的,這裡就是不同點之一;

LIBDIR:這個配置變量是指向OSG函數庫的位置,根據OSG_ANDROID_DIR所指向的OSG位置,向下尋找靜態庫的位置。其實,如果我們打開這個文件夾,我們可以發現一系列後綴為.a的文件,這些文件就是OSG的靜態庫。接下來的四行代碼,則是用於判斷目標ABI(即應用程序二進制接口),根據判斷結果重新配置靜態庫位置;

LOCAL_C_INCLUDES:這個變量指向相應版本OSG的include文件夾,用於指定OSG頭文件位置;

LOCAL_CFLAGS:這個變量是一個可選設置的變量,用於附加編譯選項。在編寫配置文件時,可以照搬此處的設置,無需修改;

LOCAL_CPPFLAGS:與上一個變量類似,區別是這個變量用於對cpp文件編譯進行設置,從字面意思就可以看出,同上,可照搬。

LOCAL_LDLIBS:用於添加系統。注意!在配置這個變量時,其中存在對GLES1和GLES2兩個版本配置的不同,這是第二個不同的地方。尤其需要注意的是,在選擇使用GLES1版本的OSG時,該變量配置的是-lGLESv1_CM,而不是想當然的-lGLESv1!新手在剛接觸時,很容易犯這個錯,而且很難察覺到。其余照搬即可。

LOCAL_SRC_FILES:在這裡列出需要編譯進動態庫的c和cpp文件。只要用到的c或cpp文件都要加進來,編譯系統會根據這個變量的值來尋找文件,如果不加進來,編譯系統就找不到相應的文件,就會造成編譯錯誤。

LOCAL_LDFLAGS:這個配置變量與LOCAL_LDLIBS變量功能類似,也是用於添加系統庫的功能。

include $(BUILD_SHARED_LIBRARY):這句代碼的意思是將該模塊定義為動態庫,即.so文件。該例子中最後還有一句被#注釋掉的include $(BUILD_STATIC_LIBRARY),這是指定該模塊生成靜態庫,即.a文件。

  下面我們再來看一下另一個配置文件,即Application.mk文件的配置方法。

 

APP_BUILD_SCRIPT := $(call my-dir)/Android.mk

APP_OPTIM := release

APP_PLATFORM 	:= android-10
APP_STL 	:= gnustl_static
APP_CPPFLAGS 	:= -fexceptions -frtti
APP_ABI 	:= armeabi armeabi-v7a
APP_MODULES     := osgNativeLib

 

下面對各個變量進行詳細講解。

APP_BUILD_SCRIPT:這個變量將在當前路徑下尋找Android.mk,也就是之前我們進行配置的mk文件;

APP_OPTIM:這是個可選變量,其值可以設置為release或者debug。當設置為release時,將會生成高度優化的二進制代碼,而設置為debug時,生成的是未優化的二進制代碼,但可以檢測出很多的BUG,可以用於調試;

APP_PLATFORM:這個變量用於設置該項目的最小運行平台,需要注意的是,網上有很多教程,在這裡設置的是android-8,但是根據我的測試,如果設置為android-8,會出現一些找不到文件的錯誤,但是設置為android-10以上,則可以正常編譯;

APP_STL:這個變量設置為gnustl_static,表示使用GNU libstlc++作為靜態庫;

APP_CPPFLAGS:這個變量用於設置一個c++編譯器開關集合,在編譯任意模塊的任意C或C++源代碼時傳遞。它可以用於改變一個給定的應用程序需要依賴的模塊的構建,而不是修改它自身的Android.mk文件;

APP_ABI:用於設置二進制程序接口,默認情況下為armeabi,本文中的例子同時設置了armeabi和armeabi-v7a。注意!網上有的例子裡面在這裡同時設置了x86,根據我的測試,加上x86後會產生NDK的Abortting stop的錯誤,所以,不要添加-x86

APP_MODULES:這個變量列出編譯所需要的模塊名稱。模塊名稱就是我們之前在Android.mk文件中設置的LOCAL_MODULE的值。

2. NDK Builder的配置

  在eclipse左邊的project view裡右擊需要設置的項目,並選擇Properties,如圖所示:

\

進入後在界面左側選擇Builder,然後點擊界面郵編的New按鈕,如圖所示:

\

在Choose configuration type的界面中選擇Program,點擊OK。如圖所示:

\

在出現的設置界面中,在Main選項卡內,Location設置為所用的NDK的安裝目錄下的nkd-build.cmd;Working directory設置為當前工程。在Refresh選項卡內,勾選上Refresh resources upon completion。在Build Options選項卡中,勾選Specify working set of relevent resouces,同時點擊Specify Resouces按鈕,選擇當前工程的jni文件夾。

\

 

\

 

\

 

3. Java中的配置

在Java中的配置比較簡單,但是也是容易遺忘的地方。因為在Android上顯示OSG窗口是基於GLSurfaceView的,那麼在創建GLSurfaceView時需要注意的是,應該根據自己使用的OSG版本對GLSurfaceView的GL版本。這個配置只需要一句代碼:

 

myGLSurfaceView.setEGLContextClientVersion(1);
  因為我的例子中使用的是GLES1版本的OSG庫,所以這裡的值設置為1;同理,如果使用的是GLES2版本的OSG庫,則將其設置為2。這裡是比較容易遺忘的地方。

三、總結

據我了解,很多剛接觸OSG for Android的新手老手,在配置項目時都會遇到這樣或那樣的問題,我在剛接觸時同樣是這樣。出問題的大部分都是對這個配置的內容不是很了解其中的意思,所以會在出了問題後不知道該怎麼辦。我總結了一下容易出錯的地方。

1. 亂加或亂減空格

在mk文件中,對空格似乎十分的敏感。我們很多人有意無意的會習慣性打空格,特別是在一行代碼的末尾處,很容易多一個空格。但是這種情況在mk文件中都有可能引起錯誤。我在剛接觸時,就試過逐行逐行地查看空格是否有多余或遺漏;

2. 在使用GLES1版本的庫時,-lGLESv1_CM的錯誤

也許在看到一些使用GLES2版本的例子上寫著-lGLES2時,會想當然的認為,使用GLES1版本就直接設置為-lGLES1就行了。結果編譯時就會發現出錯了。而且錯誤並沒有直接指向這裡,而是會出現一些找不到OSG頭文件的錯誤,會讓人很摸不著頭腦。其實這種錯誤很大可能就是出現在了這裡。

3. -x86的錯誤

我也看到過一些教程上面提到過,NDK在對x86的兼容上有一些問題,但是仍然有不少示例會加上-x86。這裡我的建議是不要在Application.mk文件的APP_ABI後面添加-x86。

---------------------------------------------------------

OSG for Android新手教程的下一篇將對一個HelloWorld的示例進行詳細講解,通過一個簡單的示例分析怎樣運行起一個最簡單的OSG for Android的程序。敬請關注。

 

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved