小型三维引擎设计实现-app层如何跨平台2

来源:互联网 发布:在线网络理财投资服务 编辑:程序博客网 时间:2024/05/17 02:47

在Android平台下,  有这样两个问题需要解决, 它们和桌面平台有些不一样:

        1: 在Android上如何读写文件? 三维程序需要载入模型, 纹理, 着色器脚本等数据, 如何读写这些文件?

        2: 如何把第三方库移植到Android平台上,  可以使用CMake?  还是为其编写Android.mk

一:  首先看看如何读写文件的问题:

从数据存放位置来分, 读写文件可以分为两类, 第一类读取assets文件夹内的文件, 第二类是读取sd卡内的文件。   相比较而言, 读取sd卡内的文件要容易一些(可以看成是读取某磁盘目录下的文件), 直接用标准库中的IO函数即可读取。 但是读取assets下的文件就要用到专门的函数了。

    读取asset下文件的方法:

   (1) :需要头文件: #include <android_native_app_glue.h>

   (2): AAssetManager* assetManager = this->mActivity->assetManager;  //获取assetManager

   (3):  AAssetManager_open(...) // 打开文件

   (4):AAsset_getBuffer(...) //获取文件内容

    (5): AAsset_getLength(...) //获取文件长度


下面看下代码:

#pragma once #include <jni.h>#include <vector>#include <string>#include <android_native_app_glue.h>#include "AndroidLog.h"class AndroidIO{public:AndroidIO(ANativeActivity* activity);bool readText(const char* filename, std::vector<unsigned char>* buffer);~AndroidIO();private:ANativeActivity* mActivity;mutable pthread_mutex_t mMutex;};

#include "AndroidIO.h"#include <fstream>#include <iostream>AndroidIO::AndroidIO(ANativeActivity* activity){pthread_mutex_init(&mMutex, NULL);    pthread_mutex_lock(&mMutex);    this->mActivity = activity;    pthread_mutex_unlock(&mMutex);}bool AndroidIO::readText(const char* filename, std::vector<unsigned char> *buffer){    pthread_mutex_lock(&mMutex);         std::ifstream f(filename, std::ios::binary );    if(f)    {        LOGI( "reading sdcard:%s", filename );          f.seekg( 0, std::ifstream::end );        int32_t fileSize = f.tellg();        f.seekg( 0, std::ifstream::beg );        buffer->reserve( fileSize );        buffer->assign( std::istreambuf_iterator<char>( f ), std::istreambuf_iterator<char>() );        f.close();        pthread_mutex_unlock( &mMutex );        return true;    }    else    {        LOGI( "reading assest:%s", filename );          AAssetManager* assetManager = this->mActivity->assetManager;        AAsset* assetFile = AAssetManager_open( assetManager, filename, AASSET_MODE_BUFFER );        if( !assetFile )        {            pthread_mutex_unlock( &mMutex );            return false;        }        uint8_t* data = (uint8_t*) AAsset_getBuffer( assetFile );        int32_t size = AAsset_getLength( assetFile );        if( data == NULL )        {            AAsset_close( assetFile );            LOGI( "Failed to load:%s", filename );            pthread_mutex_unlock( &mMutex );            return false;        }        buffer->reserve( size );        buffer->assign( data, data + size );        AAsset_close( assetFile );        pthread_mutex_unlock( &mMutex );        return true;    }}AndroidIO::~AndroidIO(){    pthread_mutex_destroy(&mMutex);}

为了验证读取文件功能, 我把shader文件分别放到assets文件夹下, 和sd卡上, 下面是运行结果:



二: 下面看看C++库如何移植到Android的问题:

       这又分为两个小问题, 一是如何把第三方库编译成Android可用的动态库?   二是如何调用这些动态库?

      1: 如何把第三方库编译成Android可用的动态库:

           一般的第三方库都有CMakeLists文件, 比如Assimp, SDL 等,  这就比较好办了, 我们可以使用CMake的方式, 把开源代码编译成Android下可用的动态库, 仅仅需要在运行CMake时加上几个选项, 具体方法, 请参考这个: https://github.com/taka-no-me/android-cmake。

           

#!/bin/sh# Path to Android NDKexport ANDROID_NDK=/you_path/android-ndk# Points to the Android SDKexport ANDROID_SDK=/you_path/sdkexport PATH=$PATH:$ANDROID_SDK/toolsexport PATH=$PATH:$ANDROID_SDK/platform-toolsexport PATH=$PATH:$ANDROID_SDK/android-toolchain/bin# from https://github.com/taka-no-me/android-cmakeexport ANDROID_STANDALONE_TOOLCHAIN=/you_path/android-cmake/android.toolchain.cmakeecho $ANDROID_STANDALONE_TOOLCHAIN# Add additional args here as appropriatecd build     cmake -DCMAKE_TOOLCHAIN_FILE=$ANDROID_STANDALONE_TOOLCHAIN \          -DANDROID_NDK=$ANDROID_NDK                       \          -DCMAKE_BUILD_TYPE=Release                     \          -DANDROID_ABI="armeabi-v7a "          \          you_src_path/    cmake --build .cd ..

       2: 编译好Android上可用的动态库之后, 下一步就是要解决如何调用的问题了:

           调用第三方动态库, 需要配置Android.mk,  以及 Application.mk,   以便程序能找到动态库和头文件, 先看一下目录结构:

          

        

            图中的 include , lib 分别存放第三方库的头文件和.so 文件。

           下面看看Android.mk 中如何调用so, 以及Application.mk 中一个需要注意的地方。

            Android.mk

           

LOCAL_PATH := $(call my-dir)include $(CLEAR_VARS)LOCAL_MODULE := fooLOCAL_SRC_FILES := lib/libfoo.soinclude $(PREBUILT_SHARED_LIBRARY)include $(CLEAR_VARS)LOCAL_MODULE    := hello-jniLOCAL_SRC_FILES := hello-jni.cLOCAL_SHARED_LIBRARIES := fooLOCAL_EXPORT_C_INCLUDES := includeinclude $(BUILD_SHARED_LIBRARY)

Application.mk

#APP_ABI := allAPP_ABI := armeabi-v7a armeabi
因为编译so属于交叉编译,  比如我们编译出来的so 是arm 指令的, 就不能再x86平台下面用,   所以注意这里的APP_ABI 的配置, 确保要和第一步的 -DANDROID_ABI 一样, 否则会出现.so格式不不正确的错误。 

         


     



阅读全文
0 0
原创粉丝点击