Irrlicht Engineを使うために右往左往する
しばらく前から仲間内でプレイしているゲームがある。活動する曜日を決めて、毎週欠かさず集まってプレイしており、はじめてからかれこれ3年以上になる。僕にとってはその中の方が居心地が良いし、そこに居る事で安心感を覚える。だからそこで使われている技術要素についても興味がある。今回はその中でも中心的に使われている要素である Irrlicht Engine について、少しだけ理解を深める事にした。
Irrlicht Engine は、3Dゲームエンジンというよりはレンダリングライブラリだ。C++で実装されており、軽量で、商用にも利用できるし、非常に寛容なオープンソースライセンスとして配布されている。ただ音声に関する実装はないし、衝突判定も簡易な実装となっているらしい。
以前はフリーのゲームエンジン用途として人気があったのかもしれないけれど、今は他にも優れたゲームエンジンがあるため、あまり使われていないかもしれない。ソースコードはSourceForgeにあり、もう更新もされていないのかと思ったのだが、確認してみるとそんな事は全くなく、 cutealien という人が精力的にコミットしていた。この人はドイツの3D関連のエンジニアらしい。本当に凄い。
IrrlichtのDownloadページには、 Irrlicht SDK なるものがZIP形式で配布されており、最新版は1.8.5だった。このファイルをダウンロードし、ローカルでビルドしようとした所、Irrlichtに同梱されているlibpngとzlibのバージョンの食い違いによってリンカーがエラーを出力する状態だった。この問題を解決するためにいろいろと試行錯誤したが、終ぞ問題を解決できなかった。しかし諦めるにはまだ早い。開発者が少ないようなプロダクトでは、最新版が一番安定しているという事はよくある。だから Irrlicht SDK 1.8.5 は諦め、最新のコードをSVNから取得する事にした。
svn checkout https://svn.code.sf.net/p/irrlicht/code/trunk irrlicht-codeSVNでコードを取得すると、 https://sourceforge.net/p/irrlicht/code/6731/ がHEADの状態のソースコードを取得できた。以降はこのコードを前提とする。
実はこの後の作業を進める上で、ビルドは通るのだが、実行中にNULLポインタに対する不正参照によってクラッシュするという、macOS上でのIrrlichtのバグに気が付いた。そのため次のパッチを当てる必要がある。
--- source/Irrlicht/CIrrDeviceOSX.mm (リビジョン 6731)
+++ source/Irrlicht/CIrrDeviceOSX.mm (作業コピー)
@@ -584,6 +584,11 @@
// Create menu
NSString* bundleName = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleName"];
+ // Fix: Ensure bundleName is never nil to prevent NSMenuItem crash
+ if (bundleName == nil || [bundleName length] == 0)
+ {
+ bundleName = @"Irrlicht";
+ }
NSMenu* mainMenu = [[[NSMenu alloc] initWithTitle:@"MainMenu"] autorelease];
NSMenu* menu = [[[NSMenu alloc] initWithTitle:bundleName] autorelease];
ビルドする環境はmacOS、XCodeなどは既にインストール済みであるものとして、このあたりの環境構築については省略する。
ソースツリー内に Irrlicht.xcodeproj というファイルがある。このファイルはXCode用のプロジェクトファイルだ。
まずはどのようなターゲットが用意されているかを確認する。
xcodebuild -list -project ./irrlicht-code/source/Irrlicht/Irrlicht.xcodeproj
Command line invocation:
/Applications/Xcode.app/Contents/Developer/usr/bin/xcodebuild -list -project ./irrlicht-code/source/Irrlicht/Irrlicht.xcodeproj
User defaults from command line:
IDEPackageSupportUseBuiltinSCM = YES
Information about project "Irrlicht":
Targets:
Irrlicht_OSX
Build Configurations:
Debug
Release
If no build configuration is specified and -scheme is not passed then "Release" is used.
Schemes:
Irrlicht_OSX
Irrlicht_OSX というターゲットが用意されている事が分かった。このターゲットを指定し xcodebuild でビルドする。
xcodebuild -project ./irrlicht-code/source/Irrlicht/Irrlicht.xcodeproj -configuration Release -target Irrlicht_OSX
ビルドに成功すると、 ./irrlicht-code/lib/OSX/libIrrlicht.a に静的ライブラリが出力される。
この静的ライブラリを使用するコードを実装する。
#include <stdio.h>
#include <irrlicht.h>
#include <exampleHelper.h>
using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;
int main()
{
IrrlichtDevice *device = createDevice(video::EDT_BURNINGSVIDEO,
dimension2d<u32>(640, 480),
16,
false, false, false, 0);
if (!device)
{
return 1;
}
device->setWindowCaption(L"Hello World! - Irrlicht Engine Demo");
IVideoDriver* driver = device->getVideoDriver();
ISceneManager* smgr = device->getSceneManager();
IGUIEnvironment* guienv = device->getGUIEnvironment();
guienv->addStaticText(L"Hello World!",
rect<s32>(10,10,260,22),
true);
const io::path mediaPath = "./irrlicht-code/media/";
IAnimatedMesh* mesh = smgr->getMesh(mediaPath + "sydney.md2");
if (!mesh)
{
device->drop();
return 1;
}
IAnimatedMeshSceneNode* node = smgr->addAnimatedMeshSceneNode(mesh);
if (node)
{
node->setMaterialFlag(EMF_LIGHTING, false);
node->setMD2Animation(scene::EMAT_STAND);
node->setMaterialTexture( 0, driver->getTexture(mediaPath + "sydney.bmp") );
}
smgr->addCameraSceneNode(0,
vector3df(0,30,-40),
vector3df(0,5,0));
while(device->run())
{
driver->beginScene(ECBF_COLOR | ECBF_DEPTH, SColor(255,100,101,140));
smgr->drawAll();
guienv->drawAll();
driver->endScene();
}
device->drop();
return 0;
}
このコードを clang++ でビルドする。
clang++ main.cpp -I./irrlicht-code/include -L./irrlicht-code/lib/OSX/ -lIrrlicht -framework Cocoa -framework OpenGL -framework IOKit
ビルドに成功すると a.out が出力される。
./a.outこのコマンドを実行すると、Irrlichtのウィンドウが開き読み込んだモデルが表示される。