Irrlicht is a well-known Open Source 3D engine, which supports multiple platforms. It has been ported to Android by Laurent Mallet, the source code can be obtained from here. The code is written in C++, but Android mainly supports Java. Using native C++ on Android to develop applications is more difficult, and not convenient, especially to debug. For a developer to use irrlicht easily, it is best to provide Java interfaces.
The work here is wrapping irrlicht engine to enable it to provide the Java interface. Traditional method for Java calling native code is using the jni mechanism. But irrlicht engine is big and has many render objects. Using jni directly to wrap irrlicht will be a hard work. We have to define classes in Java, create C++ code skeleton, maintain global reference of Java object to irrlicht render object, process callback, etc. In order to simplify programming, CLE is used as middleware to help Java to call native code.
CLE (Common Language Extension) is developed by srplab, which presents a general method for mixed language calls. It supports distributed object technique, which objects as medium to implement the mixed call between languages. Programming with cle, you need not care about details of special script languages, and the wrapping supports many languages such as Java, Lua, Python, etc.
Wrapping irrlicht with cle, the first step is to create interface description using XML language, as follows:
="1.0"="utf-8"
<service ID="d52a1620-6a1c-401b-9c31-826793086683"
Password="123" Name="SRPIrrlichtES2Engine">
<import>
<SRPFSEngine />
</import>
<module>
<SRPIrrlichtES2EngineBasicModule ID="73e4254e-1fed-4d15-970a-0756a39521ea" />
</module>
<macro>
……
</macro>
<struct>
<SRP3DVector ID="e41ba4f5-ef8f-477d-9c03-dafe387f04f9">
<X Type="VS_FLOAT" />
<Y Type="VS_FLOAT" />
<Z Type="VS_FLOAT" />
</SRP3DVector>
</struct>
<sysrootitem>
<BasicServiceItem ID="66d95cfa-ab44-481c-af86-101339687bf0"
NameID="71f6f33e-04b2-47cb-9487-092870c8e201">
<object>
<IrrDeviceClass ID="bb11872b-ae5e-45b7-8fd6-a0d009d1bb5d" SysEvent="true">
<attribute>
<Color Type="VS_COLOR" Default="" EditType="3" />
<Width Type="VS_INT32" Default="800" />
<Height Type="VS_INT32" Default="600" />
<RenderWnd Type="VS_ULONG" SyncFlag="1" Default="" />
</attribute>
<function>
<GetCurDevice ID="fb76adbd-13ec-423b-a7ea-f8434bf6823c">
<output Type="void *" />
</GetCurDevice>
<Lua_GetCurDevice Type="luafunc" Desc="Driver=Lua_GetCurDevice()"
ID="28d4732e-e36e-434a-a838-b9b29f17dc1a" />
……
</function>
</IrrDeviceClass>
……
</object>
</BasicServiceItem>
</sysrootitem>
</service>
The above XML description can also be created using tools srpdebug, which can be downloaded from srplab web site. After finishing the description, uses srpdebug tool or star2c command line tool to create C/C++ code skeleton.
Each object will be associated with one or more irrlicht objects. For the above “IrrDeviceClass
”, when activated, an irrlicht device object will be created, as follows:
SRPIrrlichtES2EngineBasicModule_IrrDeviceClass.cpp:
...
case VSEVENT_SYSTEMEVENT_ONACTIVATE:
{
IrrlichtDeviceClassLocalBuf = (struct StructOfIrrlichtDeviceClassLocalBuf *)pSRP ->
GetPrivateBuf( IrrDeviceClassPtr, IrrlichtDeviceClass_ClassLayer,
IRRLICHTDEVICECLASS_LOCALVARINDEX, NULL );
if( IrrlichtDeviceClassLocalBuf -> SRPEventReceiver == NULL )
IrrlichtDeviceClassLocalBuf -> SRPEventReceiver = new class ClassOfSRPEventReceiver();
if( IrrlichtDeviceClassLocalBuf ->IrrlichtDevice == NULL ){
irr::SIrrlichtCreationParameters param;
param.DriverType = video::EDT_OGLES2;
param.WindowId = (void *)IrrDeviceClassPtr ->RenderWnd;
param.WindowSize = core::dimension2d<s32>
(IrrDeviceClassPtr->Width, IrrDeviceClassPtr->Height);
param.Bits = 16;
param.Fullscreen = false;
param.Stencilbuffer = false;
param.Vsync = false;
param.AntiAlias = false;
param.HighPrecisionFPU = false;
param.EventReceiver = IrrlichtDeviceClassLocalBuf -> SRPEventReceiver;
IrrlichtDeviceClassLocalBuf ->IrrlichtDevice = irr::createDeviceEx(param);
#if( VS_OS_TYPE == VS_OS_WINDOWS)
_control87( _MCW_EM,0x801f );
#endif
}
}
pSRP ->GetID(IrrDeviceClassPtr,&g_DeviceObjectID);
break;
Finish the C++ code, create project to generate SRPIrrlichtES2EngineBasicModule.dll for Windows, or libSRPIrrlichtES2EngineBasicModule_android.so for Android.
For Java, to call the above library, the code is as follows:
starcore= StarCoreFactory.GetFactory();
Service=starcore._InitSimple
("test","123",0,0,"SRPIrrlichtES2Engine.xml");
SrvGroup = (StarSrvGroupClass)Service._Get("_ServiceGroup");
Device=Service._GetObject("IrrDeviceClass")._New();
Device._Set("Width",800);
Device._Set("Height",480);
Device._Set("Color",0x7F7F7F7F);
Device._Active();
When Device._Active()
is called, the C++ event VSEVENT_SYSTEMEVENT_ONACTIVATE
will be generated, then the corresponding irrlicht device is created.
An example Helloworld
:
The wrapping work is in progress, you can download the full source code from http://code.google.com/p/wrapirrlicht-for-android.