Mobile:NEWS 2003年12月5日 00:52 AM 更新

BREW プログラミング入門(7)
さらに描画のおはなし(2/2)


前のページ

トランスレートとは?

 ここまでは、クリッピングについて解説してきました。ここからはトランスレートについて解説していきます。

 トランスレートとは、端的に言えば原点移動です。描画する前に原点移動させてから描画 API を呼び出すと原点移動させた分だけ画面上でオフセットがかかります。


トランスレートの効果

 BREWでもトランスレートをサポートしておりIGraphicsインタフェースのTranslate関数を使用して設定できます。ここでトランスレート関連のAPIを一覧にまとめておきます。

  • IGraphics

関数名解説
Translate移動量を設定します

 上記表にある通り、現状のBREWではトランスレート量を設定することしかできません。また、IDisplayインタフェースにはトランスレート機能はありませんので、IGraphicsとIDisplayを混在させて使用するときなど微妙に使い勝手が悪くなってしまいます。これは本来BREWのトランスレート機能がIGraphicsのビューポートという機構のために用意されているからでしょう。

 ビューポートに関してはここでは詳しく解説しませんが、トランスレート機能は便利なだけにもう少し機能が強化されることに期待したいとおもいます。

トランスレートを使ってみる

 それでは、IGraphicsインタフェースのトランスレート機能を使用してみましょう。下記のコードは、トランスレートする前と後での描画結果の違いが分かります。

IGraphics*  graphics = app->g;
// 四角形を描画
rect.x = 10;
rect.y = 10;
rect.dx = 60;
rect.dy = 50;
IGRAPHICS_DrawRect(graphics,&rect);
// トランスレート量を設定
IGRAPHICS_Translate(graphics,-40,-40);
// 四角形を描画
IGRAPHICS_DrawRect(graphics,&rect);
// トランスレートをリセット
IGRAPHICS_Translate(graphics,40,40);
// 画面更新
IGRAPHICS_Update(graphics);

※一部省略されています。完全なコードはこちらを参照してください(クリックで別ウィンドウにソースコード表示)

 実際に描画されると以下の図のようになります。


トランスレートする前と後での違い

クリッピングとトランスレート、何が便利なの?

 ここまでで、クリッピングとトランスレートの具体例は終わりにしたいとおもいます。では、いったいクリッピングとトランスレートを使用したときと使用しなかったときで何が変わるのでしょうか?

 画面が絶対座標上で動かないデザインや、絶対に全ての範囲が描画されることが分かっている場合には、クリッピングやトランスレートを使用する必要はありません。

 しかし画面が絶対座標上で移動する場合、例えばウィンドウを表示させてその中にコンテンツを描画する場合など、ウィンドウの位置が変わるとウィンドウ内部のコンテンツの絶対座標が変わってしまいます。また、ウィンドウの大きさが変われば表示されている範囲が変わるかもしれません。

 このような状況では、クリッピングやトランスレートを使用しないで描画するのは至難の業です。例えば、トランスレート機能を使用してウィンドウの中身を描画すれば、ウィンドウのコンテンツはウィンドウ上の原点からの相対座標で表現でき、いちいち絶対座標に変換する複雑な計算を省略することができます。

 またクリッピングに対しても同様なことがいえます。つまり、複雑な計算を行わなくても複雑な描画処理を記述できるようになるのです。

 もし全ての描画を絶対座標で記述していたなら、完成した後で「もう少し全体的に下にして欲しい」とか、「この範囲は見えなくしてほしい」などの要求があった時に書き直すのが大変です。下手をすると、描画周りのコードを作り直さなければならなくなってしまいます。

 クリッピングとトランスレートが便利であるということは理解してもらえたかと思いますが、BREWでそれらを使用するのは面倒くさそうだということも上記のサンプルコードなどを見てもらえれば分かるかとおもいます。

 一つの解決策としてIGraphicsとIDisplayを抽象化して、数値の扱い方や設定の方法を共通にすることです。そのようなライブラリを独自に開発してもよいですが、現在ではそれらを行うライブラリ製品などが既に開発されています。

 既存の物を利用してしまえば、わざわざ内部の複雑な計算をいちから考えなくて良くなるので便利かとおもいます。

ビットマップの変形

 最後に少し話は変わりますが描画つながりということで、ビットマップの拡大と縮小や変形の方法を解説したいと思います。

 BREWではITransformインタフェースを使用してビットマップの変形や複雑な転送操作を行うことができます。具体的にはビットマップを拡大したり縮小したりして表示することや、90度回転や鏡像を作ることなどができます。また、行列指定でより複雑な変形を行うこともできます。

 2倍、4倍や1/2倍、1/4倍、90度回転、鏡像などはITransformインタフェースのTransformBltSimple関数により実現可能です。また、1.5倍や60度回転などはTransformBltComplex関数により実現可能です。

 ところで、TransformBltSimple関数、TransformBltComplex関数ともに変形元のビットマップを引数として必要とします。変形元のビットマップのクローンを作成してから処理を行ってはくれないようなので、変形元と変形先を同じビットマップにするとおかしな結果が 得られてしまいますので注意が必要です。

ビットマップの変形を行ってみる

 ところで、ITransformインタフェースはIBitmapインタフェースの QueryInterface関数を使用して作成します。ITransformインタフェースを単体で使用することはありません。

 それでは、まずTransformBltSimple関数を使用したコードを以下に示します。

IShell*  shell = app->a.m_pIShell;
IDisplay*  display = app->a.m_pIDisplay;
// デバイスのビットマップを取得
IDISPLAY_GetDeviceBitmap(display,&dev);
// デバイスビットマップと互換性のある作業用ビットマップを作成
IBITMAP_CreateCompatibleBitmap(dev,&tmp,100,100);
// 作業用ビットマップにビットマップを描画
IBITMAP_BltIn(tmp,0,0,100,100,bmp,0,0,AEE_RO_COPY);
// デバイスビットマップから ITransform インタフェースを作成
IBITMAP_QueryInterface(dev,AEECLSID_TRANSFORM,&transform);
// 作業用ビットマップからデバイスビットマップへ変形転送
ITRANSFORM_TransformBltSimple(
    transform,          // オブジェクト
    0,                  // 転送先の X 座標
    0,                  // 転送先の Y 座標
    tmp,                // 転送元のビットマップ
    0,                  // 転送元の転送開始 X 座標
    0,                  // 転送元の転送開始 Y 座標
    100,                // 転送元の幅
    100,                // 転送元の高さ
    TRANSFORM_ROTATE_90 | TRANSFORM_SCALE_2,   // 変形方法
    COMPOSITE_OPAQUE);  // 転送モード
// 画面更新
IDISPLAY_Update(display);

※一部省略されています。完全なコードはこちらを参照してください(クリックで別ウィンドウにソースコード表示)

※転送先のX座標や転送先のY座標は、実際にはもう少しややこしい動作を行います。詳しくはBREW APIリファレンスを参照してください

 上記のコードでは、まず作業用のビットマップを作成してそこに画像を描き、TransformBltSimple関数を使用して画像を90度回転させ2倍に拡大した後、画面に描画しています。このように、TransformBltSimple関数では拡大縮小と回転などを同時に適応することが可能です。


標準転送と変形転送(TransformBltSimple)

 では次に、TransformBltComplex関数を使用してより複雑な処理を行ってみましょう。

IShell*  shell = app->a.m_pIShell;
IDisplay*  display = app->a.m_pIDisplay;
AEETransformMatrix  matrix;
// デバイスのビットマップを取得
IDISPLAY_GetDeviceBitmap(display,&dev);
// デバイスビットマップと互換性のある作業用ビットマップを作成
IBITMAP_CreateCompatibleBitmap(dev,&tmp,100,100);
// 作業用ビットマップにビットマップを描画
IBITMAP_BltIn(tmp,0,0,100,100,bmp,0,0,AEE_RO_COPY);
// デバイスビットマップから ITransform インタフェースを作成
IBITMAP_QueryInterface(dev,AEECLSID_TRANSFORM,&transform);
// 変形マトリックスを設定
matrix.A = 192;   // 256 * 1.5 * cos(60)
matrix.B = 332;   // 256 * 1.5 * sin(60)
matrix.C = -332;  // 256 * 1.5 * -sin(60)
matrix.D = 192;   // 256 * 1.5 * cos(60)
// 作業用ビットマップからデバイスビットマップへ変形転送
ITRANSFORM_TransformBltComplex(
    transform,         // オブジェクト
    0,                 // 転送先の X 座標
    0,                 // 転送先の Y 座標
    tmp,               // 転送元のビットマップ
    0,                 // 転送元の転送開始 X 座標
    0,                 // 転送元の転送開始 Y 座標
    100,               // 転送元の幅
    100,               // 転送元の高さ
    &matrix,           // 変形マトリックス
    COMPOSITE_OPAQUE); // 転送モード
// 画面更新
IDISPLAY_Update(display);

※一部省略されています。完全なコードはこちらを参照してください(クリックで別ウィンドウにソースコード表示)

※転送先のX座標や転送先のY座標は、実際にはもう少しややこしい動作を行います。詳しくはBREW APIリファレンスを参照してください。

 上記のコードでは、まず作業用のビットマップを作成してそこに画像を描き、TransformBltComplex関数を使用して画像を1.5倍に拡大して60度回転させています。このように、TransformBltComplex関数の変形規則は行列を使用することになります。

 より詳しい、変形マトリックスの設定の方法は BREW APIリファレンスなどを参照してください。


標準転送と変形転送(TransformBltComplex)

まとめ

 今回はクリッピングやトランスレートの詳細と、ビットマップの変形について解説しました。第3回の「画面に描画してみよう!」、前回の「ビットマップを描画してみよう」と合わせてBREWでの描画についてはほぼ解説しました。

 あとは、ゲーム用にISpriteというスプライトエンジンのインタフェースが存在したりします。

 アプリケーションにとって、見た目や操作性は非常に重要な要素です。処理の内容やアルゴリズムも重要な要素ですが、ユーザインタフェースいかんによってそのアプリがユーザーに長く使われるかどうかが決まってきます。

 インタフェースを全て画像で作ることもできますが、現状の携帯電話などのモバイル機器のメモリ容量などを考えるとそれも不可能です。ある程度はコーディングで表現することになりますので、そのような時に今回解説したような事柄が重要になってくるとおもいます。

※今回の記事のソースコードは、ソフィア・クレイドル のサイトからダウンロードできます。

著者紹介
堀口淳史:ソフィア・クレイドル研究開発部チーフ ソフトウェアアーキテクト。ソフィア・クレイドルは、2002年2月京都市にて、無限の可能性を秘めたソフトウェア職人たちが楽しく集い、自ずと自己実現が達成される場になることを目指して創業。在籍スタッフの平均年齢は20代前半と若いが、その大半がプログラミング歴10年以上とそのプロフェッショナリティは極めて濃い集団である。

 これまでにBREW用アプリケーションフレームワークケータイJavaプログラム圧縮技術ケータイJavaブラウザ技術、ケータイメッセンジャー技術などを総合的に研究開発し、「高品質な共通プラットフォーム」の実現を目指してきた。

ご感想、ご質問はこちら(zdnet-contact@s-cradle.com)まで。



関連記事
▼ BREW プログラミング入門(6):ビットマップを描画してみよう
前回はイベント処理について解説しました。今回はファイルやリソースに関する事柄とビットマップやイメージの描画について解説します。

▼ BREW プログラミング入門(5):イベント処理って何だ?
前回は文字列の扱い方について解説しました。今回はBREWのイベント処理について学びます。

▼ BREW プログラミング入門(4):BREW の文字列について知ろう
前回は画面描画のAPI、インタフェースやアプレット構造体についての理解を深めました。今回は文字列の扱い方について解説します。

▼ BREW プログラミング入門(3):画面に描画をしてみよう
前回の連載では、HelloWorldアプレットを作成することで、BREWアプリケーションのおおまかな構造について学びました。今回は画面描画のAPIについて詳しく説明するとともに、インタフェースやアプレット構造体についての理解を深めます。

▼ BREW プログラミング入門(2):“HelloWorld”プログラムを作ろう
前回の連載では、BREW SDK 2.1をインストールするところまで解説しました。今回は実際にソースコードを書き、BREWエミュレータで動かしてみましょう。画面に "Hello World" と表示する簡単なBREWアプリを作成します。

▼ BREW プログラミング入門(1):BREW SDKをインストールしよう
本連載は、BREWに興味がありプログラミングを始めてみたいけれど、どこから手をつけてよいか分からない方々を対象に、ステップ・バイ・ステップでBREWプログラミングを行う方法を解説していきます

▼ Qualcomm、携帯電話向けプラットフォーム「BREW」発表──au端末に搭載
▼ “携帯電話のOS”を目指すBREW──国内でも1号機
▼ BREWとは何か?──Javaとの違い
▼ 連載バックナンバー

[堀口淳史, ITmedia]

Copyright © ITmedia, Inc. All Rights Reserved.

前のページ | 2/2 | 最初のページ



モバイルショップ

最新CPU搭載パソコンはドスパラで!!
第3世代インテルCoreプロセッサー搭載PC ドスパラはスピード出荷でお届けします!!

最新スペック搭載ゲームパソコン
高性能でゲームが快適なのは
ドスパラゲームパソコンガレリア!