WindowsMobile」カテゴリーアーカイブ

WindowsMobile touchkeysip v1.10 加速センサーで文字入力

WindowsMobile 用のソフトウエアキーボード touchkeysip に、
前から考えていた機能をいくつか追加しました。

ダウンロード
touchkeysip v1.10

●加速センサー対応

加速センサーに対応した専用バージョン touchkeysip GS をリリースしました。
アーカイブやインストーラを標準版と分けてあります。

Script 内でセンサー値を直接受け取ることが出来ます。
サンプル gsensorsip では本体を傾けることで画像をスクロールしているだけですが、
本体を傾ける向きで 日本語、英数、記号などの入力パネルを切り替えたり、
カーソルを移動させるといった応用も考えられます。
本体のアクションをきちんと処理するのは難しいですが、Script 処理次第では
何らかの動作で文字入力することも出来るかもしれません。

●ステータス領域のアイコン画像の切り替え

標準の SIP だと「あ」「A」など入力文字の状態が表示されているエリアです。
あらかじめ作成したアイコン画像を用意しておけば、状態に合わせて表示を切り替える
ことが出来るようになりました。

またキーボードをデザインした人が touchkeysip ではなく自前のアイコンを表示
したい、といった用途にも使えます。

●管理可能な画像を増量

アイコン表示追加に伴い、複数枚の画像の読み込みにきちんと対応しました。
従来は 2枚まで読み込めましたが、DisplayList に使えないなど中途半端な実装でした。
8 枚まで読み込めてかつ表示やステータスアイコンとして利用できます。
でも表示するデータはできるだけ 1枚にまとめた方が処理は高速だと思われます。

●タイマーの追加

加速センサー対応によって、従来のキーリピートとは別にポーリング用のタイマーが
必要となりました。よって複数のタイマー機能を使えるようにしています。
上限は容易に撤廃できますが API としてはとりあえず 4個まで。

●読み込める画像形式の追加

bmp 以外も読み込めるようになりました。jpeg など。
Script の命令自体は LoadBitmap のままです。
16bit RGB bitmap は直接読み込めないことがあるようです。

●サンプル

gsensorsip v1.00 はこれらの追加機能を実際に使用しています。
実用性は全く無く、あくまで機能のテスト用です。

●注意点

機能の追加や変更が多いため、互換性など何らかの問題がある場合は旧バージョン
v1.09 等を使用してください。
制作時に動作テスト可能な機種や環境も限られるため、必ずしも完全にテストが
行われているわけではない点にご注意ください。

関連エントリ
HTC Touch Diamond タッチセンサー API
WindowsMobile touchkeysip v1.07
WindowsMobile touchkeysip / ctrlswapmini

HTC Touch Diamond で Direct3DMobile その(10) d3dmclock v1.10 3Dクロック 更新

メニューから任意の画像を読み込めるように変更しました。(前回)
対応フォーマットも大幅に増えて、任意サイズの画像を直接背景として登録できます。

d3dmclock HTC Touch Diamond
↑ Windows7 ぽい感じに・・

ダウンロードはこちら
d3dmclock v1.10 ダウンロードページ

WindowsMobile 用アプリです。

速度はだいたい 16~21fps 程度です。
速度は主に時間帯と背景テクスチャの解像度で変わります。
時間帯で速度が変化するのは、各数字モデルのポリゴン数が違うから。

1024×1024 に変換されてしまう大きな画像だともっと速度が落ちるかもしれません。
HTC Touch Diamond は VGA (640×480) なので、512×512 がちょうど良いくらいでしょう。
QVGA の端末ならもっと小さくて構いません。

Touch Diamond は 2.8インチで VGA (640×480) の解像度があるため、かなり密度が
高くきれいに見えます。輪郭のジャギも気にならないし、この密度でリアルタイムに
レンダリング出来てリアルタイムに動いているのだから十分かもしれません。
blog のキャプチャは 1/4 に縮小しています。

WindowsMobile だと、せっかく載っている 3Dアクセラレータがあんまり活用されていないのは
もったいないですね。

テクスチャの読み込みは、当初 Direct3DMobile D3DMX のテクスチャローダーを
そのまま使用していました。これ対応フォーマットは dds と bmp だけ。
しかも bmp は 16bpp を読み込めないことがわかりました。
さらに 2の n乗以外のサイズも読み込めるけど固まったかと思うくらい低速です。

テクスチャローダーを作り直しました。
参考にしたのは WindowsMobile6.0 SDK サンプル
Windows Mobile 6 SDK\Samples\Common\CPP\Win32\Imaging

これで bmp だけでなく jpeg や png 、gif などメジャーなものはたいてい
読み込めるようになりました。しかも速いです。

流れは次の通り

(1) IImage として画像を読み込む
(2) IBitmapImage に変換する
(3) LockBits() してピクセル情報にアクセス
(4) SystemMemory の Surface (CreateImageSurface()) に格納する
(5) CreateTexture()
(6) Texture から Surface を取り出す。
(7) (6) の Surface に (4) の Surface をコピーして vram に転送
(8) テンポラリリソースとインターフェースを Release

#include  

// interface 取得
IImagingFactory*	iImageFactory= NULL;
CoCreateInstance( CLSID_ImagingFactory, NULL, CLSCTX_INPROC_SERVER,
			IID_IImagingFactory, &iImageFactory );
// ファイル読み込み
IImage*	iImage= NULL;
iImageFactory->CreateImageFromFile( file, &iImage );

ImageInfo	info;
iImage->GetImageInfo( &info );
int	w= info.Width;
int	h= info.Height;

// bitmap に変換
IBitmapImage*	iBitmap= NULL;
iImageFactory->CreateBitmapFromImage( iImage, w, h,
	PixelFormat24bppRGB, InterpolationHintDefault, &iBitmap );

iImage->Release();
iImageFactory->Release();

// lock
static BitmapData	lockdata;
iBitmap->LockBits( NULL, ImageLockModeRead, PixelFormat24bppRGB, &lockdata );

lockdata.Width;
lockdata.Height;
lockdata.Stride;
lockdata.Scan0;

// texture を作成
IDirect3DMobileTexture*	iTexture= NULL;
CreateTexture( w, h, 1, 0, D3DMFMT_R5G6B5, GetTexturePool(), &iTexture );

// SystemMemory の surface を作成
IDirect3DMobileSurface*	iSurface= NULL;
CreateImageSurface( w, h, D3DMFMT_R5G6B5, &iSurface );

// 書き込み
D3DMLOCKED_RECT	dlock;
iSurface->LockRect( &dlock, NULL, 0 );
uintptr_t	di= reinterpret_cast( dlock.pBits );
for( int y= 0 ; y< h ; y++ ){
    unsigned short*	dp= reinterpret_cast( di );
    for( int x= 0 ; x< w ; x++ ){
        const unsigned char*	sp= image.GetXY( x, y );
        unsigned int	b= sp[0];
        unsigned int	g= sp[1];
        unsigned int	r= sp[2];
        *dp++= ((r<<8)&0xf800)|((g<<3)&0x07e0)|((b>>3)&0x001f);
    }
    di+= dlock.Pitch;
}
iSurface->UnlockRect();

// texture の surface を取り出す
IDirect3DMobileSurface*	iTexSurface= NULL;
iTexture->GetSurfaceLevel( 0, &iTexSurface );

// コピー
CopyRects( iSurface, iTexSurface );

iSurface->Release();
iTexSurface->Release();

// unlock
iBitmap->UnlockBits( &lockdata );
iBitmap->Release();

関連エントリ
HTC Touch Diamond で Direct3DMobile その(9) d3dmclock v1.00 3D クロック
HTC Touch Diamond で Direct3DMobile その(8) ノーマルマップの解説
HTC Touch Diamond で Direct3DMobile その(7) ノーマルマップを表示する
HTC Touch Diamond で Direct3DMobile その(6) 頂点性能続き
HTC Touch Diamond で Direct3DMobile その(5)
HTC Touch Diamond で Direct3DMobile その(4) 高速化
HTC Touch Diamond で Direct3DMobile その(3) 実際の頂点性能
HTC Touch Diamond で Direct3DMobile を使う。その (2)
HTC Touch Diamond で Direct3DMobile を使う。ハードウエアアクセラレータ

HTC Touch Diamond で Direct3DMobile その(9) d3dmclock v1.00 3D クロック

せっかくなのでもうちょっと実用的なやつを。
デジタル時計にしてみました。

d3dmclock

HTC Touch Diamond の加速センサーに対応したので、本体の傾きに合わせて画面が
スムーズに回転します。
意味もなく数字 1つ 1つがポリゴンです。

d3dmclock
↑数字が不揃いなのはバグではありません。

ダウンロードはこちら
d3dmclock v1.00

WindowsMobile6.0/6.1 で動作します。加速センサーが無くても起動します。
ただし 3Dアクセラレータがないと非常に低速です。
おそらく HTC Touch Diamond 系、Touch Pro 等で動作すると思われます。

加速センサー以外にも、画面タッチの左右で回転、上下でズームします。

d3dmclock

↑どんな角度にもなります。

背景画像は適当なので入れ替えて使ってください。
プログラムと同じフォルダに入っている bgimage0.bmp ~ bgimage2.bmp です。
サイズが 256×256 や 512×512 ならおそらく何でも大丈夫です。

textimage0.dds~textimage7.dds ファイルを置き換えれば、数字用のテクスチャも
入れ替えできます。こちらもサイズは 2の n乗で mipmap が必要です。
フォーマットは R5G6B5 にしてください。

Menu の Light にチェックを入れると、光源を操作できます。
この状態で画面をタッチすると、タッチした位置から画面中央に向かうベクトルを
光源の向きと見なします。

iPhone/iPod touch みたいにスムーズに動くものを、と思ったけどなかなか難しいですね。
Touch Diamond 系をお持ちの方はよろしければ一度お試しください。

関連エントリ
HTC Touch Diamond で Direct3DMobile その(8) ノーマルマップの解説
HTC Touch Diamond で Direct3DMobile その(7) ノーマルマップを表示する
HTC Touch Diamond で Direct3DMobile その(6) 頂点性能続き
HTC Touch Diamond で Direct3DMobile その(5)
HTC Touch Diamond で Direct3DMobile その(4) 高速化
HTC Touch Diamond で Direct3DMobile その(3) 実際の頂点性能
HTC Touch Diamond で Direct3DMobile を使う。その (2)
HTC Touch Diamond で Direct3DMobile を使う。ハードウエアアクセラレータ

HTC Touch Diamond タッチセンサー API

Touch Diamond には、触れただけで反応するタッチセンサーが付いています。
ボタンやカーソルキー周りがそうです。

このタッチセンサーの値を受け取るには HTCAPI.dll を呼び出します。
ウィンドウに関連付けされ、あとはモードを設定するだけでメッセージ (WM_USER~)
で通知が来るようです。
参考にさせていただいたのは加速度センサーの読み出し同様こちらです。

Scott’s Weblog Fun with the Diamond’s tilt sensor

タッチセンサーは左右に分かれており、それぞれ個別に座標値が取れます。

・中央のカーソルキーから左側、通話ボタンやホームボタン側
・中央のカーソルキーから右側、終了ボタンや ← (OK) ボタン側

座標値は左上が原点 (0,0) で、0~67 くらいの範囲。
ただし中央のカーソルキー周囲は回転のジェスチャーとして識別されるため座標が
取れません。

中央の決定ボタンは、座標が不正な範囲 (255,255) の状態で押されることで
判別できます。カメラのオートフォーカスで半押し状態がこれ。

タッチしたイベント (DOWN) と指を離したイベント (UP) が送られてくるだけで、
MOVE イベントがありません。押した座標、離した座標は取れますが、移動中の
イベントがないのでスライドによるスクロールなどには向いていないようです。

液晶面の感圧式タッチパネルだとスクロール等のスライドを指で行うのが
難しかったりするので、本当ならこちらのタッチセンサーでスクロールできたら
よかったのですが。

また左右のパネル両方同じイベント扱いなので、どちらかにタッチしてしまうと
DOWN 状態になります。座標は独立して取れるものの状態が共有なので、
マルチタッチのような使い方にも向いていないようです。

なお液晶面のタッチパネルとは別物なので、タッチボタンと液晶画面など別センサー
同士の同時タッチは可能です。

HTCNavClose() の引数は DWORD ではなく、HWND が正しいようです。
よって HTCNavSetMode() で与えた DWORD を Close() するのではなく、使い方としては
HTCNavOpen() に与えた HWND を指定して一度だけ Close() します。

中央の回転ジェスチャーは WM_USER + 200 だけでなく WM_USER + 201 にも何らかの
データが送られています。終了イベントのようですが、送られないこともあります。

いろいろ試したけど生の値が取れる方法はまだわかりません。
とりあえずボタン部分に触れただけで反応するような感度の良いアプリは作れると
思います。

同じ部分に指を置いても

(1) 触れる → タッチセンサー
(2) 押し込み → ボタン
(3) 触れたまま揺らす → 加速度センサー

といった使い分けもできるでしょう。

関連エントリ
HTC Touch Diamond のボタン部分とタッチセンサー
HTC Touch Diamond の加速センサー

HTC Touch Diamond の加速センサー

HTC Touch Diamond の加速センサーから値を読み出してみました。
参考にさせていただいたのは下記サイトのプログラムです。

Scott’s Weblog Fun with the Diamond’s tilt sensor

API は Touch Diamond に含まれている HTCSensorSDK.dll を呼び出しています。
取り出せる値は 3軸センサーのそれぞれの加速度 X Y Z。
ソースにはだいたい -1000~1000 程度の範囲で傾きと書かれていますが、
やはり重力加速度を表しているようです。
何もしない状態で ±1000 前後 (1G)。強く振ると ±2400 程度の値も取れます。

データの連続取得は 40msec 程度の間隔が必要です。
当初動かしたときは 1/30 や 1/60 sec でサンプリングしていたため、値が更新されず
少々悩みました。

使用しているセンサーはレジストリの DeviceVendor より Kionix KXSD9

direction=5  液晶背面方向 -Z
direction=4  液晶面方向   +Z
direction=1  左サイド     -X
direction=0  右サイド     +X
direction=2  下           +Y
direction=3  上           -Y

struct SENSORDATA {
    short   ax;
    short   ay;
    short   az;
    short   zero;
    int     AngleY;
    int     AngleX;
    int	    direction;
};

例えば机の上に水平に寝かせた状態だと、液晶背面方向が重力方向だから
az = -1000 前後に、direction が 5 になります。
SENSORDATA の最後の値はこのように、大まかな端末の向きをそのまま表して いるようです。
いるようです。
AngleX/AngleY はおそらく極座標か何かだと思いますが未調査。

関連エントリ
HTC Touch Diamond のボタン部分とタッチセンサー