Merging r5975 through r6036 from trunk to ogl-es branch.

GLES drivers adapted, but only did make compile-tests.


git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/branches/ogl-es@6038 dfc29bdd-3216-0410-991c-e03cc46cb475
This commit is contained in:
cutealien
2020-01-03 19:05:16 +00:00
commit 2ae2a551a6
2007 changed files with 635880 additions and 0 deletions

View File

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.irrlicht.example"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="10"/>
<uses-feature android:glEsVersion="0x00020000" android:required="true"/>
<application android:icon="@drawable/irr_icon" android:label="HelloWorldMobile" android:theme="@android:style/Theme.NoTitleBar.Fullscreen" android:debuggable="true">
<activity android:name="android.app.NativeActivity"
android:label="HelloWorldMobile"
android:launchMode="singleTask"
android:configChanges="orientation|keyboardHidden"
android:clearTaskOnLaunch="true">
<meta-data android:name="android.app.lib_name" android:value="HelloWorldMobile" />
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>

View File

@ -0,0 +1,184 @@
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
#include "android_tools.h"
#include <android/log.h> // for the occasional debugging, style: __android_log_print(ANDROID_LOG_VERBOSE, "Irrlicht", "%s\n", "We do log");
namespace irr
{
namespace android
{
// Not all DisplayMetrics are available through the NDK.
// So we access the Java classes with the JNI interface.
// You can access other Java classes available in Android in similar ways.
// Function based roughly on the code from here: http://stackoverflow.com/questions/13249164/android-using-jni-from-nativeactivity
bool getDisplayMetrics(android_app* app, SDisplayMetrics & metrics)
{
if (!app || !app->activity || !app->activity->vm )
return false;
JNIEnv* jni = 0;
app->activity->vm->AttachCurrentThread(&jni, NULL);
if (!jni )
return false;
// get all the classes we want to access from the JVM
jclass classNativeActivity = jni->FindClass("android/app/NativeActivity");
jclass classWindowManager = jni->FindClass("android/view/WindowManager");
jclass classDisplay = jni->FindClass("android/view/Display");
jclass classDisplayMetrics = jni->FindClass("android/util/DisplayMetrics");
if (!classNativeActivity || !classWindowManager || !classDisplay || !classDisplayMetrics)
{
app->activity->vm->DetachCurrentThread();
return false;
}
// Get all the methods we want to access from the JVM classes
// Note: You can get the signatures (third parameter of GetMethodID) for all
// functions of a class with the javap tool, like in the following example for class DisplayMetrics:
// javap -s -classpath myandroidpath/adt-bundle-linux-x86_64-20131030/sdk/platforms/android-10/android.jar android/util/DisplayMetrics
jmethodID idNativeActivity_getWindowManager = jni->GetMethodID( classNativeActivity
, "getWindowManager"
, "()Landroid/view/WindowManager;");
jmethodID idWindowManager_getDefaultDisplay = jni->GetMethodID( classWindowManager
, "getDefaultDisplay"
, "()Landroid/view/Display;");
jmethodID idDisplayMetrics_constructor = jni->GetMethodID( classDisplayMetrics
, "<init>"
, "()V");
jmethodID idDisplay_getMetrics = jni->GetMethodID( classDisplay
, "getMetrics"
, "(Landroid/util/DisplayMetrics;)V");
if (!idNativeActivity_getWindowManager || !idWindowManager_getDefaultDisplay || !idDisplayMetrics_constructor
|| !idDisplay_getMetrics)
{
app->activity->vm->DetachCurrentThread();
return false;
}
// In Java the following code would be: getWindowManager().getDefaultDisplay().getMetrics(metrics);
// Note: If you need to call java functions in time-critical places you can split getting the jmethodID's
// and calling the functions into separate functions as you only have to get the jmethodID's once.
jobject windowManager = jni->CallObjectMethod(app->activity->clazz, idNativeActivity_getWindowManager);
if (!windowManager)
{
app->activity->vm->DetachCurrentThread();
return false;
}
jobject display = jni->CallObjectMethod(windowManager, idWindowManager_getDefaultDisplay);
if (!display)
{
app->activity->vm->DetachCurrentThread();
return false;
}
jobject displayMetrics = jni->NewObject( classDisplayMetrics, idDisplayMetrics_constructor);
if (!displayMetrics)
{
app->activity->vm->DetachCurrentThread();
return false;
}
jni->CallVoidMethod(display, idDisplay_getMetrics, displayMetrics);
// access the fields of DisplayMetrics (we ignore the DENSITY constants)
jfieldID idDisplayMetrics_widthPixels = jni->GetFieldID( classDisplayMetrics, "widthPixels", "I");
jfieldID idDisplayMetrics_heightPixels = jni->GetFieldID( classDisplayMetrics, "heightPixels", "I");
jfieldID idDisplayMetrics_density = jni->GetFieldID( classDisplayMetrics, "density", "F");
jfieldID idDisplayMetrics_densityDpi = jni->GetFieldID( classDisplayMetrics, "densityDpi", "I");
jfieldID idDisplayMetrics_scaledDensity = jni->GetFieldID( classDisplayMetrics, "scaledDensity", "F");
jfieldID idDisplayMetrics_xdpi = jni->GetFieldID(classDisplayMetrics, "xdpi", "F");
jfieldID idDisplayMetrics_ydpi = jni->GetFieldID(classDisplayMetrics, "ydpi", "F");
if ( idDisplayMetrics_widthPixels )
metrics.widthPixels = jni->GetIntField(displayMetrics, idDisplayMetrics_widthPixels);
if ( idDisplayMetrics_heightPixels )
metrics.heightPixels = jni->GetIntField(displayMetrics, idDisplayMetrics_heightPixels);
if (idDisplayMetrics_density )
metrics.density = jni->GetFloatField(displayMetrics, idDisplayMetrics_density);
if (idDisplayMetrics_densityDpi)
metrics.densityDpi = jni->GetIntField(displayMetrics, idDisplayMetrics_densityDpi);
if (idDisplayMetrics_scaledDensity)
metrics.scaledDensity = jni->GetFloatField(displayMetrics, idDisplayMetrics_scaledDensity);
if ( idDisplayMetrics_xdpi )
metrics.xdpi = jni->GetFloatField(displayMetrics, idDisplayMetrics_xdpi);
if ( idDisplayMetrics_ydpi )
metrics.ydpi = jni->GetFloatField(displayMetrics, idDisplayMetrics_ydpi);
app->activity->vm->DetachCurrentThread();
return true;
}
void setSoftInputVisibility(android_app* app, bool visible)
{
// NOTE: Unfortunately ANativeActivity_showSoftInput from the NDK does not work and Google does not care.
// This is based on the solution from @Ratamovic from here: http://stackoverflow.com/questions/5864790/how-to-show-the-soft-keyboard-on-native-activity
if (!app || !app->activity || !app->activity->vm )
return;
JNIEnv* jni = 0;
app->activity->vm->AttachCurrentThread(&jni, NULL);
if (!jni )
return;
// get all the classes we want to access from the JVM (could be cached)
jclass classNativeActivity = jni->FindClass("android/app/NativeActivity");
jclass classInputMethodManager = jni->FindClass("android/view/inputmethod/InputMethodManager");
jclass classWindow = jni->FindClass("android/view/Window");
jclass classView = jni->FindClass("android/view/View");
if (classNativeActivity && classInputMethodManager && classWindow)
{
// Get all the methods we want to access from the JVM classes (could be cached)
jmethodID mid_getSystemService = jni->GetMethodID(classNativeActivity, "getSystemService","(Ljava/lang/String;)Ljava/lang/Object;");
jmethodID mid_showSoftInput = jni->GetMethodID(classInputMethodManager, "showSoftInput", "(Landroid/view/View;I)Z");
jmethodID mid_hideSoftInput = jni->GetMethodID(classInputMethodManager, "hideSoftInputFromWindow", "(Landroid/os/IBinder;I)Z");
jmethodID mid_getWindow = jni->GetMethodID(classNativeActivity, "getWindow", "()Landroid/view/Window;");
jmethodID mid_getWindowToken = jni->GetMethodID(classView, "getWindowToken", "()Landroid/os/IBinder;");
jmethodID mid_getDecorView = jni->GetMethodID(classWindow, "getDecorView", "()Landroid/view/View;");
if ( mid_getSystemService && mid_showSoftInput && mid_hideSoftInput && mid_getWindow && mid_getDecorView && mid_getWindowToken )
{
jstring paramInput = jni->NewStringUTF("input_method");
jobject objInputMethodManager = jni->CallObjectMethod(app->activity->clazz, mid_getSystemService, paramInput);
jni->DeleteLocalRef(paramInput);
jobject objWindow = jni->CallObjectMethod(app->activity->clazz, mid_getWindow);
if ( visible && objInputMethodManager && objWindow)
{
jobject objDecorView = jni->CallObjectMethod(objWindow, mid_getDecorView);
if ( objDecorView )
{
int showFlags = 0;
jni->CallBooleanMethod(objInputMethodManager, mid_showSoftInput, objDecorView, showFlags);
}
}
else if ( !visible && objInputMethodManager && objWindow )
{
jobject objDecorView = jni->CallObjectMethod(objWindow, mid_getDecorView);
if ( objDecorView )
{
jobject objBinder = jni->CallObjectMethod(objDecorView, mid_getWindowToken);
if ( objBinder )
{
int hideFlags = 0;
jni->CallBooleanMethod(objInputMethodManager, mid_hideSoftInput, objBinder, hideFlags);
}
}
}
}
}
app->activity->vm->DetachCurrentThread();
}
} // namespace android
} // namespace irr

View File

@ -0,0 +1,33 @@
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
#ifndef __IRR_ANDROID_TOOLS_H__
#define __IRR_ANDROID_TOOLS_H__
#include <irrlicht.h>
#include <android_native_app_glue.h>
namespace irr
{
namespace android
{
struct SDisplayMetrics
{
irr::s32 widthPixels;
irr::s32 heightPixels;
irr::f32 density;
irr::s32 densityDpi;
irr::f32 scaledDensity;
irr::f32 xdpi;
irr::f32 ydpi;
};
//! Access SDisplayMetrics
extern bool getDisplayMetrics(android_app* app, SDisplayMetrics & metrics);
extern void setSoftInputVisibility(android_app* app, bool visible);
}
}
#endif // __IRR_ANDROID_TOOLS_H__

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<project name="HelloWorldMobile" default="help">
<property file="local.properties" />
<property file="ant.properties" />
<property environment="env" />
<condition property="sdk.dir" value="${env.ANDROID_HOME}">
<isset property="env.ANDROID_HOME" />
</condition>
<loadproperties srcFile="project.properties" />
<fail
message="sdk.dir is missing. Make sure to generate local.properties using 'android update project' or to inject it through the ANDROID_HOME environment variable."
unless="sdk.dir"
/>
<import file="custom_rules.xml" optional="true" />
<import file="${sdk.dir}/tools/ant/build.xml" />
</project>

View File

@ -0,0 +1,50 @@
LOCAL_PATH := $(call my-dir)/..
IRRLICHT_PROJECT_PATH := $(LOCAL_PATH)
include $(CLEAR_VARS)
LOCAL_MODULE := Irrlicht
LOCAL_SRC_FILES := $(IRRLICHT_PROJECT_PATH)/../../lib/Android/libIrrlicht.a
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := HelloWorldMobile
LOCAL_CFLAGS := -pipe -fno-exceptions -fno-rtti -fstrict-aliasing
ifndef NDEBUG
LOCAL_CFLAGS += -g -D_DEBUG
else
LOCAL_CFLAGS += -fexpensive-optimizations -O3
endif
ifeq ($(TARGET_ARCH_ABI),x86)
LOCAL_CFLAGS += -fno-stack-protector
endif
LOCAL_C_INCLUDES := ../../include
LOCAL_SRC_FILES := main.cpp android_tools.cpp
LOCAL_LDLIBS := -lEGL -llog -lGLESv1_CM -lGLESv2 -lz -landroid
LOCAL_STATIC_LIBRARIES := Irrlicht android_native_app_glue
include $(BUILD_SHARED_LIBRARY)
$(call import-module,android/native_app_glue)
# copy Irrlicht data to assets
$(shell mkdir -p $(IRRLICHT_PROJECT_PATH)/assets)
$(shell mkdir -p $(IRRLICHT_PROJECT_PATH)/assets/media)
$(shell mkdir -p $(IRRLICHT_PROJECT_PATH)/assets/media/Shaders)
$(shell mkdir -p $(IRRLICHT_PROJECT_PATH)/src)
$(shell cp $(IRRLICHT_PROJECT_PATH)/../../media/Shaders/*.* $(IRRLICHT_PROJECT_PATH)/assets/media/Shaders/)
$(shell cp $(IRRLICHT_PROJECT_PATH)/../../media/irrlichtlogo3.png $(IRRLICHT_PROJECT_PATH)/assets/media/)
$(shell cp $(IRRLICHT_PROJECT_PATH)/../../media/dwarf.x $(IRRLICHT_PROJECT_PATH)/assets/media/)
$(shell cp $(IRRLICHT_PROJECT_PATH)/../../media/dwarf.jpg $(IRRLICHT_PROJECT_PATH)/assets/media/)
$(shell cp $(IRRLICHT_PROJECT_PATH)/../../media/axe.jpg $(IRRLICHT_PROJECT_PATH)/assets/media/)
$(shell cp $(IRRLICHT_PROJECT_PATH)/../../media/fonthaettenschweiler.bmp $(IRRLICHT_PROJECT_PATH)/assets/media/)
$(shell cp $(IRRLICHT_PROJECT_PATH)/../../media/bigfont.png $(IRRLICHT_PROJECT_PATH)/assets/media/)

View File

@ -0,0 +1,2 @@
APP_PLATFORM := android-10
APP_MODULES := HelloWorldMobile

View File

@ -0,0 +1,387 @@
/** Example 027 Helloworld_Android
This example shows a simple application for Android.
*/
#include <irrlicht.h>
#ifdef _IRR_ANDROID_PLATFORM_
#include <android_native_app_glue.h>
#include "android_tools.h"
#include "android/window.h"
using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;
enum GUI_IDS
{
GUI_INFO_FPS,
GUI_IRR_LOGO,
};
/*
Android is using multitouch events.
We allow users to move around the Irrlicht logo as example of how to use those.
*/
class MyEventReceiver : public IEventReceiver
{
public:
MyEventReceiver(android_app* app )
: Device(0), AndroidApp(app), SpriteToMove(0), TouchID(-1)
{
}
void Init(IrrlichtDevice *device)
{
Device = device;
}
virtual bool OnEvent(const SEvent& event)
{
if (event.EventType == EET_TOUCH_INPUT_EVENT)
{
/*
For now we fake mouse-events. Touch-events will be handled inside Irrlicht in the future, but until
that is implemented you can use this workaround to get a GUI which works at least for simple elements like
buttons. That workaround does ignore multi-touch events - if you need several buttons pressed at the same
time you have to handle that yourself.
*/
SEvent fakeMouseEvent;
fakeMouseEvent.EventType = EET_MOUSE_INPUT_EVENT;
fakeMouseEvent.MouseInput.X = event.TouchInput.X;
fakeMouseEvent.MouseInput.Y = event.TouchInput.Y;
fakeMouseEvent.MouseInput.Shift = false;
fakeMouseEvent.MouseInput.Control = false;
fakeMouseEvent.MouseInput.ButtonStates = 0;
fakeMouseEvent.MouseInput.Event = EMIE_COUNT;
switch (event.TouchInput.Event)
{
case ETIE_PRESSED_DOWN:
{
// We only work with the first for now.force opengl error
if ( TouchID == -1 )
{
fakeMouseEvent.MouseInput.Event = EMIE_LMOUSE_PRESSED_DOWN;
if (Device)
{
position2d<s32> touchPoint(event.TouchInput.X, event.TouchInput.Y);
IGUIElement * logo = Device->getGUIEnvironment()->getRootGUIElement()->getElementFromId ( GUI_IRR_LOGO );
if ( logo && logo->isPointInside (touchPoint) )
{
TouchID = event.TouchInput.ID;
SpriteToMove = logo;
SpriteStartRect = SpriteToMove->getRelativePosition();
TouchStartPos = touchPoint;
}
}
}
break;
}
case ETIE_MOVED:
if ( TouchID == event.TouchInput.ID )
{
fakeMouseEvent.MouseInput.Event = EMIE_MOUSE_MOVED;
fakeMouseEvent.MouseInput.ButtonStates = EMBSM_LEFT;
if ( SpriteToMove && TouchID == event.TouchInput.ID )
{
position2d<s32> touchPoint(event.TouchInput.X, event.TouchInput.Y);
MoveSprite(touchPoint);
}
}
break;
case ETIE_LEFT_UP:
if ( TouchID == event.TouchInput.ID )
{
fakeMouseEvent.MouseInput.Event = EMIE_LMOUSE_LEFT_UP;
if ( SpriteToMove )
{
TouchID = -1;
position2d<s32> touchPoint(event.TouchInput.X, event.TouchInput.Y);
MoveSprite(touchPoint);
SpriteToMove = 0;
}
}
break;
default:
break;
}
if ( fakeMouseEvent.MouseInput.Event != EMIE_COUNT && Device )
{
Device->postEventFromUser(fakeMouseEvent);
}
}
else if ( event.EventType == EET_GUI_EVENT )
{
/*
Show and hide the soft input keyboard when an edit-box get's the focus.
*/
switch(event.GUIEvent.EventType)
{
case EGET_EDITBOX_ENTER:
if ( event.GUIEvent.Caller->getType() == EGUIET_EDIT_BOX )
{
if( Device->getGUIEnvironment() )
Device->getGUIEnvironment()->setFocus(NULL);
android::setSoftInputVisibility(AndroidApp, false);
}
break;
case EGET_ELEMENT_FOCUS_LOST:
if ( event.GUIEvent.Caller->getType() == EGUIET_EDIT_BOX )
{
/* Unfortunatly this only works on some android devices.
On other devices Android passes through touch-input events when the virtual keyboard is clicked while blocking those events in areas where the keyboard isn't.
Very likely an Android bug as it only happens in certain cases (like Android Lollipop with landscape mode on MotoG, but also some reports from other devices).
Or maybe Irrlicht still does something wrong.
Can't figure it out so far - so be warned - with landscape mode you might be better off writing your own keyboard.
*/
android::setSoftInputVisibility(AndroidApp, false);
}
break;
case EGET_ELEMENT_FOCUSED:
if ( event.GUIEvent.Caller->getType() == EGUIET_EDIT_BOX )
{
android::setSoftInputVisibility(AndroidApp, true);
}
break;
default:
break;
}
}
return false;
}
void MoveSprite(const irr::core::position2d<irr::s32> &touchPos)
{
irr::core::position2d<irr::s32> move(touchPos-TouchStartPos);
SpriteToMove->setRelativePosition(SpriteStartRect.UpperLeftCorner + move);
}
private:
IrrlichtDevice * Device;
android_app* AndroidApp;
gui::IGUIElement * SpriteToMove;
core::rect<s32> SpriteStartRect;
core::position2d<irr::s32> TouchStartPos;
s32 TouchID;
};
/* Mainloop.
*/
void mainloop( IrrlichtDevice *device, IGUIStaticText * infoText )
{
u32 loop = 0; // loop is reset when the app is destroyed unlike runCounter
static u32 runCounter = 0; // static's seem to survive even an app-destroy message (not sure if that's guaranteed).
while(device->run())
{
/*
The window seems to be always active in this setup.
That's because when it's not active Android will stop the code from running.
*/
if (device->isWindowActive())
{
/*
Show FPS and some counters to show which parts of an app run
in different app-lifecycle states.
*/
if ( infoText )
{
stringw str = L"FPS:";
str += (s32)device->getVideoDriver()->getFPS();
str += L" r:";
str += runCounter;
str += L" l:";
str += loop;
infoText->setText ( str.c_str() );
}
device->getVideoDriver()->beginScene(true, true, SColor(0,100,100,100));
device->getSceneManager()->drawAll();
device->getGUIEnvironment()->drawAll();
device->getVideoDriver()->endScene ();
}
device->yield(); // probably nicer to the battery
++runCounter;
++loop;
}
}
/* Main application code. */
void android_main(android_app* app)
{
// Make sure glue isn't stripped.
app_dummy();
/*
The receiver can already receive system events while createDeviceEx is called.
So we create it first.
*/
MyEventReceiver receiver(app);
/*
Create the device.
You have currently the choice between 2 drivers:
EDT_OGLES1 is basically a opengl fixed function pipeline.
EDT_OGLES2 is a shader pipeline. Irrlicht comes with shaders to simulate
typical fixed function materials. For this to work the
corresponding shaders from the Irrlicht media/Shaders folder are
copied to the application assets folder (done in the Makefile).
*/
SIrrlichtCreationParameters param;
// param.DriverType = EDT_OGLES1; // android:glEsVersion in AndroidManifest.xml should be "0x00010000" (requesting 0x00020000 will also guarantee that ES1 works)
param.DriverType = EDT_OGLES2; // android:glEsVersion in AndroidManifest.xml should be "0x00020000"
param.WindowSize = dimension2d<u32>(300,300); // using 0,0 it will automatically set it to the maximal size
param.PrivateData = app;
param.Bits = 24;
param.ZBufferBits = 16;
param.AntiAlias = 0;
param. EventReceiver = &receiver;
/* Logging is written to a file. So your application should disable all logging when you distribute your
application or it can fill up that file over time.
*/
#ifndef _DEBUG
param.LoggingLevel = ELL_NONE;
#endif
IrrlichtDevice *device = createDeviceEx(param);
if (device == 0)
return;
receiver.Init(device);
// ANativeActivity_setWindowFlags(app->activity, AWINDOW_FLAG_FULLSCREEN, 0);
IVideoDriver* driver = device->getVideoDriver();
ISceneManager* smgr = device->getSceneManager();
IGUIEnvironment* guienv = device->getGUIEnvironment();
ILogger* logger = device->getLogger();
IFileSystem * fs = device->getFileSystem();
/* Access to the Android native window. You often need this when accessing NDK functions like we are doing here.
Note that windowWidth/windowHeight have already subtracted things like the taskbar which your device might have,
so you get the real size of your render-window.
*/
ANativeWindow* nativeWindow = static_cast<ANativeWindow*>(driver->getExposedVideoData().OGLESAndroid.Window);
int32_t windowWidth = ANativeWindow_getWidth(app->window);
int32_t windowHeight = ANativeWindow_getHeight(app->window);
/* Get display metrics. We are accessing the Java functions of the JVM directly in this case as there is no NDK function for that yet.
Checkout android_tools.cpp if you want to know how that is done. */
irr::android::SDisplayMetrics displayMetrics;
memset(&displayMetrics, 0, sizeof displayMetrics);
irr::android::getDisplayMetrics(app, displayMetrics);
/* For troubleshooting you can use the Irrlicht logger.
The Irrlicht logging messages are send to the Android logging system using the tag "Irrlicht".
They stay in a file there, so you can check them even after running your app.
You can watch them with the command: "adb logcat Irrlicht:V DEBUG:V *:S"
This means Irrlicht _V_erbose, debug messages verbose (p.E callstack on crashes) and all other messages _S_ilent.
Clean the logging file with: "adb logcat -c".
See http://developer.android.com/tools/debugging/debugging-log.html for more advanced log options.
*/
char strDisplay[1000];
sprintf(strDisplay, "Window size:(%d/%d)\nDisplay size:(%d/%d)", windowWidth, windowHeight, displayMetrics.widthPixels, displayMetrics.heightPixels);
logger->log(strDisplay);
core::dimension2d<s32> dim(driver->getScreenSize());
sprintf(strDisplay, "getScreenSize:(%d/%d)", dim.Width, dim.Height);
logger->log(strDisplay);
/* Your media must be somewhere inside the assets folder. The assets folder is the root for the file system.
This example copies the media in the Android.mk makefile. */
stringc mediaPath = "media/";
// The Android assets file-system does not know which sub-directories it has (blame google).
// So we have to add all sub-directories in assets manually. Otherwise we could still open the files,
// but existFile checks will fail (which are for example needed by getFont).
for ( u32 i=0; i < fs->getFileArchiveCount(); ++i )
{
IFileArchive* archive = fs->getFileArchive(i);
if ( archive->getType() == EFAT_ANDROID_ASSET )
{
archive->addDirectoryToFileList(mediaPath);
break;
}
}
/* Set the font-size depending on your device.
dpi=dots per inch. 1 inch = 2.54 cm. */
IGUISkin* skin = guienv->getSkin();
IGUIFont* font = 0;
if ( displayMetrics.xdpi < 100 ) // just guessing some value where fontsize might start to get too small
font = guienv->getFont(mediaPath + "fonthaettenschweiler.bmp");
else
font = guienv->getFont(mediaPath + "bigfont.png");
if (font)
skin->setFont(font);
// A field to show some text. Comment out stat->setText in run() if you want to see the dpi instead of the fps.
IGUIStaticText *text = guienv->addStaticText(stringw(displayMetrics.xdpi).c_str(),
rect<s32>(5,5,635,35), false, false, 0, GUI_INFO_FPS );
guienv->addEditBox( L"", rect<s32>(5,40,475,80));
// add irrlicht logo
IGUIImage * logo = guienv->addImage(driver->getTexture(mediaPath + "irrlichtlogo3.png"),
core::position2d<s32>(5,85), true, 0, GUI_IRR_LOGO);
s32 minLogoWidth = windowWidth/3;
if ( logo && logo->getRelativePosition().getWidth() < minLogoWidth )
{
/* Scale to make it better visible on high-res devices (we could also work with dpi here).
*/
logo->setScaleImage(true);
core::rect<s32> logoPos(logo->getRelativePosition());
f32 scale = (f32)minLogoWidth/(f32)logoPos.getWidth();
logoPos.LowerRightCorner.X = logoPos.UpperLeftCorner.X + minLogoWidth;
logoPos.LowerRightCorner.Y = logoPos.UpperLeftCorner.Y + (s32)((f32)logoPos.getHeight()*scale);
logo->setRelativePosition(logoPos);
}
/*
Add a 3d model. Note that you might need to add light when using other models.
A copy of the model and it's textures must be inside the assets folder to be installed to Android.
In this example we do copy it to the assets folder in the Makefile jni/Android.mk
*/
IAnimatedMesh* mesh = smgr->getMesh(mediaPath + "dwarf.x");
if (!mesh)
{
device->closeDevice();
device->drop();
return;
}
smgr->addAnimatedMeshSceneNode( mesh );
/*
To look at the mesh, we place a camera.
*/
smgr->addCameraSceneNode(0, vector3df(15,40,-90), vector3df(0,30,0));
/*
Mainloop. Applications usually never quit themself in Android. The OS is responsible for that.
*/
mainloop(device, text);
/* Cleanup */
device->setEventReceiver(0);
device->closeDevice();
device->drop();
}
#endif // defined(_IRR_ANDROID_PLATFORM_)
/*
**/

View File

@ -0,0 +1 @@
target = android-10

View File

@ -0,0 +1,95 @@
------------
REQUIREMENTS
------------
To use Android you need to have installed:
- Android SDK (from http://developer.android.com)
- Android NDK (from http://developer.android.com)
- ant (a build tool commonly used for Java)
- A Java jdk (for example openjdk-6-jdk)
- GNU Make 3.81 or later
- A recent version of awk
- On Windows you need to have Cygwin (at least version 1.7) installed
----------------------------
BUILDING Irrlicht & your App
----------------------------
1. Assign your Android SDK path to an ANDROID_HOME environment variable.
2. Add $ANDROID_HOME/tools and $ANDROID_HOME/platform-tools and the Android NDK main folder to your PATH environment variable.
3. Go to: source/Irrlicht/Android and call "ndk-build" or "ndk-build NDEBUG=1"
4. Go to: examples/01.HelloWorld_Android and call "ndk-build" or "ndk-build NDEBUG=1"
5. Call "ant debug" to create package
6. Connect device to PC (with USB debugging mode ON) or turn on emulator.
7. Call "adb -d install bin/HelloWorldMobile-debug.apk" (if you use emulator please add "-e" parameter instead of "-d") to install package on your device/emulator.
Troubleshooting:
Error: Unable to resolve project target 'android-10'
Solution: Run "android sdk" in sdk/tools and install API 10.
Alternatively you can probably (not yet tested) set another APP_PLATFORM
in the Application.mk's for the project and for Irrlicht. In this case you
should likely also change the android:minSdkVersion in the AndroidManifest.xml
-----
FILES
-----
AndroidManifest.xml:
Every Android application needs one of those to describe the needs of the application.
Must have exactly this name.
See http://developer.android.com/guide/topics/manifest/manifest-intro.html
build.xml:
Ant build file to create the final package.
You might want to create a new one as described in the Android documentation:
http://developer.android.com/tools/projects/projects-cmdline.html
That will then also update project.properties.
project.properties
Contains the build target (and maybe other project properties). Must exist.
jni:
A folder by this name must exist below the folder where you have build.xml.
Usually it contains the native (c/c++) source files, but in our case we put
the source-files one level higher (with LOCAL_PATH in Android.mk).
jni/Android.mk:
The Makefile for the project.
Source-files in the project are added to LOCAL_SRC_FILES
In the Irrlicht example it also copies the assets, but you can
also already create your project assets in the right place.
jni/Application.mk:
Optional file which for example restricts which modules are installed and
where you can set specific target architectures.
More info about this can be found in the ndk docs.
res:
A folder with resources which districuted with your application and can be accessed via ID's.
Unfortunately no direct NDK access to resources at the time of writing this. So you either have
to access them with java-code and copy to c++ somehow or you have to use hacks to read the format
directly (which is done by some apps, but not future-safe and google recommends not doing that).
Please check the official "App Resources" android developer documention, as this is rather complex.
We use it only for the application icons in this example.
assets:
Files in here are distributed with your app. It's acting like a read-only file system.
assets/media/Shaders:
Shader code needed by the OGLES2 driver to simulate a fixed function pipeline.
In the example this code is automatically copied within the Android.mk makefile.
The path where the shaders are searched is set in the IRR_OGLES2_SHADER_PATH define in IrrCompileConfig.h
The names are hardcoded so they have to be identical to those found in media/Shaders.
You can rewrite the shaders, but ensure to add some working shaders files by those names.
The OGLES1 driver doesn't need those files.
obj:
All object and library files mentioned in the Android.mk are put in here before linking.
libs:
Contains the binaries of your application after compilation. The application itself is a lib(probably because native code can't run directly but only as lib).
src:
The src folder is needed when you have Java sources and should only contain .java and .aidl files.
Although the examples doesn't use Java the makefile creates this folder as the ant build.xml in the android sdk needs it.

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB