2009-03-28 7 views
1

J'utilise une connexion WinSock pour obtenir les informations de l'accéléromètre et l'iPhone et dans une application Direct3D. J'ai modifié le code d'exemple d'Apple GLGravity pour faire bouger mon hélicoptère par rapport à la gravité, mais j'ai besoin de "boucher" le mouvement pour que l'hélicoptère ne puisse pas voler à l'envers! J'ai essayé de limiter la sortie de l'accéléromètre comme siDirect3D & iPhone Accelerometer Matrix

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

Sauf que cela ne semble pas fonctionner !? La seule chose que je peux penser est que j'ai besoin de modifier la matrice personnalisée, mais je n'arrive pas à comprendre ce que j'ai besoin de changer. La matrice est le code ci-dessous.

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

Si quelqu'un peut l'aider serait très apprécié!

+0

quel comportement avez-vous maintenant? – bayda

+0

directx sur l'iphone? – hhafez

+0

non, je pense qu'il a utilisé iphone comme dispositif de contrôle – bayda

Répondre

0

Essayez de normaliser le vecteur d'accélération en premier. (edit: après avoir vérifié la longueur) (edit edit: j'imagine que je dois apprendre à lire ... comment supprimer ma réponse?)

0

Donc si je comprends bien, l'iPhone est votre accéléromètre données, dire à quel point vous déplacez l'iPhone dans 3 axes.

Je ne connais pas cet échantillon de pomme, donc je ne sais pas ce qu'il fait. Cependant, on dirait que vous mappez l'accélération directement à l'orientation, mais je pense que ce que vous voulez faire est d'intégrer l'accélération pour obtenir une position et regarder les changements de position afin d'orienter l'hélicoptère. Fondamentalement, c'est plus un problème de physique qu'un problème Direct3D.

0

Il semble que vous utilisiez le vecteur d'accélération du téléphone pour définir un axe d'un repère orthogonal. Et je suppose que + Y est pointé vers le sol, donc vous êtes préoccupé par le cas où le vecteur pointe vers le ciel.

Considérons le cas lorsque l'iPhone signale {0, -6.0, 0}. Vous allez modifier ce vecteur à {0, -.38, 0}. Mais ils se normalisent tous deux à {0, -1.0, 0}. Ainsi, l'effet du blocage de y à -38 est influencé par l'amplitude des deux autres composantes du vecteur. Ce que vous voulez vraiment, c'est limiter l'angle du vecteur au plan XZ quand Y est négatif. Supposons que vous souhaitiez limiter la valeur du plan XZ à 30 degrés maximum lorsque Y est négatif. Par exemple:

Tout d'abord normaliser le vecteur alors:

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

Vous devez également gérer le cas lorsque _x et _z sont à zéro. Le plus simple, mais probablement pas le meilleur, serait de choisir le vecteur _x = XZLimitLength, _y = -sinLimitAngle, _z = 0. –

+0

Et je suis également d'accord avec légaliser que si vous essayez de faire un hélicoptère virtuel se déplacer avec le téléphone fait alors toute l'approche est fausse. –

1

Je pense double intégration est probablement trop compliquer les choses. Si je comprends bien le problème, l'iPhone vous donne un vecteur de valeurs des accéléromètres. En supposant que l'utilisateur ne l'agite pas, ce vecteur aura une longueur à peu près constante et pointera directement vers le bas avec la gravité.

Il y a un problème majeur avec ceci, et c'est que vous ne pouvez pas dire quand l'utilisateur tourne le téléphone autour de l'horizontale. Imaginez que vous mentez votre téléphone sur la table, avec le fond face à vous pendant que vous êtes assis devant; le vecteur de gravité serait (0, -1, 0). Maintenant faites pivoter votre téléphone d'environ 90 degrés de sorte que le fond soit tourné vers la gauche, mais qu'il soit toujours à plat sur la table. Le vecteur de gravité va encore être (0, -1, 0). Mais vous voulez vraiment que votre hélicoptère tourne avec le téléphone. C'est une limitation de base du fait que l'iPhone ne possède qu'un accéléromètre 2D, et il extrapole un vecteur de gravité 3D à partir de cela. Supposons donc que vous avez dit à l'utilisateur qu'il n'est pas autorisé à faire pivoter son téléphone comme ça, et qu'il doit le garder avec le point le plus bas. C'est bien, vous pouvez toujours obtenir beaucoup de contrôle de cela.

Ensuite, vous devez plafonner l'entrée de sorte que l'hélicoptère ne dépasse jamais de plus de 90 degrés de son côté. Imaginez le vecteur qui vous est donné comme étant un bâton attaché à votre téléphone, et qui pend avec la gravité. Le vecteur que vous avez décrit la direction de la gravité par rapport à la surface plane du téléphone. Si c'était (0, -1, 0) le bâton pointe directement vers le bas (-y). si c'était (1, 0, 0), le manche pointe vers la droite du téléphone (+ x), et implique que le téléphone a été tordu de 90 degrés dans le sens des aiguilles d'une montre (en détournant votre regard du téléphone).

Supposons dans cette métaphore que le manche a une liberté de rotation totale. Il peut pointer dans n'importe quelle direction depuis le téléphone. Donc, déplacer le bâton autour décrit la surface d'une sphère. Mais surtout, vous voulez seulement que le bâton puisse se déplacer dans la moitié inférieure de cette sphère. Si l'utilisateur tord le téléphone de sorte que le bâton serait dans la moitié supérieure de la sphère, vous voulez qu'il plafonne de sorte qu'il pointe quelque part autour de l'équateur de la sphère.

Vous pouvez réaliser cela très proprement en utilisant des coordonnées polaires. Les vecteurs 3D et les coordonnées polaires sont interchangeables - vous pouvez convertir vers et depuis sans perdre aucune information.

Convertissez le vecteur que vous avez (normalisé bien sûr) en un ensemble de coordonnées polaires 3D (vous devriez pouvoir trouver cette logique sur le Web assez facilement). Cela vous donnera un angle autour du plan horizontal, et un angle pour le plan vertical (et une distance par rapport à l'origine - pour un vecteur normalisé, cela devrait être 1.0). Si l'angle vertical est positif, le vecteur est dans la moitié supérieure de la sphère, négatif dans la moitié inférieure. Puis, plafonner l'angle vertical de sorte qu'il soit toujours zéro ou moins (et ainsi dans la moitié inférieure de la sphère). Ensuite, vous pouvez prendre l'angle vertical horizontal et plafonné, et le convertir en un vecteur.

Ce nouveau vecteur, s'il est branché sur le code matriciel que vous avez déjà, vous donnera l'orientation correcte, limitée à l'amplitude de mouvement dont vous avez besoin. Il sera également stable si l'utilisateur tourne son téléphone légèrement au-delà de la marque de 90 degrés - cette logique gardera votre vecteur directionnel aussi proche que possible de l'orientation actuelle de l'utilisateur, sans dépasser la limite que vous avez définie.

Questions connexes