OpenGL 变换不同轴多次旋转的对象

我正在构建一个建模程序,我想对它们自己空间中的对象进行变换,然后将该单个对象分配给一个组,以围绕该组旋转的另一个轴旋转.但是,我也希望能够在组合时在对象自己的空间中进行转换.

I am building a modeling program and I'd like to do transformations on objects in their own space and then assign that single object to a group to rotate around another axis which the group rotates around. However, I'd also like to be able to do transformations in the object's own space when it's combined.

操作单个对象,我选择对象的中心.

Manipulating the individual object, I pick the object's center.

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

然后我将其发送给着色器,

I then send this off to the shader,

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

我现在想围绕另一个轴旋转这个对象,比如 45 度的 (5,0,0) 轴.

I would now like to rotate this object around another axis, say an axis of (5,0,0) of 45 degrees.

我现在有:

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)

我现在已经将对象从它的本地空间移动到了组空间.当结合组的旋转时,我现在在对象自己的空间中操作变换有点困难.当我像这样将 groupR 轴设置为 (0,1,0) 时,我的成功有限:

I've now moved the object from it's local space to the Group space. I'm having a bit of difficulty now operating tranformations in the object's own space when combined with the Group's rotation. I've had limited success when I set the groupR axis to (0,1,0) like so:

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

这里的问题是,如果 R(组的旋转)的旋转轴等于 (0,1,0),这只会在它自己的空间中正确平移对象:

the problem here is that this will only translate the object correctly in it's own space if the axis of rotation of R (Group's rotation) is equal to (0,1,0):

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

同样,旋转不正确.我在想,也许我必须撤销 groupR 的轴平移?然后在某处重新应用它?

Again, the rotations are incorrect. I'm thinking that maybe I have to undo the groupR's axis translation? and then re-apply it somewhere?

推荐答案

假设我们有一个移动、旋转和缩放的对象,我们定义一个变换矩阵如下:

Let's assume we have an object that is moved, rotated and scaled, and we define a transformation matrix as follows:

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

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

我们有我们想要在对象上运行的旋转矩阵.在这种情况下,我们围绕 Z 轴旋转:

And we have rotation matrix that we want to run on the object. In this case we have rotation around the Z-axis:

foat angle ...; // rotation angle

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

我们可以利用这些信息进行多次轮换.首先,我们要在对象的局部轴上旋转对象:

We have several rotations we can do with this information. First we want to rotate the object on its local axis:

glm::mat4 modelMat = objMat * rotMat;

可以像这样执行绕世界原点的旋转:

A Rotation around the worlds origin can be performed like this:

glm::mat4 modelMat = rotMat * objMat;

为了在世界坐标系中绕物体的原点旋转,我们必须消除物体的旋转:

In order to rotate around the origin of the object in the world coordinate system, we must eliminate the rotation of the object:

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

围绕世界原点相对于对象的旋转你必须做相反的事情:

A Rotation around the worlds origin in relation to the object you have to do the opposite:

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

如果您有一个完整的对象变换矩阵,并且您不知道旋转部分,则可以轻松确定.

If you have a complete transformations matrix for an object and you do not know the rotation part, then it can be easily determined.

请注意,变换矩阵通常如下所示:

Note that a transformation matrix usually looks like this:

( 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 )

要生成仅旋转矩阵,您必须提取归一化轴向量:

To generate a rotation only matrix you have to extract the normalized axis vectors:

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; 

相关文章