第一步 ,配置所需Android环境:
1. adt 本文采用adt-bundle-windows-x86-20130522 打开链接
2. ndk 本文采用r8d ndk
3、OgreSDK_Android_v1-9-0RC1 可以官网下载,也可以在云盘下载 链接:http://pan.baidu.com/s/1kT91uHh 密码:t6ar
4、java所需环境 jdk ,用1.7版本的就可以。并配置环境变量(不知道不用行不行)
第二步 ,采用android_native_app_glue 方式,编写纯c++的Android程序。
视频教程:点击打开链接
文本教程:点击打开链接
第三步,解压OgreSDK_Android_v1-9-0RC1,将Ogre Android SDK\Samples\GLES1\bin目录中的apk安装到Android装备上,运行一下看看效果。是个红色背景的恶魔。你可以修改工程中的背景色看看,不会成功的,因为没法生存so。所以,第四步。
第四步,将ogre的移植上来。需要做的修改
1、将ogresdk压缩包解压后将目录下的Ogre 和Dependencies文件夹放置到 第二步中的工程文件夹同级目录中。
2、修改mk文件。Android.mk文件,修改为
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := NDKTest ----你自己的工程名
LOCAL_LDLIBS := -landroid -lc -lm -ldl -llog -lEGL -lGLESv1_CM
LOCAL_LDLIBS += -L$(LOCAL_PATH)/../../Ogre/lib/armeabi-v7a -L$(LOCAL_PATH)/../../Dependencies/lib/armeabi-v7a
LOCAL_LDLIBS += -lPlugin_ParticleFXStatic -lPlugin_OctreeSceneManagerStatic -lRenderSystem_GLESStatic -lOgreOverlayStatic -lOgreMainStatic
LOCAL_LDLIBS += -lzzip -lz -lFreeImage -lfreetype -lOIS $(LOCAL_PATH)/../../Dependencies/lib/armeabi-v7a/libsupc++.a $(LOCAL_PATH)/../../Dependencies/lib/armeabi-v7a/libstdc++.a ./obj/local/armeabi-v7a/libcpufeatures.a
LOCAL_STATIC_LIBRARIES := android_native_app_glue cpufeatures
LOCAL_CFLAGS := -DGL_GLEXT_PROTOTYPES=1 -I$(LOCAL_PATH)/../../Ogre/include/Build -I$(LOCAL_PATH)/../../Ogre/include/OgreMain -I$(LOCAL_PATH)/../../Ogre/include/RenderSystems/GLES
LOCAL_CFLAGS += -I$(LOCAL_PATH)/../../Ogre/include/RenderSystems/GLES/EGL -I$(ANDROID_NDK)/sources/cpufeatures -I$(LOCAL_PATH)/../../Ogre/include/Components/Overlay
LOCAL_CFLAGS += -I$(LOCAL_PATH)/../../Ogre/include/PlugIns/ParticleFX -I$(LOCAL_PATH)/../../Ogre/include/PlugIns/OctreeSceneManager
LOCAL_CFLAGS += -I$(LOCAL_PATH)/../../Dependencies/include -I$(LOCAL_PATH)/../../Dependencies/include/OIS
LOCAL_CFLAGS += -fexceptions -frtti -x c++ -D___ANDROID___ -DANDROID -DZZIP_OMIT_CONFIG_H
LOCAL_PATH := ./jni
LOCAL_SRC_FILES := NDKTest.cpp
include $(BUILD_SHARED_LIBRARY)
$(call import-module,android/cpufeatures)
$(call import-module,android/native_app_glue)
Application.mk文件修改为(因为x86的有些平板不行)
APP_ABI := armeabi-v7a
APP_STL := gnustl_static
3、修改自己的cpp文件
#include <jni.h>
#include <android/native_window.h>
#include <android_native_app_glue.h>
#include <android/log.h>
#include <stdio.h>
#define OGRE_STATIC_GLES
#define OGRE_STATIC_ParticleFX
#define OGRE_STATIC_OctreeSceneManager
#include "OgreStaticPluginLoader.h"
#include "Ogre.h"
#include "OgreRenderWindow.h"
#include "OgreStringConverter.h"
#include "Android/OgreAndroidEGLWindow.h"
#include "Android/OgreAPKFileSystemArchive.h"
#include "Android/OgreAPKZipArchive.h"
#include <EGL/egl.h>
#include <android/log.h>
#include <android_native_app_glue.h>
//#include "MCameraMan.h"
static Ogre::RenderWindow* gRenderWnd = NULL;
static Ogre::Root* gRoot = NULL;
static Ogre::StaticPluginLoader* gStaticPluginLoader = NULL;
static AAssetManager* gAssetMgr = NULL;
static Ogre::SceneManager* gSceneMgr = NULL;
static Ogre::Camera* gCamera=NULL;
static Ogre::SceneNode* gNode=NULL;
//static MCameraMan* gCamMan=NULL;
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 setupScene()
{
Ogre::ConfigFile cf;
cf.load(openAPKFile("resources.cfg"));
Ogre::ConfigFile::SectionIterator seci = cf.getSectionIterator();
while (seci.hasMoreElements())
{
Ogre::String sec, type, arch;
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;
Ogre::ResourceGroupManager::getSingleton().addResourceLocation(arch, type, sec);
}
}
Ogre::ResourceGroupManager::getSingletonPtr()->initialiseResourceGroup(Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
gSceneMgr = gRoot->createSceneManager(Ogre::ST_GENERIC);
Ogre::Camera* camera = gSceneMgr->createCamera("MyCam");
gCamera=camera;
//gCamMan=new MCameraMan(camera);
Ogre::Entity* pEntity = gSceneMgr->createEntity("SinbadInstance", "Sinbad.mesh");
Ogre::SceneNode* pNode = gSceneMgr->getRootSceneNode()->createChildSceneNode();
pNode->attachObject(pEntity);
gNode=pNode;
Ogre::Light* pDirLight = gSceneMgr->createLight();
pDirLight->setDirection(Ogre::Vector3(0,-1,0));
pDirLight->setType(Ogre::Light::LT_DIRECTIONAL);
pNode->attachObject(pDirLight);
camera->setNearClipDistance(1.0f);
camera->setFarClipDistance(100000.0f);
camera->setPosition(0,0,20.0f);
camera->lookAt(0,0,0);
camera->setAutoAspectRatio(true);
Ogre::Viewport* vp = gRenderWnd->addViewport(camera);
vp->setBackgroundColour(Ogre::ColourValue(0,0,0));
}
static int32_t handleInput(struct android_app* app, AInputEvent* event)
{
if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_MOTION) {
int nNum = AMotionEvent_getPointerCount(event);
char szTrace[1024] = {0};
sprintf (szTrace, "engine_handle_input num=[%d]", nNum);
int xpos=0;
int ypos=0;
for (int nIdx = 0; nIdx < nNum; nIdx++)
{
int nX = AMotionEvent_getX(event, 0);
int nY = AMotionEvent_getY(event, 0);
xpos=nX;
ypos=nY;
sprintf (strrchr(szTrace, 0), " (%d %d)", nX, nY);
}
__android_log_print(ANDROID_LOG_DEBUG, "ndktest",
"%s", szTrace);
static int x_zdel=xpos;
static int y_zdel=ypos;
sprintf(szTrace,"") ;
if( AMotionEvent_getAction(event)== AMOTION_EVENT_ACTION_MOVE)
{
x_zdel=xpos-x_zdel;
y_zdel=ypos-y_zdel;
//gCamera->lookAt(x_zdel,y_zdel,0);
<span style="white-space:pre"> </span>//移动node
gNode->translate(x_zdel/10,y_zdel/10,0);
//gCamMan->getCamera()->yaw(Ogre::Degree(x_zdel*0.1));
//gCamMan->getCamera()->pitch(Ogre::Degree(y_zdel*0.1));
sprintf (szTrace, " move =(%d %d)", x_zdel,y_zdel);
__android_log_print(ANDROID_LOG_DEBUG, "ndktest",
"%s", szTrace);
x_zdel=xpos;
y_zdel=ypos;
}
else if(AMotionEvent_getAction(event)== AMOTION_EVENT_ACTION_DOWN)
{
x_zdel=xpos;
y_zdel=ypos;
}
else if(AMotionEvent_getAction(event)== AMOTION_EVENT_ACTION_UP)
{
}
sprintf (szTrace, " xypos=(%d %d)", x_zdel,y_zdel);
__android_log_print(ANDROID_LOG_DEBUG, "ndktest",
"%s", szTrace);
if (AKeyEvent_getAction(event) != AKEY_EVENT_ACTION_UP)
{
sprintf(szTrace,"key up") ;
__android_log_print(ANDROID_LOG_DEBUG, "ndktest",
"%s", szTrace);
return 1;
}
return 1;
}
return 0;
}
static void handleCmd(struct android_app* app, int32_t cmd)
{
switch (cmd)
{
case APP_CMD_SAVE_STATE:
break;
case APP_CMD_INIT_WINDOW:
if(app->window && gRoot)
{
AConfiguration* config = AConfiguration_new();
AConfiguration_fromAssetManager(config, app->activity->assetManager);
gAssetMgr = app->activity->assetManager;
if(!gRenderWnd)
{
Ogre::ArchiveManager::getSingleton().addArchiveFactory( new Ogre::APKFileSystemArchiveFactory(app->activity->assetManager) );
Ogre::ArchiveManager::getSingleton().addArchiveFactory( new Ogre::APKZipArchiveFactory(app->activity->assetManager) );
Ogre::NameValuePairList opt;
opt["externalWindowHandle"] = Ogre::StringConverter::toString((int)app->window);
opt["androidConfig"] = Ogre::StringConverter::toString((int)config);
gRenderWnd = gRoot->createRenderWindow("OgreWindow", 0, 0, false, &opt);
setupScene();
}
else
{
static_cast<Ogre::AndroidEGLWindow*>(gRenderWnd)->_createInternalResources(app->window, config);
}
AConfiguration_delete(config);
}
break;
case APP_CMD_TERM_WINDOW:
if(gRoot && gRenderWnd)
static_cast<Ogre::AndroidEGLWindow*>(gRenderWnd)->_destroyInternalResources();
break;
case APP_CMD_GAINED_FOCUS:
break;
case APP_CMD_LOST_FOCUS:
break;
}
}
void android_main(struct android_app* state)
{
app_dummy();
if(gRoot == NULL)
{
gRoot = new Ogre::Root();
#ifdef OGRE_STATIC_LIB
gStaticPluginLoader = new Ogre::StaticPluginLoader();
gStaticPluginLoader->load();
#endif
gRoot->setRenderSystem(gRoot->getAvailableRenderers().at(0));
gRoot->initialise(false);
}
state->onAppCmd = &handleCmd;
state->onInputEvent = &handleInput;
int ident, events;
struct android_poll_source* source;
while (true)
{
while ((ident = ALooper_pollAll(0, NULL, &events, (void**)&source)) >= 0)
{
if (source != NULL)
source->process(state, source);
if (state->destroyRequested != 0)
return;
}
if(gRenderWnd != NULL && gRenderWnd->isActive())
{
gRenderWnd->windowMovedOrResized();
gRoot->renderOneFrame();
}
}
}
最后运行,成功。