您的位置:首页 > 移动开发

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

2017-07-11 16:20 405 查看
”小擎“可以作为一个第三方库或者独立可执行程序来运行, 目前可以在windows, linux, android 上运行。 app层可以说是应用程序抽象层, 来屏蔽不同平台的接口细节。

一: 首先考虑一个问题:  一个应用程序如何做到跨平台?

1: C/C++ 标准库是跨平台的, 所以稍加注意的话用C/C++写的应用程序是跨平台的。

2: OpenGL 是跨平台的。

3: OpenGL所依赖的窗口不是跨平台的,   我们知道在Windows上 有WGL, Linux上 有GLX,  Android 上有 EGL, 这些组件能够在本地窗口的基础上创建一个OpenGL渲染上下文, 支持OpenGL能在不同平台的窗口上显示。  我们还知道有个叫GLFW的开源库, 它封装了WGL, GLX, EGL。 使用它能够创建一个跨Windows, Linux运行的窗口。

4: 线程 不是跨平台的, C++11支持线程,但由于不用C++11, 所以必须有个小型跨平台的线程库, 这个似乎也很容易做到。

5: GLFW, GLEW, GLM , Assimp 是跨平台的, 但官方不支持Android,  也就是说这些库即使经过NDK编译, 也有可能无法在Android使用, 我觉得这个应该也有解决方法。

所以我们得设计两种Application, 一种是桌面的(Windows 和 Linux), 一种是Andorid的, 再由这两个抽象出一个Application, 来做到跨平台功能。

Application

ApplicationDesktop

ApplicationAndroid

二: 其次考虑一个问题: 应用程序怎样在Android上运行。 

我们知道开发一个在Android上运行的程序有三种方式, 一种是纯java开发,  一种是java + jni开发,  一种是纯jni开发, 我们就以最后一种形式, 在Android上运行一个对的应用程序, 是以纯C++开发的, 它的思路是: 应用程序入口是android_main,   然后以EGL创建OpenGL渲染上下文, 然后渲染引用程序。 这种实现可以参考android-ndk-r9d/samples/native-activity。

三: 最后, app层是这样设计的:

Application:

#ifndef _APPLICATION_H_
#define _APPLICATION_H_

#include <stdio.h>
#include <string.h>
#include <math.h>

#include <string>
#include <iostream>

#if defined(WIN32)
#include <Windows.h>
#elif defined(ANDROID)
#include <android_native_app_glue.h>
#else
#include <unistd.h>
#endif

class Application
{
public:
Application();
void run(Application* instance);
virtual ~Application();
protected:
virtual bool init() = 0;
virtual void loop() = 0;
virtual void uninit() = 0;
protected:
static Application *mInstance;
protected:
bool mRunning;
bool mDebugMode;
};

#if defined( __WIN32__ ) || defined( _WIN32 )
#define DECLARE_MAIN(a)                       \
int main(int argc, char **argv)               \
{                                             \
a *app = new a(argc, argv)                \
app->run(app);                            \
delete app;                               \
return 0;                                 \
}
#elif defined( ANDROID )
#define DECLARE_MAIN(a)                        \
void android_main(struct android_app* state)   \
{                                              \
app_dummy();                               \
a *app = new a(state);                     \
app->run(app);                             \
delete app;                                \
}
#else //Probably Linux
#define DECLARE_MAIN(a)                        \
int main(int argc, const char ** argv)         \
{                                              \
a *app = new a(argc, argv);                \
app->run(app);                             \
delete app;                                \
return 0;                                  \
}
#endif

#endif


ApplicationDesktop:

#ifndef _APPLICATION_DESKTOP_H_
#define _APPLICATION_DESKTOP_H_

#include <string>

#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>

#include "Application.h"

class ApplicationDesktop: public Application
{
public:
ApplicationDesktop(int argc, const char ** argv);
virtual ~ApplicationDesktop();
protected:
virtual bool initDisplay();
virtual bool initRenderer();
virtual bool initScene();
virtual void drawFrame();
virtual void uninitScene();
virtual void uninitRenderer();
virtual void uninitDisplay();
private:
bool init();
void loop();
void uninit();
private:
bool parseArgs();
void printHelpInfo(const char * exeFile);
public:
virtual void onKey(int key);
virtual void onResize(int w, int h);
virtual void onMouseMove(int x, int y);
virtual void onMouseWheel(double yoffset);
virtual void onMouseButton(int button, int action);
virtual void onMousePosition(int& x, int& y);
private:
static void glfw_onKey(GLFWwindow* window, int key, int scancode, int action, int mods);
static void glfw_onResize(GLFWwindow* window, int w, int h);
static void glfw_onMouseMove(GLFWwindow* window, double x, double y);
static void glfw_onMouseWheel(GLFWwindow* window, double xoffset, double yoffset);
static void glfw_onMouseButton(GLFWwindow* window, int button, int action, int mods);
protected:
int mArgc;
const char **mArgv;

std::string mWinTitle;
int mWinWidth;
int mWinHeight;

int mMajorVersion;
int mMinorVersion;
bool mDebugMode;
bool mFullScreen;
bool mRunning;
float mDeltaTime;
float mLastTime;
glm::ivec2 mCurPos;
GLFWwindow* mCurWindow;
};

#endif


ApplicationAndroid:

#ifndef _APPLICATION_DESKTOP_H_
#define _APPLICATION_DESKTOP_H_

#include <string>

#include <jni.h>
#include <errno.h>

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

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

#define APPLICATION_NAME "ApplicationAndroid"

#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, APPLICATION_NAME, __VA_ARGS__))
#define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN, APPLICATION_NAME, __VA_ARGS__))
#define LOGD(...) ((void)__android_log_print(ANDROID_LOG_DEBUG, APPLICATION_NAME, __VA_ARGS__))
#define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, APPLICATION_NAME, __VA_ARGS__))

#include "Application.h"

class ApplicationAndroid: public Application
{
public:
struct saved_state
{
float angle;
int32_t x;
int32_t y;
};
public:
ApplicationAndroid(struct android_app *app);
virtual ~ApplicationAndroid();
protected:
virtual bool initArgs();
virtual bool initDisplay();
virtual bool initRenderer();
virtual bool initScene();
virtual void drawFrame();
virtual void uninitScene();
virtual void uninitRenderer();
virtual void uninitDisplay();
private:
bool init();
void loop();
void uninit();
private:
static void handleCmd(struct android_app* app, int32_t cmd);
static int32_t handleInput(struct android_app* app, AInputEvent* event);
protected:
int mMajorVersion;
int mMinorVersion;

int mWinWidth;
int mWinHeight;
bool mFullScreen;
std::string mWinTitle;

struct android_app *mApp;
struct saved_state mState;

EGLDisplay mDisplay;
EGLSurface mSurface;
EGLContext mContext;

ASensorManager *mSensorManager;
const ASensor *mAccelerometerSensor;
ASensorEventQueue *mSensorEventQueue;
};

#endif
运行结果如图:





imgui 学习网址: http://sol.gfxile.net/imgui/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: