0.为了与本文情况一致,建议各位看官的工具均升至最新版

Eclipse Kepler+ADT 22.3.0+CDT-master-8.2.1+android-ndk-r9c-windows-x86_64


1.下载Android版Irrlicht的源码。https://gitorious.org/irrlichtandroid/irrlichtandroid/source/f12c3b9743d64dc5cd61931f40e42e8ca64b40ef:


2.将源码导入到Eclipse。怎么导入?蹲墙角反省半小时~~


3.导入完毕,代码结构如下图

为了程序能支持OpenGL ES,Android的版本号要在8以上,这里我选择的是android-16。并且将AndroidManifest.xml中的minSdkVersion改成8


4.右击项目,选择Android Tools→Add Native Support,在弹出的输入框中,输入irrlicht

如果所有插件均是最新版,则会出现Include文件夹。


5.接下来,就是最激动人心的时刻,右击项目,Run As | Android Application。完成!!


6.好吧~,还没结束……,在经过几分钟的编译以后,如果你的NDK是r9版本,就会碰到第一个坑。

这是因为,r9版本以后,方法的接口名变了。只需将

__android_log_print(ANDROID_LOG_INFO, "log", message);改为

__android_log_print(ANDROID_LOG_INFO, "log", “%s”, message);


7.重新编译,在即将完成编译时,半路又杀出来一个程咬金

multiple definition of 'GL_BGRA'。这是因为,同时编译了OpenGL ES1和OpenGL ES2,造成了重复定义。我们首先使用ES1.x渲染。在include\irrCompileConfig.h,注释掉#define _IRR_COMPILE_WITH_OGLES2_,再次重新编译。


8.由于所有的文件都间接包含了irrCompileConfig.h,因此等于是又重新编译了一遍。

恭喜,编译成功。


9.oh on!闪退~~看看logcat吧

请注意这句No OpenGL-ES2 support compiled in.其实,在/jni/android-activity.cpp的nativeInitGL()方法中,我们可以找到答案。

   1: device = createDevice( video::EDT_OGLES2, dimension2d(gWindowWidth, gWindowHeight), 16, false, false, false, 0);

在创建device,用的是OGLES2,如果我们一路跟进去createDevice()→new CIrrDeviceAndroid()→createDriver(),就会发现,由于我们注释了_IRR_COMPILE_WITH_OGLES2_,导致程序irrlicht没有底层图形库去渲染图形,造成程序闪退。现在将createDevice的参数改为video::EDT_OGLES1

  1: device = createDevice( video::EDT_OGLES1, dimension2d(gWindowWidth, gWindowHeight), 16, false, false, false, 0);


10.再次运行,是不是点的想吐了?吐也不行,哥依然闪现给你看~~……。继续logcat吧

又发现线索,Could not load mesh, because file could not be opened: 和cannot getMesh。我们可以在项目中搜索cannot getMesh试试看。在/jni/app-android.cpp的initSydney()方法中,我们发现

   1: smgr = device->getSceneManager();
   2: guienv = device->getGUIEnvironment();
   3:
   4: stringc myDir = gSdCardPath;
   5: myDir += "/Irrlicht";
   6: device->getFileSystem()->changeWorkingDirectoryTo(myDir.c_str());
   7:
   8: stringc sydneyFilename = "/Irrlicht/sydney.md2";
   9: mesh = smgr->getMesh( (gSdCardPath+sydneyFilename).c_str() );
  10:if (!mesh){
  11:     device->drop();
  12:     __android_log_print(ANDROID_LOG_INFO, "Irrlicht", "cannot getMesh");
  13:return;
  14: }

如果你能看懂上面的代码,那差不多,也就知道错出在哪了。程序要从/sdcard/Irrlicht/获去sydney.md2,但手机的SD卡上并没有这个路径。所以,我们可以在SD卡上创建一个Irrlicht目录,并把/IrrlichtSDCard下的文件拷贝到/sdcard/Irrlicht/。


11.如果一切顺利,劳拉将会在红色的背景中原地踏步~~

帅不帅~~


12.总有些人怕麻烦,还得在SD卡创建文件夹,还要复制文件……,DDMS还只能一个一个复制~~麻烦啊~~,还有方法吗?

不怕麻烦的程序员不是好码农!秘密就在Utils.java中,直接看unpackOnSdCard()

   1:if (Environment.getExternalStorageState().compareTo(Environment.MEDIA_MOUNTED)==0) {
   2:     File sdcard = Environment.getExternalStorageDirectory();
   3:     String irrlichtPath = sdcard.getAbsoluteFile() + "/Irrlicht/";
   4:     File irrlichtDir = new File(irrlichtPath);
   5:if (irrlichtDir.exists() && !irrlichtDir.isDirectory()) {
   6:thrownew IOException("Irrlicht exists and is not a directory on SD Card");
   7:     } elseif (!irrlichtDir.exists()) {
   8:         irrlichtDir.mkdirs();
   9:     }
  10:// Note: /sdcard/irrlicht dir exists
  11:     String[] filenames = assetManager.list("data");
  12:for(String filename:filenames) {
  13:         InputStream inputStream = assetManager.open("data/" + filename);
  14:         OutputStream outputStream = new FileOutputStream(irrlichtPath + "/" + filename);
  15:// copy
  16:         byte[] buffer = new byte[4096];
  17:int length;
  18:while ( (length = inputStream.read(buffer)) > 0 ) {
  19:             outputStream.write(buffer, 0, length);
  20:         }
  21:         outputStream.flush();
  22:         outputStream.close();
  23:         inputStream.close();
  24:     }           
  25: } else {
  26:thrownew IOException("SD Card not available");
  27: }

#1—#9 正是在SD卡上创建Irrlicht目录

重点看11行

String[] filenames = assetManager.list("data");

该行代码是获取,/asset/data/下的所有文件名

由此,该函数的功能正是取代我们之前的手动操作,将文件复制到/sdcard/Irrlicht/目录下。

删除之前的SD卡上的Irrlicht目录,在assets目录下新建data目录,将IrrlichtSdcard下的文件复制到data目录下

运行程序~~劳拉依旧飞奔~~

PS:在USB连接手机时,请将USB模式设置成仅充电,即不用通过windows的资源管理器访问到手机的SD卡,否则Environment.getExternalStorageState()将会返回shard。剩下的,你懂得~~

更多相关文章

  1. Android四大组件之activity之间带数据跳转
  2. Android(安卓)Widget开发
  3. Android—将Bitmap图片保存到SD卡目录下或者指定目录
  4. Android之应用中执行Linux命令
  5. 初学Android,数据存储之SD卡文件浏览器(四十四)
  6. android读取raw下面的文件
  7. android 屏幕测试程序 测试R G B三色 和 全黑, 全白5种状态
  8. Linux 统计代码行数
  9. 【android 文件的基本操作】

随机推荐

  1. 如何更改webservice url端点?
  2. Linux下java/bin目录下的命令集合
  3. 派生类具有基类私有成员
  4. java中final关键字详解
  5. java 对称加密——密钥与加密后的数据存
  6. 基于james3.0 的邮件系统(struts2.3.2 +sp
  7. 如何在Java中递归解压缩文件?
  8. 试图改变Jtable java中行的颜色
  9. idea下Kotlin的扁平化集合flatMap
  10. 使加权图在JGraphT中工作