二通りの表示方法がある。
irrDriver->draw2DImage(irrDriver->getTexture("irrlichtlogo2.png"),
core::position2d<s32>(400, 400), // 表示先の位置
core::rect<s32>(0, 0, 128, 128), // 元画像中の表示する範囲
NULL, // クリッピングなし
video::SColor(255,255,255,255), // 色(暗くしたい場合は小さくする)
true // アルファチャネル有効
);
これは、座標(400,400)を左上としてirrlichtlogo2.pngを表示する例である。irrlichtlogo2.pngは128x128の画像なので、(0, 0, 128, 128)は全域を表示するという意味になる。
拡大縮小ありの場合は、下記のようにする。
irrDriver->draw2DImage(irrDriver->getTexture("irrlichtlogo2.png"),
core::rect<s32>(400, 400, 480, 480), // 表示先の範囲
core::rect<s32>(0, 0, 128, 128), // 元画像中の表示する範囲
NULL, // クリッピングなし
NULL, // 暗くしたい場合は、4頂点の色をSColorへのポインタで指定
true // アルファチャネル有効
);
上記の場合、(400, 400)の位置を左上として幅80高さ80で表示する。
GUIEnvironmentに登録して表示する場合、前提として、各フレームでIGUIEnvironment::drawAll()を呼び出している必要がある。登録されたものを描画するのがdrawAll()関数だからである。無い場合は、SceneManagerのdrawAll()呼び出し以降、かつendScene()よりも前に下記の呼び出しを挿入すること。
pIrrDevice->getGUIEnvironment()->drawAll();
(イメージを表示する場合の例)
下記を実行すると、以後この画像を表示し続ける。
gui::IGUIEnvironment* ge = pIrrDevice->getGUIEnvironment();
gui::IGUIImage* gi = ge->addImage(
pIrrDevice->getVideoDriver()->getTexture("irrlichtlogo2.png"),
core::position2d<s32>(10,20)); // スクリーン座標のx=10,y=20に表示
消したいときは、gi->remove() で削除する。drop()ではない。
Irrlichtのビルボード機能、スプライト機能には、回転機能が存在しない。このため、そういうことがしたいのならプリミティブを直接操作する必要がある。
このために作成したユーティリティ関数を下記に示す。
using namespace irr;
using namespace irr::core;
template <class T>
class CMatrix2 {
public:
T M[4];
void transformVect(irr::core::vector2d<T> &v) {
irr::core::vector2d<T> r;
r.X = v.X * M[0] + v.Y * M[1];
r.Y = v.X * M[2] + v.Y * M[3];
v = r;
}
};
enum enumDRAWBillBoard_Coord {
EDBC_WORLD = 0,
EDBC_CAMERA = 1
};
void DrawRotatedBillboard(IrrlichtDevice* pDevice, scene::ICameraSceneNode* pCamera,
video::ITexture* pTexture, core::vector3df vpos, core::dimension2d<f32> size,
double rot, enumDRAWBillBoard_Coord edbc, bool bScale) {
scene::ISceneManager* smgr = pDevice->getSceneManager();
video::IVideoDriver* pDriver = pDevice->getVideoDriver();
vector3df v1, v2;
if(edbc == EDBC_WORLD) {
pCamera->getViewMatrix().transformVect(v1, vpos);
if(v1.Z <= 0) return;
}
else
v1 = vpos;
pCamera->getProjectionMatrix().transformVect(v2, v1);
if(v2.Z <= 0) return;
vector2df rvscr(v2.X / v2.Z, v2.Y / v2.Z);
CMatrix2<float> mtx;
mtx.M[0] = (float)cos(rot); mtx.M[1] = (float)-sin(rot);
mtx.M[2] = -mtx.M[1]; mtx.M[3] = mtx.M[0];
dimension2d<u32> d2Screen = pDriver->getCurrentRenderTargetSize();
rect<s32> rvp = pDriver->getViewPort();
float H = float(v2.Z * tan(pCamera->getFOV() / 2));
float r = bScale ? rvp.getHeight() / 2 / H : 1.0f;
dimension2d<f32> ssize(size.Width * r , size.Height * r);
position2d<float> center(d2Screen.Width / 2 + rvscr.X * d2Screen.Width / 2,
d2Screen.Height / 2 - rvscr.Y * d2Screen.Height / 2);
position2d<float> p2d[4];
p2d[0].X = - ssize.Width / 2;
p2d[0].Y = - ssize.Height / 2;
p2d[1].X = ssize.Width / 2;
p2d[1].Y = - ssize.Height / 2;
p2d[2].X = ssize.Width / 2;
p2d[2].Y = ssize.Height / 2;
p2d[3].X = - ssize.Width / 2;
p2d[3].Y = ssize.Height / 2;
video::S3DVertex vert[4];
for(int i = 0; i < 4; i ++) {
mtx.transformVect(p2d[i]); // To rotate billboard
p2d[i].X *= d2Screen.Width / rvp.getWidth();
p2d[i].Y *= d2Screen.Height / rvp.getHeight();
p2d[i] += center;
vert[i].Pos.X = p2d[i].X;
vert[i].Pos.Y = p2d[i].Y;
vert[i].Color = video::SColor(255, 255, 255, 255);
}
float xmin = p2d[0].X;
float xmax = p2d[0].X;
float ymin = p2d[0].Y;
float ymax = p2d[0].Y;
for(int i = 1; i < 4; i ++) {
if(p2d[i].X > xmax) xmax = p2d[i].X;
if(p2d[i].X < xmin) xmin = p2d[i].X;
if(p2d[i].Y > ymax) ymax = p2d[i].Y;
if(p2d[i].Y < ymin) ymin = p2d[i].Y;
}
if(xmin > d2Screen.Width || ymin > d2Screen.Height ||
xmax < 0 || ymax < 0)
return; // Totally out of viewport
vert[1].TCoords.X = 1;
vert[2].TCoords.X = 1;
vert[2].TCoords.Y = 1;
vert[3].TCoords.Y = 1;
u16 index[] = { 0, 1, 2, 2, 3, 0};
video::SMaterial mat;
mat.Lighting = false;
mat.TextureLayer[0].Texture = pTexture;
mat.setFlag(video::EMF_ZBUFFER, false);
mat.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
pDriver->setMaterial(mat);
pDriver->draw2DVertexPrimitiveList(vert, 4, index, 2, video::EVT_STANDARD);
}
このように、標準で存在しない物については、上記のようにプリミティブ描画関数draw2DVertexPrimitiveList等を直接操作して描画する必要がある。