zoukankan      html  css  js  c++  java
  • Ogre 1.9 Android移植

     

    Ogre 1.9 Android移植

    分类: 图形渲染

    上一篇博客,将1.8.1这个版本移植到了Android平台,无奈着不是官方版本,不太完美。这次尝试为Android平台构建1.9版本(注意这是个不稳定版本,1.9官方没有正式Release)。

    依赖库官方已经移植好了,直接下载下来就可以了。

    地址 http://sourceforge.net/projects/ogre/files/ogre-dependencies-android/1.9/AndroidDependencies.zip/download

    具体的移植步骤,请看这里的官方文档,很详细了。我就说几个移植中需要注意的地方。

    Android NDK我选的是官方的android-ndk-r8d,顺利的移植了,其他版本无一幸免都有无法检测编译机器类型的错误,应该是Ogre使用的android-cmake版本的问题,具体我没有细究。

    环境变量ANDROID_NDK别忘了,这个是android-cmake脚本要用到的。

    编译出来的,SampleOgreBrowserNDK这个安装包的resources.cfg有点小问题,我做了点修改,修改如下:

    # Resources required by the sample browser and most samples.
    [Essential]
    APKZip=/packs/SdkTrays.zip
    APKFileSystem=/thumbnails

    # Common sample resources needed by many of the samples.
    # Rarely used resources should be separately loaded by the
    # samples which require them.
    [Popular]
    APKFileSystem=/fonts
    APKFileSystem=/materials/programs
    APKFileSystem=/materials/programs/GLSLES
    APKFileSystem=/materials/scripts
    APKFileSystem=/materials/textures
    APKFileSystem=/materials/textures/nvidia
    APKFileSystem=/models
    APKFileSystem=/particle
    APKFileSystem=/RTShaderLib
    APKFileSystem=/RTShaderLib/materials
    APKFileSystem=/RTShaderLib/GLSLES
    APKFileSystem=/materials/scripts/SSAO
    APKFileSystem=/materials/textures/SSAO
    APKZip=/packs/cubemap.zip
    APKZip=/packs/cubemapsJS.zip
    APKZip=/packs/dragon.zip
    APKZip=/packs/fresneldemo.zip
    APKZip=/packs/ogretestmap.zip
    APKZip=/packs/ogredance.zip
    APKZip=/packs/Sinbad.zip
    APKZip=/packs/skybox.zip

    [General]
    APKFileSystem=/

    编译出来的库都是静态链接的,一堆依赖,稍不留神就出问题,可能本人水平不够吧。

    写了个测试程序,SampleBrowser这个项目一堆#ifdef,看着真心头疼,自己写了个简单的Android测试程序。

    先上代码:

    //File: main.cpp

    #include <OgrePlatform.h>
    #include <OgreRoot.h>
    #include <EGL/egl.h>
    #include <GLES/gl.h>

    #include <android/log.h>
    #include <android_native_app_glue.h>

    #ifdef OGRE_STATIC_LIB
    #include <OgreStaticPluginLoader.h>
    #endif

    #ifdef USE_RTSHADER_SYSTEM
    #   include "OgreRTShaderSystem.h"
    #endif

    #include "Android/OgreAPKFileSystemArchive.h"
    #include "Android/OgreAPKZipArchive.h"
    #include "ANDROID/OgreAndroidEGLWindow.h"

    #define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "Ogre", __VA_ARGS__))
    #define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN, "Ogre", __VA_ARGS__))

    #ifdef OGRE_STATIC_LIB
    Ogre::StaticPluginLoader* gStaticPluginLoader;
    #endif

    Ogre::Root* gRoot = NULL;
    Ogre::RenderWindow* gWnd = NULL;
    AAssetManager* gAssetMgr = NULL;
    bool bInit = false;

    static Ogre::DataStreamPtr openAPKFile(const Ogre::String& fileName)
    {
        Ogre::DataStreamPtr stream;
        AAsset* asset = AAssetManager_open(gAssetMgr, fileName.c_str(), AASSET_MODE_BUFFER);
        if(asset) {
            off_t length = AAsset_getLength(asset);
            void* membuf = OGRE_MALLOC(length, Ogre::MEMCATEGORY_GENERAL);
            memcpy(membuf, AAsset_getBuffer(asset), length);
            AAsset_close(asset);

            stream = Ogre::DataStreamPtr(new Ogre::MemoryDataStream(membuf, length, true, true));
        }

        return stream;
    }

    static void handleCmd(struct android_app* app, int32_t cmd)
    {
        switch(cmd)
        {
        case APP_CMD_INIT_WINDOW:
            if(app->window && gRoot) {
                AConfiguration* config = AConfiguration_new();
                AConfiguration_fromAssetManager(config, app->activity->assetManager);

                if(!gWnd) {
                    LOGW("APP_CMD_INIT_WINDOW");
                    Ogre::NameValuePairList opt;
                    opt["externalWindowHandle"] = Ogre::StringConverter::toString((int)app->window);
                    opt["androidConfig"] = Ogre::StringConverter::toString((int)config);
                    gWnd = Ogre::Root::getSingleton().createRenderWindow("OgreWindow", 0, 0, false, &opt);

                    if(gWnd->isFullScreen()) {
                        LOGW("Window Is Fullscreen");
                    }

                    Ogre::Root::getSingleton().getRenderSystem()->_initRenderTargets();

                                // Clear event times
                                Ogre::Root::getSingleton().clearEventTimes();

                    LOGI("CreateSceneManager Begin");
                    Ogre::SceneManager* sm = gRoot->createSceneManager(Ogre::ST_GENERIC, "DummyScene");
                    LOGI("CreateSceneManager End");

                    Ogre::Camera* cam = sm->createCamera("DummyCamera");
                    cam->setPosition(Ogre::Vector3(20, 80, 50));
                    cam->lookAt(Ogre::Vector3(0, 0, 0));
                    cam->setNearClipDistance(5);

                    Ogre::Viewport* vp = gWnd->addViewport(cam);
                    vp->setBackgroundColour(Ogre::ColourValue(0.9, 0.9, 0.9));

                    Ogre::Real fWidth = vp->getActualWidth();
                    Ogre::Real fHeight = vp->getActualHeight();
                    LOGW("fWidth: %f, fHeight: %f", fWidth, fHeight);

                    cam->setAspectRatio(Ogre::Real(vp->getActualWidth()) / Ogre::Real(vp->getActualHeight()));

                    Ogre::TextureManager::getSingleton().setDefaultNumMipmaps(5);

                    sm->setAmbientLight(Ogre::ColourValue(0.9, 0.9, 0.9));
                    sm->createLight()->setPosition(20, 80, 50);

                    sm->setSkyBox(true, "Examples/CloudyNoonSkyBox");
                    Ogre::Entity* head = sm->createEntity("Head", "ogrehead.mesh");
                    Ogre::Entity* head2 = sm->createEntity("Head2", "r5capsule.mesh");

                    Ogre::SceneNode* headNode = sm->getRootSceneNode()->createChildSceneNode();
                    headNode->attachObject(head);
                    headNode->setPosition(0, 0, 0);

                    Ogre::SceneNode* headNode2 = sm->getRootSceneNode()->createChildSceneNode();
                    headNode2->attachObject(head2);
                    headNode2->setPosition(0, 10, 0);

                    gWnd->windowMovedOrResized();
                    bInit = true;
                }else
                {
                    static_cast<Ogre::AndroidEGLWindow*>(gWnd)->_createInternalResources(app->window, config);
                }

                AConfiguration_delete(config);
            }
            break;
        }
    }

    void android_main(struct android_app* state)
    {
        app_dummy();

        gAssetMgr = state->activity->assetManager;

        struct android_pool_source* source;

        state->onAppCmd = &handleCmd;
        gRoot = new Ogre::Root();

    //#ifdef OGRE_STATIC_LIB
        LOGI("Load Plugin");
        gStaticPluginLoader = new Ogre::StaticPluginLoader();
        gStaticPluginLoader->load();
        LOGI("Load Plugin End");
    //#endif
        Ogre::ArchiveManager::getSingleton().addArchiveFactory(new Ogre::APKFileSystemArchiveFactory(gAssetMgr));
        Ogre::ArchiveManager::getSingleton().addArchiveFactory(new Ogre::APKZipArchiveFactory(gAssetMgr));

        gRoot->setRenderSystem(gRoot->getAvailableRenderers().at(0));
        gRoot->initialise(false);

        Ogre::ConfigFile cf;
        cf.load(openAPKFile("resources.cfg"));

        Ogre::ConfigFile::SectionIterator seci = cf.getSectionIterator();
        Ogre::String sec, type, arch;

        while(seci.hasMoreElements()) {
            sec = seci.peekNextKey();
            Ogre::ConfigFile::SettingsMultiMap* settings = seci.getNext();
            Ogre::ConfigFile::SettingsMultiMap::iterator i;

            for(i = settings->begin(); i != settings->end(); i++) {
                type = i->first;
                arch = i->second;

                LOGI("arch: %s, type: %s, sec: %s", arch.c_str(), type.c_str(), sec.c_str());
                Ogre::ResourceGroupManager::getSingleton().addResourceLocation(arch, type, sec);
            }
        }

        Ogre::ResourceGroupManager::getSingleton().initialiseAllResourceGroups();

        while (1) {

                int ident;
                int events;
                struct android_poll_source* source;

                while ((ident=ALooper_pollAll(0, NULL, &events,
                        (void**)&source)) >= 0) {

                    // Process this event.
                    if (source != NULL)
                        source->process(state, source);

                    if(state->destroyRequested != 0)
                        return;

                 }

                 if(gWnd != NULL && gWnd->isActive()) {
                    gWnd->windowMovedOrResized();
                    gRoot->renderOneFrame();
                 }
        }
    }

    使用了NativeActivity,所以不用写一行Java代码。(NativeActivity Android NKD中有个例子,代码不明白的话可以参考一下)。接着是Android.mk

    LOCAL_PATH := $(call my-dir)
    include $(CLEAR_VARS)

    LOCAL_MODULE := andogre

    LOCAL_SRC_FILES := main.cpp

    LOCAL_LDLIBS := -landroid -lc -lm -ldl -llog -lEGL -lGLESv2
    LOCAL_LDLIBS += -L$(MY_HOME)/android/ogre-v1-9/lib -L$(MY_HOME)/android/AndroidDependencies/lib/armeabi
    LOCAL_LDLIBS += -lPlugin_ParticleFXStatic -lPlugin_OctreeSceneManagerStatic -lRenderSystem_GLES2Static
    LOCAL_LDLIBS += -lOgreRTShaderSystemStatic -lOgreOverlayStatic -lOgreMainStatic
    LOCAL_LDLIBS += -lzzip -lz -lFreeImage -lfreetype -lOIS $(MY_HOME)/android/systemlibs/armeabi/libsupc++.a $(MY_HOME)/android/systemlibs/armeabi/libstdc++.a D:/workspace/AndOgre/obj/local/armeabi/libcpufeatures.a

    LOCAL_STATIC_LIBRARIES := android_native_app_glue cpufeatures

    LOCAL_CFLAGS := -DGL_GLEXT_PROTOTYPES=1 -I$(MY_HOME)/android/ogre-v1-9/include/OGRE
    LOCAL_CFLAGS += -I$(MY_HOME)/android/ogre-v1-9/include/OGRE/Android
    LOCAL_CFLAGS += -I$(MY_HOME)/android/ogre-v1-9/include/OGRE/Overlay
    LOCAL_CFLAGS += -I$(MY_HOME)/android/ogre-v1-9/include/OGRE/Plugins/OctreeSceneManager
    LOCAL_CFLAGS += -I$(MY_HOME)/android/ogre-v1-9/include/OGRE/Plugins/ParticleFX
    LOCAL_CFLAGS += -I$(MY_HOME)/android/ogre-v1-9/include/OGRE/RenderSystems/GLES2
    LOCAL_CFLAGS += -I$(MY_HOME)/android/ogre-v1-9/include/OGRE/RTShaderSystem
    LOCAL_CFLAGS += -ID:/android-ndk-r8d/sources/cpufeatures
    LOCAL_CFLAGS += -I$(MY_HOME)/android/AndroidDependencies/include
    LOCAL_CFLAGS += -I$(MY_HOME)/android/AndroidDependencies/include/OIS
    LOCAL_CFLAGS += -fexceptions -frtti -x c++ -D___ANDROID___ -DANDROID -DZZIP_OMIT_CONFIG_H -DUSE_RTSHADER_SYSTEM=1
    LOCAL_CFLAGS += -DOGRE_STATIC_GLES2 -DOGRE_STATIC_OctreeSceneManager -DOGRE_STATIC_ParticleFX

    include $(BUILD_SHARED_LIBRARY)

    $(call import-module, android/native_app_glue)
    $(call import-module, android/cpufeatures)

    Application.mk文件:

    APP_ABI := armeabi
    APP_STL := gnustl_static

    为了使用NativeActivity,AndroidManifest.xml得改一下,要不然系统不能识别到NativityActivity

    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="cloud.example.andogre"
        android:versionCode="1"
        android:versionName="1.0" >

        <uses-sdk
            android:minSdkVersion="8"
            android:targetSdkVersion="17" />

          <-- 无java代码 -->

          <application android:allowBackup="true" android:label="@string/app_name" android:hasCode="false">

            <-- 这里,告诉系统Activity是NativeActivity -->
            <activity android:name="android.app.NativeActivity"
                    android:label="@string/app_name"
                    android:configChanges="orientation|keyboardHidden"
                    android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen" >
                <!-- Tell NativeActivity the name of or .so -->
                <meta-data android:name="android.app.lib_name"
                        android:value="andogre" />
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
            </activity>
        </application>

    </manifest>

    以上就是全部内容。欢迎指正

     
    2
  • 相关阅读:
    codeforces#1310B. Double Elimination(动态规划)
    codeforces#1300E. Water Balance(贪心)
    带权并查集
    codeforces#1295D. Same GCDs(数论/莫比乌斯)
    jsp实现图片换行显示
    codeforces#1257 F. Make Them Similar ( 经典中间相遇问题 )
    codeforces#1248D2. The World Is Just a Programming Task(括号匹配转化为折线处理)
    codeforces#1251E2. Voting (Hard Version)(贪心)
    codeforces#1249F. Maximum Weight Subset(树上dp)
    hdu6731 Angle Beats(ccpc秦皇岛A,计算几何)
  • 原文地址:https://www.cnblogs.com/moonvan/p/3938580.html
Copyright © 2011-2022 走看看