どのように私は正しく拡張現実のためのシーンを変換するために、重力ベクトルを使用していますか?

StackOverflow https://stackoverflow.com/questions/2541668

  •  23-09-2019
  •  | 
  •  

質問

私はOpenGLを取得する方法を見つけ出すをしようとしている正しく表示されるオブジェクトを指定されたデバイスの向きに応じて(すなわち加速度計からの重力ベクトルに応じて、およびコンパスから向かう)。

GLGravityサンプルプロジェクトは、ほとんどこの(見出しを無視するにもかかわらず)のようなものですが、それは、いくつかの不具合を持っている例があります。たとえば、ティーポットは、視野角のデバイスは、水平線を横切るよう原稿180°ジャンプ、そしてあなたが風景に肖像画からデバイスを傾けた場合、それはまた、誤って回転します。これは、オブジェクトオフ、それだけが示すように、このアプリのコンテキストで結構です、それはこれらの事を行うことは重要ではありません。しかし、それはあなたが、デバイスの向きに応じたOpenGLオブジェクトの視聴現実の生活をエミュレートしようとすると、コードがうまく動作しないことを意味します。何が起こるかというと、それはほとんど機能していることですが、あなたはコンパスから適用する見出しの回転がGLGravityのサンプルプロジェクトで見られるスプリアス追加の回転によって「壊れて」を取得します。

缶誰もがショーがどのようにデバイスの向きに対して正しく調整すること(すなわち。重力ベクトル)のサンプルコードを提供する、またはそれが偽の見出しの変更が含まれていないようにGLGravity例を修正する?

//Clear matrix to be used to rotate from the current referential to one based on the gravity vector
bzero(matrix, sizeof(matrix));
matrix[3][3] = 1.0;

//Setup first matrix column as gravity vector
matrix[0][0] = accel[0] / length;
matrix[0][1] = accel[1] / length;
matrix[0][2] = accel[2] / length;

//Setup second matrix column as an arbitrary vector in the plane perpendicular to the gravity vector {Gx, Gy, Gz} defined by by the equation "Gx * x + Gy * y + Gz * z = 0" in which we arbitrarily set x=0 and y=1
matrix[1][0] = 0.0;
matrix[1][1] = 1.0;
matrix[1][2] = -accel[1] / accel[2];
length = sqrtf(matrix[1][0] * matrix[1][0] + matrix[1][1] * matrix[1][1] + matrix[1][2] * matrix[1][2]);
matrix[1][0] /= length;
matrix[1][1] /= length;
matrix[1][2] /= length;

//Setup third matrix column as the cross product of the first two
matrix[2][0] = matrix[0][1] * matrix[1][2] - matrix[0][2] * matrix[1][1];
matrix[2][1] = matrix[1][0] * matrix[0][2] - matrix[1][2] * matrix[0][0];
matrix[2][2] = matrix[0][0] * matrix[1][1] - matrix[0][1] * matrix[1][0];

//Finally load matrix
glMultMatrixf((GLfloat*)matrix);
<時間>

ここで私の最後の答えに示すようにgluLookAtソリューションのために必要とされる標高と傾斜を取得する方法を示す明確だ。

// elevation comes from z component (0 = facing horizon)
elevationRadians = asin(gravityVector.z / Vector3DMagnitude(gravityVector));

// tilt is how far screen is from vertical, looking along z axis
tiltRadians = atan2(-gravityVector.y, -gravityVector.x) - M_PI_2;
<時間> クリスの提案にフォローアップ:私は、行/列の順序の規則が異なるとCWまたはCCWを見出しによるこのすべて正しいを持っている場合、私はわかりません。しかし、次のコードは、私が思いついたものです。

Vector3D forward = Vector3DMake(0.0f, 0.0f, -1.0f);

// Multiply it by current rotation matrix to get teapot direction
Vector3D direction;     
direction.x = matrix[0][0] * forward.x + matrix[1][0] * forward.y + matrix[2][0] * forward.z;
direction.y = matrix[0][1] * forward.x + matrix[1][1] * forward.y + matrix[2][1] * forward.z;
direction.z = matrix[0][2] * forward.x + matrix[1][2] * forward.y + matrix[2][2] * forward.z;

heading = atan2(direction.z, direction.x) * 180 / M_PI;

// Use this heading to adjust the teapot direction back to keep it fixed
// Rotate about vertical axis (Y), as it is a heading adjustment
glRotatef(heading, 0.0, 1.0, 0.0);
私はこのコードを実行すると、

は、ティーポットの挙動が明らかに例えば「改善」しています。 (ポートレートビュー)デバイスの画面が前方に投げているとき、もはや向かうと、背中直立を通じて/原稿180°反転しません。しかし、それはまだ(ランドスケープビュー)デバイスは、前方/バック投球されたときに見出しで大きなジャンプします。何かのない権利ので。これは、実際の見出しの上記の計算が間違っていることを示唆している...

正しい解決策はありません

他のヒント

私は最終的に機能するソリューションを見つけました。 : - )

Iは回転行列アプローチを落とし、その代わりにgluLookAtを採用しました。あなたは、デバイス「標高」を知っている必要があり、この作業を行うには(90オーバーヘッド、地平線上の0。地平線にすなわち角度を見て)、およびカメラの「チルト」(どこまでデバイスは、そのX / Y平面すなわち垂直からですデバイス重力ベクトル成分から得られる両方とも0垂直/肖像画、90 +/-場合、水平/ランドスケープ)。

Vector3D eye, scene, up;
CGFloat distanceFromScene = 0.8;
// Adjust eye position for elevation (y/z)
eye.x = 0;
eye.y = distanceFromScene * -sin(elevationRadians); // eye position goes down as elevation angle goes up
eye.z = distanceFromScene * cos(elevationRadians);  // z position is maximum when elevation is zero 
// Lookat point is origin
scene = Vector3DMake(0, 0, 0); // Scene is at origin
// Camera tilt - involves x/y plane only - arbitrary vector length
up.x = sin(tiltRadians);
up.y = cos(tiltRadians);
up.z = 0;

次に、あなただけのgluLookAt変換を適用し、また、デバイスの見出しに応じてシーンを回転させます。

// Adjust view for device orientation
gluLookAt(eye.x, eye.y, eye.z, scene.x, scene.y, scene.z, up.x, up.y, up.z);
// Apply device heading to scene
glRotatef(currentHeadingDegrees, 0.0, 1.0, 0.0);

iPhoneの加速度値に応じてオブジェクトを回転してみます。

float angle = -atan2(accelX, accelY);

glPushMatrix();     
glTranslatef(centerPoint.x, centerPoint.y, 0);
glRotatef(angle, 0, 0, 1);
glTranslatef(-centerPoint.x, -centerPoint.y, 0);
glPopMatrix();
中心点は、中間点がオブジェクトである

OO、素敵ます。

GLGravityは、右ヨー以外のすべてを取得するようです。ここで私はしようとするだろうものです。 GLGravityが行うすべてを行うし、この:

プロジェクトの方向ますの中のベクターは、コンパスや何でもあなたがそう選択を使用して、の顔にティーポットをしたいです。そして、乗算「フォワード」ティーポットのあなたの方向性を与えるティーポットの現在の回転行列、ベクトルによって直面。水平面への2つのベクトルを平坦化し、それらの間の角度を取る。

この角度は、あなたの是正ヨーです。そして、それによってglRotatefます。

かどうかは、3GSのコンパスは、仕事への本のための十分な信頼性と堅牢であることは別のものです。北のベクトルが自分の顔に垂直であるとき、通常のコンパスは動作しません。しかしので、多分、彼らはそこに機械的ソリューションを持っている、私はちょうど私の同僚の3GS上のマップのアプリを試してみましたが、対処するようです。デバイスが実際に何をしているのかを知ることは、それが与える結果を解釈するのに役立ちます。

設定が完了したら、N極とS極であなたのアプリケーションをテストするようにしてください。 : - )

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top