2016-10-25 6 views
0

J'ai un programme que je construis en 3D.Rotations de quaternion basées sur le vecteur et le point

Il est fondamentalement fait d'un objet (une sorte de cube) que les utilisateurs peuvent faire pivoter et se déplacer, tandis que je peux regarder leur vue de l'objet en inspectant le même objet sur le serveur avec une flèche dirigée vers leur point de vue.

Le client envoie son emplacement, sa direction et le haut comme 3 vecteurs au serveur. J'essaye de rendre ma flèche basée sur leur emplacement et leur rotation.


Je fais cela avec le code suivant (en utilisant LibGDX pour la 3D):

Vector3[] vs; 
Vector3 tmp = new Vector3(); 
batch.begin(wm.cam); 
for (SocketWrapper s : clientAtt.keySet()) {// for every client 
    vs = clientAtt.get(s); // read the 3 vectors: { position, direction, up } 

    tmp.set(vs[2].nor()); 
    vs[1].nor(); 

    // arr.transform is the transform of the arrow 
    arr.transform.set(vs[0], new Quaternion().setFromCross(tmp.crs(Vector3.Z).nor(), vs[1])); 

    batch.render(arr); 
} 

Et c'est la définition de arr:

arrow = new ModelBuilder().createArrow(0, 0, 0, 1, 0, 0, 0.1f, 0.1f, 5, GL20.GL_TRIANGLES, new Material(ColorAttribute.createDiffuse(Color.RED)), VertexAttributes.Usage.Position | VertexAttributes.Usage.Normal); 
arr = new ModelInstance(arrow); 

Si je tourne seulement autour l'axe Y, tout fonctionne, mais si j'utilise l'axe X/Z ça devient fou. J'essaye de comprendre où mes maths sont fausses et comment le réparer.

Merci.

+0

si vous voulez exprimer une rotation: chaque fois que vous recevez une nouvelle série de vecteur vous faites comme vous avez créé un quaternion à partir de l'angle d'axe (le produit croisé que vous avez fait), puis vous devez stocker le quaternion précédent. et chaque fois que votre quaternion de transformation devrait être newQuaternion * previousQuaternion. –

+0

Alors, quelle est votre question? – Xoppa

Répondre

1

Quaternion est utilisé pour définir seulement une rotation, pas l'orientation. Par exemple: il définit la façon de transformer un vecteur donné (unité) en un autre vecteur afin de faire pivoter la quantité que vous avez spécifiée. Mais il ne définit pas quel vecteur c'est. Encore plus: il ya un nombre infini de transformations possibles qui peuvent atteindre cet objectif.

La méthode setFromCross vous permet de spécifier cette rotation en fournissant deux vecteurs arbitraires. Le Quaternion sera alors défini de sorte qu'il transforme le premier vecteur en le deuxième vecteur, en le faisant tourner autour d'un axe perpendiculaire aux vecteurs que vous avez fournis.

Ainsi, dans votre cas:

setFromCross(tmp.set(up).crs(Vector3.Z).nor(), direction) 

Ceci définit la Quaternion afin qu'il tournerait le produit croisé de votre haut vecteur et le Z + vecteur à votre vecteur de direction, le long de l'axe qui est perpendiculaire à ceux deux vecteurs. Cela pourrait fonctionner pour vous dans certains cas, mais je doute que ce soit ce que vous voulez vraiment faire. Donc, pour répondre à votre question: c'est probablement là où vos maths vont mal.

Bien que cela dépasse le cadre de votre question, regardons comment vous pourriez réaliser ce que vous voulez réaliser.

  1. Définissez d'abord l'orientation de votre modèle lorsqu'il n'est pas pivoté. Par exemple. quel côté est en haut, quel côté est en avant (direction) et quel côté est droit (ou gauche). Supposons pour ce cas que, au repos, votre modèle est à la hausse Y + (upRest = new Vector3(0, 1, 0);), il fait face à X + (directionRest = new Vector3(1, 0, 0)) et à droite est Z + (rightRest = new Vector3(0, 0, 1);).

  2. Définissez maintenant l'orientation pivotée souhaitée.Vous avez déjà, à l'exception du droit pour lequel nous pouvons utiliser le produit croisé (perpendiculaire) antivectorielle: upTarget = new Vector3(vs[2]).nor(); directionTarget = new Vector3(vs[1]).nor(); rightTarget = new Vector3().set(upTarget).crs(directionTraget).nor(); Notez que vous pourriez avoir besoin d'échanger le haut et la direction des vecteurs cibles dans le produit croisé (.set(directionTarget).crs(upTarget).nor();)

  3. Parce que la orientation au repos est axe aligné, nous pouvons prendre un joli petit raccourci par l'une des propriétés d'une matrice. Un Matrix4 peut être défini comme: un vecteur de 4 vecteurs. Le premier de ces quatre vecteurs spécifie l'axe X pivoté, le second spécifie l'axe Y pivoté, le troisième vecteur spécifie le vecteur Z pivoté et le quatrième vecteur spécifie l'emplacement. Donc, utilisez ce une doublure pour définir le modèle à l'orientation et la position que nous voulons:

    arr.transform.set(directionTarget, upTarget, rightTarget, vs[0]);