Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/opengl/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ OpenGL变换具有不同轴多次旋转的对象_C++_Opengl_Rotation_Glm Math_Coordinate Transformation - Fatal编程技术网

C++ OpenGL变换具有不同轴多次旋转的对象

C++ OpenGL变换具有不同轴多次旋转的对象,c++,opengl,rotation,glm-math,coordinate-transformation,C++,Opengl,Rotation,Glm Math,Coordinate Transformation,我正在构建一个建模程序,我想对它们自己空间中的对象进行变换,然后将单个对象指定给一个组,以围绕该组旋转的另一个轴旋转。但是,我也希望能够在组合对象时在对象自身的空间中进行变换 操纵单个对象时,我拾取对象的中心 glm::mat4 transform; transform = glm::translate(transform, - obj.meshCenter); glm::mat4 transform1; transform1 = glm::translate(transform1, obj.m

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

操纵单个对象时,我拾取对象的中心

glm::mat4 transform;
transform = glm::translate(transform, - obj.meshCenter);
glm::mat4 transform1;
transform1 = glm::translate(transform1, obj.meshCenter);
obj.rotation =  transform1*obj.thisRot*transform;
然后我将其发送到着色器

glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(obj.translation*obj.rotation*objscale);
我现在想绕另一个轴旋转这个物体,比如说一个45度的(5,0,0)轴

我现在有:

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)时,我的成功有限,如下所示:

这里的问题是,只有当R(组的旋转)的旋转轴等于(0,1,0)时,才会在其自身空间中正确平移对象:


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

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

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

glm::mat4 objMat = objTrans * objRot * objScale;
我们有旋转矩阵,我们想在物体上运行。在这种情况下,我们绕Z轴旋转:

foat angle ...; // rotation angle

glm::mat4 rotMat = glm::rotate( angle, glm::vec3( 0.0, 0.0, 1.0 ) ); 
我们可以利用这些信息进行多次旋转。 首先,我们要在对象的局部轴上旋转对象:

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

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

为了在世界坐标系中围绕对象的原点旋转,必须消除对象的旋转:

围绕世界原点相对于对象的旋转必须执行相反的操作:

如果有对象的完整变换矩阵,但不知道旋转部分,则可以轻松确定

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

( 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 )
要生成仅旋转矩阵,必须提取归一化轴向量:

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; 

下面是我想要的行为和我使用的设置的部分答案。这似乎是我需要做的,以获得正确的变换,在对象空间,而一组旋转分开。 在这里,我有一个由7个不同的单独网格组成的模型,这些网格围绕y轴上(0,5,0)的原点旋转,这只是我为测试选择的任意旋转

 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;
    }
更新:

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

这只是一个部分答案,因为我将在对象级别和组级别上进行变换,我几乎可以肯定,在我发布的答案中没有考虑到的情况下,会出现一些错误。

我试图做的是撤消组旋转,以便我的局部变换计算是正确的。上面的倒数将使旋转和平移(尚未尝试缩放)返回到局部空间。如果groupRotation的轴不位于原点,则会出现挂起。我将尝试在上面的矩阵乘法中插入轴位置的逆平移。我只是不确定它应该是什么顺序,或者它是否会起作用。不过,我明天早上会好好试一试。你不能直接修改
obj.thisRot
并重新计算组合变换吗?这样就不那么容易出错。顺便说一句,我不会指望
glm::value_ptr()
返回临时对象的有效地址,该临时对象在调用
glm::value_ptr()
后立即被删除。您好Rabbid,我感谢您的帮助。我想也许我没有很好地解释这个问题。如果我将问题简化为(obj.groupRot*obj.translate*(obj.rot=identity)*(obj.scale=identity)。例如,平移和/或缩放将受到GroupRot的影响。。这就是我尝试将所有对象的变换矩阵乘以obj.groupRotation逆矩阵的原因。要将其乘以对象空间,请正常执行变换,然后再乘以obj.groupRotation返回到正确的空间。obj.gr的位置这一问题似乎来自于中国。
glm::mat4 modelMat = (objRot * rotMat * glm::inverse(objRot)) * objMat;
( 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 )
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; 
 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;
    }
     //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;
 //Translation works as well with
 obj.finalTranslation= tempGroupRotInverse* 
 obj.translation * tempGroupRot ;