2009-03-28 37 views
1

私はWinSock接続を使用して、加速度計情報とiPhoneを取得し、Direct3Dアプリケーションに取り込みます。私はApples GLGravityのサンプルコードを変更して、ヘリコプターを重力に関して動かすようにしましたが、ヘリコプターが逆さまに飛べないように動きを「キャップ」する必要があります。私は加速度計の出力を制限しようとしましたDirect3D&iPhone Accelerometer Matrix

if (y < -0.38f) { 
    y = -0.38f; 
} 

これはうまくいきません!私が考えることができるのは、カスタムマトリクスを変更する必要があることだけですが、変更する必要があるものの周りに頭を浮かべているようには見えません。行列は以下のコードです。

_x = acceleration.x; 
_y = acceleration.y; 
_z = acceleration.z; 

float length; 
D3DXMATRIX matrix, t; 

memset(matrix, '\0', sizeof(matrix)); 

D3DXMatrixIdentity(&matrix); 

// Make sure acceleration value is big enough. 
length = sqrtf(_x * _x + _y * _y + _z * _z); 

if (length >= 0.1f && kInFlight == TRUE) { // We have a acceleration value good enough to work with. 
    matrix._44 = 1.0f; // 

    // First matrix column is a gravity vector. 
    matrix._11 = _x/length; 
    matrix._12 = _y/length; 
    matrix._13 = _z/length; 

    // Second matrix is arbitrary vector in the plane perpendicular to the gravity vector {Gx, Gy, Gz}. 
    // defined by the equation Gx * x + Gy * y + Gz * z = 0 in which we set x = 0 and y = 1. 
    matrix._21 = 0.0f; 
    matrix._22 = 1.0f; 
    matrix._23 = -_y/_z; 
    length = sqrtf(matrix._21 * matrix._21 + matrix._22 * matrix._22 + matrix._23 * matrix._23); 
    matrix._21 /= length; 
    matrix._22 /= length; 
    matrix._23 /= length; 

    // Set third matrix column as a cross product of the first two. 
    matrix._31 = matrix._12 * matrix._23 - matrix._13 * matrix._22; 
    matrix._32 = matrix._21 * matrix._13 - matrix._23 * matrix._11; 
    matrix._33 = matrix._11 * matrix._22 - matrix._12 * matrix._21; 
} 

誰でも助けていただければ幸いです。

+0

あなたは今どのような行動をしていますか? – bayda

+0

iphoneのdirectxですか? – hhafez

+0

いいえ、私は彼が制御装置のようにiphoneを使用したと思います – bayda

答えて

0

最初に加速度ベクトルを正規化してみてください。

0

これを正しく理解すれば、iPhoneはあなたに加速度計を供給しています(私の答えを削除するにはどうすればよいですか?あなたがiPhoneを3軸で動かすのがいかに難しいかを示すデータ。

私はそのリンゴのサンプルに精通していないので、私はそれが何をしているのか分かりません。しかし、あなたは方向付けに直接的に加速をマッピングしているように思えますが、あなたがしたいことは、ヘリコプターを方向付けるために位置を取得し位置の変化を見るために加速を二重に統合することだと思います。基本的に、これはDirect3Dの問題よりも物理的な問題のほうが多いです。

0

携帯電話からの加速度ベクトルを使用して、直交座標系の1つの軸を定義しているようです。そして、私は+ Yが地面の点であると仮定して、ベクトルが空を指している場合を心配しています。

iphoneが{0、-6.0、0}を報告した場合を考えてみましょう。このベクトルを{0、-.38、0}に変更します。しかし、それらは共に{0、-1.0、0}に正規化されます。したがって、-38°のyをクランプする効果は、ベクトルの他の2つの成分の大きさによって影響を受ける。

あなたが本当に望むのは、Yが負のときにベクトルの角度をXZ平面に限定することです。

Yが負の場合、XZ平面に対して30度以下に制限したいとします。最初にベクトルを正規化してください:

const float limitAngle = 30.f * PI/180.f; // angle in radians 
const float sinLimitAngle = sinf(limitAngle); 
const float XZLimitLength = sqrtf(1-sinLimitAngle*sinLimitAngle); 

if (_y < -sinLimitAngle) 
{ 
    _y = -sinLimitAngle; 
    float XZlengthScale = XZLimitLength/sqrtf(_x*_x + _z*_z); 
    _x *= XZlengthScale; 
    _z *= XZlengthScale; 
} 
+0

また、_xと_zがゼロの場合もこのケースを処理する必要があります。最も単純なのは、おそらく最良ではありませんが、ベクトル_x = XZLimitLength、_y = -sinLimitAngle、_z = 0を選択することです。 –

+0

また、電話機のように仮想ヘリコプターを移動しようとしている場合は、全体のアプローチは間違っています。 –

1

私は二重積分は多分複雑すぎると考えています。私が問題を正しく理解すれば、iPhoneは加速度計の値のベクトルをあなたに与えてくれます。ユーザがそれを振っていないと仮定すると、そのベクトルはほぼ一定の長さであり、重力で直接下方を指している。

これには大きな問題が1つあります。これは、ユーザーが水平方向に電話機を回すタイミングを知らせることができないことです。テーブルの上に携帯電話を置いて、自分の前に座っているときに、下を向いていると想像してください。重力ベクトルは(0、-1,0)となる。今、あなたの電話を90度回転させて、底面が左に向いているようにしますが、テーブルの上にはまだ平らです。重力ベクトルはまだ(0、-1,0)になります。しかし、あなたは本当にあなたのヘリコプターが電話で回ってほしいと思っています。 iPhoneには2D加速度計しか搭載されておらず、3D重力ベクトルを外挿するという基本的な制限があります。

だから、そのように自分の電話機を回転させることは許されておらず、一番下の位置に置いておく必要があるとユーザに伝えたとします。それは大丈夫です、あなたはまだそれから多くのコントロールを得ることができます。

次に、ヘリコプターがその側を90度以上超えないように入力を制限する必要があります。あなたの携帯電話に付いているスティックであり、重力にぶら下がっているとしているベクトルを想像してみてください。あなたが持っているベクトルは、電話機の平らな面に対する重力の方向を表しています。それが(0、-1、0)の場合は、スティックが直接下方(-y)を指しています。 (1、0、0)の場合、スティックは電話機の右側(+ x)​​を指していて、電話機が時計回りに90度ねじられていることを示しています。

このメタファーでは、スティックが完全な回転自由度を持っていると仮定します。それは電話からどの方向に向いていてもかまいません。スティックを動かすと、球の表面が描かれます。しかし、重要なことは、スティックがその球の下半分の周りを移動できることだけです。スティックが球体の上半分にあるようにユーザが電話機をねじった場合、球体の赤道のまわりのどこかを指しているようにスティックをキャップしたいとします。

極座標を使用すると、これをきれいに行うことができます。 3Dベクトルと極座標は交換可能です。情報を失うことなく変換できます。

あなたが持っているベクトルを(もちろん正規化した)3次元極座標セットに変換します(このロジックをウェブ上で簡単に見つけることができるはずです)。これにより、水平面の周りの角度と垂直面の角度(原点からの距離 - 正規化されたベクトルの場合は1.0になります)が得られます。垂直角が正の場合、ベクトルは球の上半分にあり、負の値は下半分にあります。次に、垂直角を常に0以下になるようにキャップします(球の下半分にも同様に)。次に、水平方向と直角方向の角度を取り、それをベクトルに変換し直すことができます。

あなたが既に持っているマトリクスコードに接続されている場合、この新しいベクトルは、必要な動きの範囲に限られた正しい向きを与えます。また、ユーザーが設定した制限を超えずに、指向ベクトルをユーザーの現在の向きにできるだけ近い状態に保ちます。