2017-07-13 2 views
2

Je suis en train de construire un programme de modélisation et je voudrais faire des transformations sur des objets dans leur propre espace, puis assigner cet objet à un groupe pour tourner autour d'un autre axe. autour. Cependant, j'aimerais aussi être capable de faire des transformations dans l'espace de l'objet quand il est combiné.OpenGL transformant des objets avec des rotations multiples de différents axes

En manipulant l'objet individuel, je choisis le centre de l'objet.

glm::mat4 transform; 
transform = glm::translate(transform, - obj.meshCenter); 
glm::mat4 transform1; 
transform1 = glm::translate(transform1, obj.meshCenter); 
obj.rotation = transform1*obj.thisRot*transform; 

J'envoie ensuite cette option pour le shader,

glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(obj.translation*obj.rotation*objscale); 

Je voudrais maintenant faire pivoter cet objet autour d'un autre axe, par exemple un axe de (5,0,0) de 45 degrés.

J'ai maintenant:

glm::mat4 groupR; 
groupR = glm::rotate(groupR,glm::degrees(45.0f),glm::vec3(5,0,0)); 
obj.groupRotation = groupR; 
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, 
glm::value_ptr(obj.groupRotation*obj.translation*obj.rotation*objscale) 

J'ai maintenant déplacé l'objet à partir de son espace local à l'espace du Groupe. J'ai un peu de mal à gérer les transformations dans l'espace de l'objet quand on le combine avec la rotation du groupe. J'ai eu un succès limité quand je mets l'axe à; R (0,1,0) comme ceci:

///Translating object in its own space/// 
glm::mat4 R = obj.groupRotation; 
obj.translation = glm::inverse(R) * obj.translate * R; 

le problème est que cela ne traduit correctement l'objet dans son propre espace si l'axe de rotation de R (rotation du groupe) est égale à (0,1,0):

///Rotating object in its own space/// 
glm::mat4 R = obj.groupRotation; 
obj.rotation = glm::inverse(R) * obj.rot * R; 

Encore une fois, les rotations sont incorrectes. Je pense que je dois peut-être annuler la traduction de l'axe du groupe? puis réappliquer quelque part?

+0

Peut-être que cette question peut vous aider [Problèmes avec la matrice de rotation de l'axe Z dans glsl shader ] (https://stackoverflow.com/questions/6458051/issues-with-z-axis-rotation-matrix-in- glsl-shader/44986176 # 44986176) – Rabbid76

+0

ce que j'essaie de faire est d'annuler le groupRotation de sorte que mes calculs de transformation locale soient corrects.L'inverse ci-dessus retournera les rotations et les traductions (n'ont pas encore tenté de mise à l'échelle) dans l'espace local. Le raccrochage est si l'axe de groupRotation n'est pas situé à l'origine. Je vais essayer d'insérer une translation inverse de l'emplacement de l'axe dans les multiplications matricielles ci-dessus. Je ne suis pas sûr dans quel ordre il devrait être ou si cela fonctionnera même. Cependant, je vais faire un bon coup le matin. –

+0

Ne pouvez-vous pas modifier 'obj.thisRot' directement et recalculer la transformation combinée? Ce serait beaucoup moins sujet aux erreurs. Btw, je ne compterais pas sur 'glm :: value_ptr()' pour retourner une adresse valide pour un objet temporaire qui est supprimé juste après l'appel de 'glm :: value_ptr()'. –

Répondre

3

Supposons que nous avons un objet qui est déplacé, tourné et mis à l'échelle, et nous définissons une matrice de transformation comme suit:

glm::mat4 objTrans ...; // translation 
glm::mat4 objRot ...; // roation 
glm::mat4 objScale ...; // scaling 

glm::mat4 objMat = objTrans * objRot * objScale; 

Et nous avons la matrice de rotation que nous voulons exécuter sur l'objet. Dans ce cas, nous avons la rotation autour de l'axe Z:

foat angle ...; // rotation angle 

glm::mat4 rotMat = glm::rotate(angle, glm::vec3(0.0, 0.0, 1.0)); 

Nous avons plusieurs rotations que nous pouvons faire avec cette information. Tout d'abord, nous voulons faire tourner l'objet sur son axe local:

enter image description here

glm::mat4 modelMat = objMat * rotMat; 

Une rotation autour de l'origine des mondes peut être effectuée comme ceci:

enter image description here

glm::mat4 modelMat = rotMat * objMat; 

En Afin de tourner autour de l'origine de l'objet dans le système de coordonnées du monde, nous devons éliminer le rota tion du objct:

enter image description here

glm::mat4 modelMat = objMat * (glm::inverse(objRot) * rotMat * objRot); 

Une rotation autour de l'origine des mondes par rapport à l'objet que vous avez à faire le contraire:

enter image description here

glm::mat4 modelMat = (objRot * rotMat * glm::inverse(objRot)) * objMat; 

Si vous avez une matrice de transformations complète pour un objet et vous ne connaissez pas la partie de rotation, alors il peut être facilement déterminé.

Notez qu'une matrice de transformation ressemble généralement à ceci:

(X-axis.x, X-axis.y, X-axis.z, 0) 
(Y-axis.x, Y-axis.y, Y-axis.z, 0) 
(Z-axis.x, Z-axis.y, Z-axis.z, 0) 
(trans.x, trans.y, trans.z, 1) 

Pour générer une rotation seule matrice que vous devez extraire les vecteurs d'axe normalisés:

glm::mat4 a ...; // any matrix 
glm::vec3 x = glm::normalize(a[0][0], a[0][1], a[0][2]); 
glm::vec3 y = glm::normalize(a[1][0], a[1][1], a[1][2]); 
glm::vec3 z = glm::normalize(a[2][0], a[2][1], a[2][2]); 

glm::mat4 r; 
r[0][0] = x[0]; r[0][1] = x[1]; r[0][2] = x[2]; r[0][3] = 0.0f; 
r[1][0] = y[0]; r[1][1] = y[1]; r[1][2] = y[2]; r[0][3] = 0.0f; 
r[2][0] = z[0]; r[2][1] = z[1]; r[2][2] = z[2]; r[0][3] = 0.0f; 
r[3][0] = 0.0f; r[3][1] = 0.0f; r[3][2] = 0.0f; r[0][3] = 1.0f; 
+0

Salut Rabbid, j'apprécie l'aide. Je pense que je n'explique peut-être pas assez le problème. Si je réduis le problème à ceci (obj.groupRot * obj.translate * (obj.rot = identité) * (obj.scale = identité) La traduction et/ou l'échelle comme exemple sera affectée par le GroupRot .. C'est la raison de mes tentatives de multiplier tous mes objets transforme les matrices par l'obj.groupRotation inverse pour l'obtenir dans l'espace objet, effectue mes transformations normalement et ensuite multiplie par obj.groupRotation dans l'espace correct. être la question –

+0

@ TomTom J'espère que ma réponse surmenée peut vous aider – Rabbid76

1

Voici une réponse partielle à la comportement que je veux et la configuration que j'ai utilisée. Cela semble être ce que je dois faire pour obtenir les transformations correctes dans l'espace objet en dehors d'une rotation de groupe. Ici, j'ai un modèle composé de 7 différentes mailles individuelles qui tourne autour de l'origine de (0,5,0) sur l'axe des y, c'est juste une rotation arbitraire que je choisis pour les tests.

for (int i = 0; i < models.at(currentSelectedPointer.x)->meshes.size()i++) 
    { 
    glm::mat4 rotMat; 
    rotMat = glm::translate(rotMat, glm::vec3(5, 0, 0)); 
    rotMat = glm::rotate(rotMat, f, glm::vec3(0, 1.0, 0.0)); 
    rotMat = glm::translate(rotMat, glm::vec3(-5, 0, 0)); 
    models.at(currentSelectedPointer.x)->meshes.at(i).groupRotation = rotMat; 
    } 

toutes les mailles sont en rotation autour de l'entreprise (0,5,0) en tant que groupe, et non pas à (0,5,0), sur l'axe Y.

pour faire la rotation correcte sur un objet dans son propre espace objet, je dois annuler l'emplacement de l'origine de groupRotation (Désolé pour le code désordonné, mais je l'ai fait par étapes comme ça pour garder tout séparé et facilement détectable). En outre, l'objet individuel a une matrice d'identité à la fois pour sa traduction et son échelle.

 //These will be used to shift the groupRotation origin back to the 
    // origin in order to rotate around the object's origin. 

    glm::mat4 gotoGroupAxis; 
    gotoGroupAxis= glm::translate(gotoGroupAxis, glm::vec3(5, 0, 0)); 
    glm::mat4 goBack ; 
    goBack = glm::translate(goBack , glm::vec3(-5, 0, 0)); 

    ////////Group rotation and it's inverse   
    glm::mat4 tempGroupRot = goBack *obj.groupRotation*gotoGroupAxis; 
    glm::mat4 tempGroupRotInverse= glm::inverse(tempGroupRot); 

    //thisRot and lastRot are matrix variables I use to accumulate and 
    //save rotations  
    obj.thisRot = tempGroupRotInverse* 
    glm::toMat4(currentRotation)*tempGroupRot * 
    obj.lastRot; 

    //now I translate the object's rotation origin to it's center. 

    glm::mat4 transform = glm::translate(transform, -obj.meshCenter); 
    glm::mat4 transform1 = glm::translate(transform1, obj.meshCenter); 
    //Finally I rotate the object in it's own space. 
    obj.rotation = transform1*obj.thisRot*transform; 

Mise à jour:

//Translation works as well with 
obj.finalTranslation= tempGroupRotInverse* 
obj.translation * tempGroupRot ; 

Ceci est seulement une réponse partielle parce que je vais être faire à un niveau transforme l'objet et au niveau du groupe et je suis presque certain que quelque chose va mal tourner vers le bas la ligne qui n'a pas été prise en compte par la réponse que j'ai postée.