2011/08/11
Android 3.1 と GamePad のイベントの詳細 (2)
引き続き Android OS 3.1 に Xbox360 Pad と Playstation3 Pad を
つないだ場合の値の取り方です。(前回)
アナログスティックの情報は onGenericMotionEvent で受け取れます。
入力値に差が生じた場合のみイベントが発生します。
getX()/getY() は getAxisValue() の AXIS_X, AXIS_Y と同値です。
対応付は下記の通り
Xbox360 Pad のみ、デジタル方向ボタン(十字キー) が MotionEvent の
AXIS_HAT_X/AXIS_HAT_Y を返します。(KeyEvent も発生します)
他にも MotionEvent と同時に KeyEvent を発生させるものがあります。
●デジタル方向キーとアナログスティックの区別方法
ここで問題となるのは、左アナログスティックで MotionEvent だけでなく
KeyEvent も発生してしまうことです。
デジタル方向ボタンの代わりに左アナログスティックを使うことができる反面、
アナログとデジタルに異なる操作を割り当てたいときに困ります。
KeyCode だけではこの両者を区別できないので方法を探しました。
Xbox360 Pad の方向キーは AXIS_HAT_X/AXIS_HAT_Y からも値をとれるため
KeyEvent を参照せずにこちらを使えば区別することができます。
PS3 Pad の場合は SOURCE_CLASS で区別できるようです。
訂正 2011/08/11 不要でした。Xbox360 のみ AXIS → KeyCode 変換だけで OK です。
PS3 のみデジタル方向キーが SOURCE_CLASS_BUTTON となります。
実際のコード(Activity 抜粋)は下記の通り。
これで Xbox360 Pad / PS3 Pad 共に、デジタル方向ボタンを
KEYCODE_DPAD_UP/DOWN/LEFT/RIGHT を受け取れるようになります。
(プログラムコード訂正しました 2011/08/11 )
●複数のパッドの認識
USB ハブを経由して、同時に複数のコントローラを接続することができました。
どのコントローラも上記の同じイベントを発生させます。
getDeviceId() を参照することで、どのコントローラが送ったイベントなのか
区別できるようです。
Xbox360 Pad と PS3 Pad の組み合わせは OK、PS3 Pad を同時に 2個つないでも
きちんと区別できました。バスパワーハブだったため 3個以上は試していません。
● Playstation3 Pad (PS3 Pad) の注意点
PS3 Pad はもともとワイヤレスコントローラですが、Android 3.1 の場合
USB ケーブルで繋ぎます。
1. PS3 Pad が電源 OFF の状態を確認
2. USB ケーブルで Android 3.1 端末に繋ぐ
3. (PS) ボタンを押す
4. LED 4つが点滅したままだけど問題なし。そのまま使える。
接続前に (PS) ボタンを押してしまうとペアリングしてある PS3 本体の
電源が入ってしまうので要注意です。
ワイヤレスで PS3 本体につながってしまうと USB ケーブルをつないでも
PS3 が優先され Android で認識できません。
最初の頃、遠くにある PS3 本体の電源がいつの間にか入っていて、
なかなかつながらずにはまりました。
関連エントリ
・Android 3.1 と GamePad のイベントコード
つないだ場合の値の取り方です。(前回)
アナログスティックの情報は onGenericMotionEvent で受け取れます。
@Override public boolean onGenericMotionEvent( MotionEvent event ) { float posx= event.getAxisValue( MotionEvent.AXIS_X ); ~ }
入力値に差が生じた場合のみイベントが発生します。
getX()/getY() は getAxisValue() の AXIS_X, AXIS_Y と同値です。
対応付は下記の通り
axis Xbox360Pad PS3 Pad 範囲 Source ----------------------------------------------------------------------- AXIS_X 左stick 横 左stick 横 -1~1 SOURCE_CLASS_JOYSTICK AXIS_Y 左stick 縦 左stick 縦 -1~1 SOURCE_CLASS_JOYSTICK AXIS_Z 右stick 横 右stick 横 -1~1 SOURCE_CLASS_JOYSTICK AXIS_RZ 右stick 縦 右stick 縦 -1~1 SOURCE_CLASS_JOYSTICK AXIS_HAT_X 十字キー横 ---- -1~1 SOURCE_CLASS_JOYSTICK AXIS_HAT_Y 十字キー縦 ---- -1~1 SOURCE_CLASS_JOYSTICK AXIS_LTRIGGER Lトリガ L2 0~1 AXIS_RTRIGGER Rトリガ R2 0~1 左上が (-1,-1), 右下が (1,1)
Xbox360 Pad のみ、デジタル方向ボタン(十字キー) が MotionEvent の
AXIS_HAT_X/AXIS_HAT_Y を返します。(KeyEvent も発生します)
他にも MotionEvent と同時に KeyEvent を発生させるものがあります。
◎Xbox360 Pad / PS3 Pad ・AXIS_X KEYCODE_DPAD_LEFT/KEYCODE_DPAD_RIGHT ・AXIS_Y KEYCODE_DPAD_UP/KEYCODE_DPAD_DOWN ◎PS3 Pad のみ ・AXIS_LTRIGGER KEYCODE_L2 ・AXIS_RTRIGGER KEYCODE_R2 ◎Xbox360 Pad のみ ・AXIS_HAT_X KEYCODE_DPAD_LEFT/KEYCODE_DPAD_RIGHT ・AXIS_HAT_Y KEYCODE_DPAD_UP/KEYCODE_DPAD_DOWN
●デジタル方向キーとアナログスティックの区別方法
KeyEvent も発生してしまうことです。
デジタル方向ボタンの代わりに左アナログスティックを使うことができる反面、
アナログとデジタルに異なる操作を割り当てたいときに困ります。
KeyEvent を参照せずにこちらを使えば区別することができます。
訂正 2011/08/11 不要でした。Xbox360 のみ AXIS → KeyCode 変換だけで OK です。
KeyEvent.getSource() & InputDevice.SOURCE_CLASS_MASK
PS3 のみデジタル方向キーが SOURCE_CLASS_BUTTON となります。
◎KeyEvent の SOURCE_CLASS 値 Xbox360 Pad PS3 Pad -------------------------------------------------------------------- デジタル方向キー SOURCE_CLASS_JOYSTICK SOURCE_CLASS_BUTTON アナログ方向キー SOURCE_CLASS_JOYSTICK SOURCE_CLASS_JOYSTICK ◎MotionEvent の情報 Xbox360 Pad PS3 Pad -------------------------------------------------------------------- デジタル方向キー AXIS_HAT_X/AXIS_HAT_Y 無し アナログ方向キー AXIS_X/AXIS_Y AXIS_X/AXIS_Y
実際のコード(Activity 抜粋)は下記の通り。
これで Xbox360 Pad / PS3 Pad 共に、デジタル方向ボタンを
KEYCODE_DPAD_UP/DOWN/LEFT/RIGHT を受け取れるようになります。
(プログラムコード訂正しました 2011/08/11 )
final static int SENDKEY_UP = 0; final static int SENDKEY_DOWN = 1; private int mPrevState= 0; private boolean sendKey( int KeyCode, int up_down ) { // 実際のキーコード処理 ~ } @Override public boolean onKeyDown( int KeyCode, KeyEvent event ) { return sendKey( KeyCode, SENDKEY_DOWN ); } @Override public boolean onKeyUp( int KeyCode, KeyEvent event ) { return sendKey( KeyCode, SENDKEY_UP ); } @Override public boolean onGenericMotionEvent( MotionEvent event ) { // Xbox360 の 十字キーはこれで判別 final int KEYFLAG_UP = (1<<0); final int KEYFLAG_DOWN = (1<<1); final int KEYFLAG_LEFT = (1<<2); final int KEYFLAG_RIGHT = (1<<3); final float HAT_BORDER= 0.5f; float hatx= event.getAxisValue( MotionEvent.AXIS_HAT_X ); float haty= event.getAxisValue( MotionEvent.AXIS_HAT_Y ); int code= 0; if( hatx < -HAT_BORDER ){ code|= KEYFLAG_LEFT; } if( hatx > HAT_BORDER ){ code|= KEYFLAG_RIGHT; } if( haty < -HAT_BORDER ){ code|= KEYFLAG_UP; } if( haty > HAT_BORDER ){ code|= KEYFLAG_DOWN; } int diff= code ^ mPrevState; mPrevState= code; for( int kc= KeyEvent.KEYCODE_DPAD_UP ; diff != 0 ; diff>>= 1, code>>= 1, kc++ ){ if( (diff & 1) != 0 ){ // 代わりのキーコードを発生させる sendKey( kc, (code & 1) != 0 ? SENDKEY_DOWN : SENDKEY_UP ); } } // アナログ値の受け取り float lx= event.getAxisValue( MotionEvent.AXIS_X ); float ly= event.getAxisValue( MotionEvent.AXIS_Y ); float rx= event.getAxisValue( MotionEvent.AXIS_Z ); float ry= event.getAxisValue( MotionEvent.AXIS_RZ ); float tl= event.getAxisValue( MotionEvent.AXIS_LTRIGGER ); float tr= event.getAxisValue( MotionEvent.AXIS_RTRIGGER ); ~ }
●複数のパッドの認識
USB ハブを経由して、同時に複数のコントローラを接続することができました。
どのコントローラも上記の同じイベントを発生させます。
getDeviceId() を参照することで、どのコントローラが送ったイベントなのか
区別できるようです。
Xbox360 Pad と PS3 Pad の組み合わせは OK、PS3 Pad を同時に 2個つないでも
きちんと区別できました。バスパワーハブだったため 3個以上は試していません。
● Playstation3 Pad (PS3 Pad) の注意点
PS3 Pad はもともとワイヤレスコントローラですが、Android 3.1 の場合
USB ケーブルで繋ぎます。
1. PS3 Pad が電源 OFF の状態を確認
2. USB ケーブルで Android 3.1 端末に繋ぐ
3. (PS) ボタンを押す
4. LED 4つが点滅したままだけど問題なし。そのまま使える。
接続前に (PS) ボタンを押してしまうとペアリングしてある PS3 本体の
電源が入ってしまうので要注意です。
ワイヤレスで PS3 本体につながってしまうと USB ケーブルをつないでも
PS3 が優先され Android で認識できません。
最初の頃、遠くにある PS3 本体の電源がいつの間にか入っていて、
なかなかつながらずにはまりました。
関連エントリ
・Android 3.1 と GamePad のイベントコード
2011/08/10
Android 3.1 と GamePad のイベントコード
Acer ICONIA TAB A500 が Android OS 3.1 になったので早速つないでみました。
Android 3.1 からは USB でゲームパッドがつながります。
・Xbox 360 用の USB コントローラ
・Playstation3 用コントローラを USB (有線)接続
どちらもきちんと認識しました。
判定の仕方は下記のとおりです。
ボタン類は通常のキーボードと同じ、onKey~ でキーコードとして通知されます。
十字キーはカーソルキーと同じ KEYCODE_DPAD_UP/DOWN/LEFT/RIGHT
(19~22) です。
そのため取り敢えずつないだけでも HOME 画面などでカーソル移動に使えます。
未確認ですが、おそらく KeyEvent.isGamepadButton() で本来のカーソルキーと
区別できると思われます。 訂正2011/08/10 13:22
ボタン類は専用のキーコード(96~)が割り当てられているようです。
Xbox360 と PS3 ほぼ上記のキーアサイン通りなのですが微妙に互換性がありません。
BUTTON_X は 360 だと (X) ボタンで PS3 は (×) バツボタンです。
AB/XY が入れ替わっているような感じです。
360 Pad 中央の Xbox ボタンは KEYCODE_BUTTON_MODE ですが、
PS ボタンは異なる数値 (188) でした。
アナログ操作は onGenericMotionEvent で MotionEvent が来ます。
L/Rトリガは 360 は MotionEvent だけですが PS3 だと
MotionEvent + BUTTON_L2/R2 の両方が返るようです。
もう少し調査が必要ですが、取り敢えず PC 等と操作方法の
互換性が保てるので便利になりそうです。
Android 3.1 からは USB でゲームパッドがつながります。
・Xbox 360 用の USB コントローラ
・Playstation3 用コントローラを USB (有線)接続
どちらもきちんと認識しました。
判定の仕方は下記のとおりです。
ボタン類は通常のキーボードと同じ、onKey~ でキーコードとして通知されます。
十字キーはカーソルキーと同じ KEYCODE_DPAD_UP/DOWN/LEFT/RIGHT
(19~22) です。
そのため取り敢えずつないだけでも HOME 画面などでカーソル移動に使えます。
区別できると思われます。
ボタン類は専用のキーコード(96~)が割り当てられているようです。
KEYCODE_BUTTON_A 96 □ KEYCODE_BUTTON_B 97 △ KEYCODE_BUTTON_C 98 KEYCODE_BUTTON_X 99 × KEYCODE_BUTTON_Y 100 ◯ KEYCODE_BUTTON_Z 101 KEYCODE_BUTTON_L1 102 KEYCODE_BUTTON_R1 103 KEYCODE_BUTTON_L2 104 KEYCODE_BUTTON_R2 105 KEYCODE_BUTTON_THUMBL 106 KEYCODE_BUTTON_THUMBR 107 KEYCODE_BUTTON_START 108 KEYCODE_BUTTON_SELECT 109 (BACK) KEYCODE_BUTTON_MODE 110 (Xbox) 188 (PS)
Xbox360 と PS3 ほぼ上記のキーアサイン通りなのですが微妙に互換性がありません。
BUTTON_X は 360 だと (X) ボタンで PS3 は (×) バツボタンです。
AB/XY が入れ替わっているような感じです。
360 Pad 中央の Xbox ボタンは KEYCODE_BUTTON_MODE ですが、
PS ボタンは異なる数値 (188) でした。
アナログ操作は onGenericMotionEvent で MotionEvent が来ます。
L/Rトリガは 360 は MotionEvent だけですが PS3 だと
MotionEvent + BUTTON_L2/R2 の両方が返るようです。
もう少し調査が必要ですが、取り敢えず PC 等と操作方法の
互換性が保てるので便利になりそうです。
2011/08/07
Android Galaxy S2 ARM Mali-400 MP は速い (2)
そこそこ複雑なシーンでの比較。
そこそこの背景+キャラ描画に Shadow map ありの数値です。
TBR だし OpenGL ES 2.0 では Shadow map は現実的ではないと
思ってましたが Mali だと十分できそうです。
影なしだと全体的に数値が上がり、Mali はほとんど 60fps 固定。
PVR 対策で alpha test は off。
圧縮テクスチャ次第ではもう少し差が縮まるかもしれません。
Tegra2 は解像度が異なり近い条件での比較ができませんでした。
Tegra2 には depth texture がありませんが、代わりに half float
の color buffer を使っています。
・GL ES Extension 一覧
関連エントリ
・Android Galaxy S2 ARM Mali-400 MP
Mali-400MP 800x480 : 50fps Adreno 205 854x480 : 20fps Adreno 200 800x480 : 5fps PVR SGX540 800x480 : 23fps
そこそこの背景+キャラ描画に Shadow map ありの数値です。
TBR だし OpenGL ES 2.0 では Shadow map は現実的ではないと
思ってましたが Mali だと十分できそうです。
影なしだと全体的に数値が上がり、Mali はほとんど 60fps 固定。
PVR 対策で alpha test は off。
圧縮テクスチャ次第ではもう少し差が縮まるかもしれません。
Tegra2 は解像度が異なり近い条件での比較ができませんでした。
Tegra2 には depth texture がありませんが、代わりに half float
の color buffer を使っています。
if( Extension("GL_OES_depth_texture") ){ ~ }else if( Extension("GL_OES_texture_half_float") ){ // Tegra250 glGenTextures( 1, &gShadowTexture ); glBindTexture( GL_TEXTURE_2D, gShadowTexture ); glTexImage2D( GL_TEXTURE_2D, 0, GL_LUMINANCE, width, height, 0, GL_LUMINANCE, GL_HALF_FLOAT_OES, NULL ); glGenRenderbuffers( 1, &gShadowDepth ); glBindRenderbuffer( GL_RENDERBUFFER, gShadowDepth ); glRenderbufferStorage( GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, height ); glGenFramebuffers( 1, &gShadowTarget ); glBindFramebuffer( GL_FRAMEBUFFER, gShadowTarget ); glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, gShadowTexture, 0 ); glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, gShadowDepth ); }
・GL ES Extension 一覧
関連エントリ
・Android Galaxy S2 ARM Mali-400 MP
2011/08/05
Android Galaxy S2 ARM Mali-400 MP
ベンチは走らせてませんが 3D 描画は速い。
今まで試した Android の中では最速でした。
● GPU
Unified でなく unit が独立しているせいもあるかもしれませんが、
比較的長い pixel shader も意外なほど動きます。
その代わり extension は少な目です。
・Mobile GPU の比較
float 系テクスチャや圧縮頂点フォーマットが無いようです。
また圧縮テクスチャが ETC1 だけに制限されるのも、他の GPU との
大きな違いとなっています。
今の Mobile GPU はそれぞれ何かしらのトレードオフがあり全部入りはありません。
例えば Adreno 200 は演算ユニットが高精度固定、Unified で頂点機能も豊富、
低帯域対策は TBR と ATITC。その代わり頂点キャッシュなし。
PVR SGX535 は TBDR + PVRTC で全体的なスループットが高いがシェーダーの
演算精度をどこまで落とせるかが最適化の要。
Tegra2 は TBR でない代わりに転送量削減で 16bit depth 固定など。
Mali-400MP はまた違った特徴を持っているようです。
● CPU
Cortex-A9 1.2GHz dual。iPad2 同様 neon ありです。
今まで触ったハードで A9 neon 無しは Tegra2 だけでした。
モバイルでの 3D ゲームも現実的なレベルだと思います。
デスクトップ GPU との差はまだまだですが、意外にすぐ追いつかれるかも
しれません。
関連エントリ
・iPad2 A5 と浮動小数演算 VFP/NEON
・Android OpenGL ES 2.0 の圧縮テクスチャ
・Tegra2 Cortex-A9 と浮動小数演算
・Snapdragon と浮動小数演算速度
今まで試した Android の中では最速でした。
● GPU
GL_VERSION: OpenGL ES 2.0 GL_RENDERER: Mali-400 MP GL_VENDOR: ARM GL_SHADING_LANGUAGE_VERSION: OpenGL ES GLSL ES 1.00 [GL_OES_texture_npot] [GL_OES_compressed_ETC1_RGB8_texture] [GL_OES_standard_derivatives] [GL_OES_EGL_image] [GL_OES_depth24] [GL_ARM_rgba8] [GL_ARM_mali_shader_binary] [GL_OES_depth_texture] [GL_OES_packed_depth_stencil] API=0 Shader=100 pconst=1024 vconst=128 vin=16 vout=12 ptex=8 vtex=0 combotex=8 maxrender=4096 maxtexsize=4096 cubetexsize=1024 viewdims=4096 TextureFormat 1 tc[00]=8d64 GL_ETC1_RGB8_OES
Unified でなく unit が独立しているせいもあるかもしれませんが、
比較的長い pixel shader も意外なほど動きます。
その代わり extension は少な目です。
・Mobile GPU の比較
float 系テクスチャや圧縮頂点フォーマットが無いようです。
また圧縮テクスチャが ETC1 だけに制限されるのも、他の GPU との
大きな違いとなっています。
今の Mobile GPU はそれぞれ何かしらのトレードオフがあり全部入りはありません。
例えば Adreno 200 は演算ユニットが高精度固定、Unified で頂点機能も豊富、
低帯域対策は TBR と ATITC。その代わり頂点キャッシュなし。
PVR SGX535 は TBDR + PVRTC で全体的なスループットが高いがシェーダーの
演算精度をどこまで落とせるかが最適化の要。
Tegra2 は TBR でない代わりに転送量削減で 16bit depth 固定など。
Mali-400MP はまた違った特徴を持っているようです。
● CPU
Cortex-A9 1.2GHz dual。iPad2 同様 neon ありです。
今まで触ったハードで A9 neon 無しは Tegra2 だけでした。
Processor : ARMv7 Processor rev 1 (v7l) processor : 0 BogoMIPS : 1592.52 processor : 1 BogoMIPS : 1592.52 Features : swp half thumb fastmult vfp edsp neon vfpv3 CPU implementer : 0x41 CPU architecture: 7 CPU variant : 0x2 CPU part : 0xc09 CPU revision : 1
モバイルでの 3D ゲームも現実的なレベルだと思います。
デスクトップ GPU との差はまだまだですが、意外にすぐ追いつかれるかも
しれません。
関連エントリ
・iPad2 A5 と浮動小数演算 VFP/NEON
・Android OpenGL ES 2.0 の圧縮テクスチャ
・Tegra2 Cortex-A9 と浮動小数演算
・Snapdragon と浮動小数演算速度