1

WinSock 接続を使用して、加速度計情報をオフにし、iPhone を Direct3D アプリケーションに取り込みます。Apples GLGravity のサンプル コードを修正して、ヘリコプタが重力に関連して動くようにしました。私はそのように加速度計の出力を制限しようとしました

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;
}

誰かが助けることができれば、それは大歓迎です!

4

4 に答える 4

1

二重積分はおそらく物事を複雑にしすぎていると思います。私が問題を正しく理解していれば、iPhoneは加速度計からの値のベクトルを提供しています。ユーザーがそれを振り回していないと仮定すると、そのベクトルはほぼ一定の長さであり、重力で真下を向いています。

これには大きな問題が1つあります。それは、ユーザーがいつ電話を水平方向に回転させたかがわからないことです。あなたがテーブルの上にあなたの電話を置いて、あなたがそれの前に座っているときに底があなたに面していると想像してください。重力ベクトルは(0、-1、0)になります。次に、スマートフォンを約90度回転させて、底面が左を向くようにしますが、テーブル上では平らになります。重力ベクトルは引き続き(0、-1、0)になります。しかし、あなたは本当にあなたのヘリコプターが電話で向きを変えて欲しいと思うでしょう。これは、iPhoneに2D加速度計しかないという事実の基本的な制限であり、そこから3D重力ベクトルを外挿しています。

それで、あなたがユーザーにそのように彼らの電話を回転させることは許されないことをあなたが言ったと仮定しましょう、そして彼らはあなたに一番下のポイントでそれを維持しなければなりません。それは結構です、あなたはまだそれから多くのコントロールを得ることができます。

次に、ヘリコプターの側面が90度を超えないように、入力に上限を設定する必要があります。あなたがあなたの電話に取り付けられた棒であり、重力でぶら下がっているとしてあなたが与えられたベクトルを想像してみてください。あなたが持っているベクトルは、電話の平らな面を基準にした重力の方向を表しています。(0、-1、0)の場合、スティックは真下(-y)を指しています。(1、0、0)の場合、スティックは電話の右側(+ x)​​を指しており、電話が時計回りに90度ねじれていることを意味します(電話を見てあなたから離れている)。

この比喩では、スティックに完全な回転の自由があると仮定します。それは電話から任意の方向を指している可能性があります。したがって、スティックを動かすと、球の表面がわかります。しかし重要なのは、スティックがその球の下半分の周りを移動できるようにすることだけです。スティックが球の上半分にくるようにユーザーが電話をひねる場合は、球の赤道の周りのどこかを指すようにキャップを付ける必要があります。

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

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

この新しいベクトルは、すでに持っているマトリックスコードに接続されている場合、必要な可動域に制限された正しい方向を示します。また、ユーザーが電話を90度のマークをわずかに超えて回しても安定します。このロジックにより、設定した制限を超えることなく、方向ベクトルがユーザーの現在の方向にできるだけ近くなります。

于 2009-08-28T21:26:16.753 に答える
0

最初に加速度ベクトルを正規化してみてください。(編集:長さを確認した後)(編集編集:読み方を学ぶ必要があると思います...答えを削除するにはどうすればよいですか?)

于 2009-06-25T17:01:42.557 に答える
0

つまり、私がこれを正しく理解していれば、iPhone は加速度計のデータを提供しており、iPhone を 3 軸でどれだけ激しく動かしているかを示しています。

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

于 2009-07-17T02:09:18.483 に答える
0

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

iPhone が {0, -6.0, 0} を報告する場合を考えてみましょう。このベクトルを {0, -.38, 0} に変更します。しかし、どちらも {0, -1.0, 0} に正規化されています。したがって、y を -.38 にクランプする効果は、ベクトルの他の 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;
}
于 2009-08-16T14:02:58.717 に答える