查看: 4897|回复: 30

关于osg osg::MatrixTransform旋转的问题

[复制链接]

该用户从未签到

发表于 2014-5-16 19:44:57 | 显示全部楼层 |阅读模式
new 了一个
osg::MatrixTransform   *transformModel = osg::MatrixTransform;
transformModel ->addChild(myModel);//并添加了一个柱状的几何体,柱状几何体的起点在transformModel局部坐标系 的原点位置,
柱状几何体的方向是在transformModel 的局部坐标系下延Z轴向下,假设我设置transformModel 在全局坐标系下的位置为(100, -100, -100);
transformModel ->setMatrix(osg::Matrix::translate(osg::Vec3(100, -100, -100)));
我现在要让柱状几何体末端指向全局坐标系下的原点,应该如何旋转?

/////我的方法
osg::Matrix  mat;
osg::Vec3 fromVec(100, -100, -100);
osg::Vec3 toVec(0, 0, 0);
osg::Vec3 up(0, 0, 1);
mat.makeLookAt(fromVec, toVec, up);
通过makeLookAt函数得到从fromVec看向toVec的四元数,并把四元数转化为欧拉角,从欧拉角得到transformModel 绕x,y,z轴的旋转角度,
在程序中各种试了下,大概的方向对,但还是没有完全指向全局坐标系的原点 ,求大神

该用户从未签到

 楼主| 发表于 2014-5-16 19:45:48 | 显示全部楼层
自己顶一个

该用户从未签到

发表于 2014-5-16 20:26:18 | 显示全部楼层
我想问一下,你说“并把四元数转化为欧拉角”是怎么实现的,代码给我看看行吗?

该用户从未签到

 楼主| 发表于 2014-5-16 20:36:00 | 显示全部楼层
wpsperson 发表于 2014-5-16 20:26
我想问一下,你说“并把四元数转化为欧拉角”是怎么实现的,代码给我看看行吗?

终于有大神了,网上百度的转换方法,难到是方法不对?
osg:uat HPRToQuat(double heading, double pitch, double roll)
{
osg::Quat q(
  roll,osg::Vec3d(0.0, 1.0, 0.0),
  pitch,osg::Vec3d(1.0, 0.0, 0.0),
  heading,osg::Vec3d(0.0, 0.0, 1.0));
return q;
}
// Quat to HPR,pitch范围:[-PI/2, PI/2]
void QuatToHPR(osg::Quat q, double& heading, double& pitch, double& roll)
{
        double test = q.y() * q.z() + q.x() * q.w();
        if (test > 0.4999)
        { // singularity at north pole
        heading = 2.0 * atan2(q.y(), q.w());
        pitch   = osg:I_2;
        roll    = 0.0;
        return;
        }
        if (test < -0.4999)
        { // singularity at south pole
        heading = 2.0 * atan2(q.y(), q.w());
        pitch   = -osg::PI_2;
        roll    = 0.0;
        return;
        }
        double sqx = q.x() * q.x();
        double sqy = q.y() * q.y();
        double sqz = q.z() * q.z();
        heading = atan2(2.0 * q.z() * q.w() - 2.0 * q.y() * q.x(), 1.0 - 2.0 * sqz - 2.0 * sqx);
        pitch   = asin(2.0 * test);
        roll    = atan2(2.0 * q.y() * q.w() - 2.0 * q.z() * q.x(), 1.0 - 2.0 * sqy - 2.0 * sqx);
}

该用户从未签到

 楼主| 发表于 2014-5-16 20:37:35 | 显示全部楼层
osg :: PI_2  

该用户从未签到

 楼主| 发表于 2014-5-16 20:38:22 | 显示全部楼层
yuye30121 发表于 2014-5-16 20:36
终于有大神了,网上百度的转换方法,难到是方法不对?
osg:uat HPRToQuat(double heading, double pit ...

表情的地方是osg :: Quat 和osg :: PI_2

该用户从未签到

发表于 2014-5-16 20:44:14 | 显示全部楼层
osg::Vec3 from = -osg::Z_AXIS*transformModel ->getMatrix()->getRotate();  //当前方向
osg::Vec3 to= osg::Vec3(0, 0, 0) - transformModel ->getMatrix()->getTrans();//目标方向

transformModel ->setMatrix( osg::Matrix::rotate(from,to)*
                                            osg::Matrix::translate(transformModel ->getMatrix()->getTrans()) );//目标位姿

该用户从未签到

 楼主| 发表于 2014-5-16 20:54:20 | 显示全部楼层
cenfer 发表于 2014-5-16 20:44
osg::Vec3 from = -osg::Z_AXIS*transformModel ->getMatrix()->getRotate();  //当前方向
osg::Vec3 to=  ...

对这个不太懂,麻烦问下
osg::Vec3 from = -osg::Z_AXIS*transformModel ->getMatrix()->getRotate();  //当前方向?这个当前方向值的是什么方向?
osg::Vec3 to= osg::Vec3(0, 0, 0) - transformModel ->getMatrix()->getTrans();//目标方向

transformModel ->setMatrix( osg::Matrix::rotate(from,to)*
                                            osg::Matrix::translate(transformModel ->getMatrix()->getTrans()) );//目标位姿

该用户从未签到

发表于 2014-5-16 21:32:49 | 显示全部楼层
yuye30121 发表于 2014-5-16 20:54
对这个不太懂,麻烦问下
osg::Vec3 from = -osg::Z_AXIS*transformModel ->getMatrix()->getRotate();   ...

你的描述 [柱状几何体的方向是在transformModel 的局部坐标系下延Z轴向下]
-osg::Z_AXIS就是柱状几何体在其局部坐标系下的方向啊
这步是计算当前 柱状几何体的世界方向

该用户从未签到

 楼主| 发表于 2014-5-16 21:38:48 | 显示全部楼层
cenfer 发表于 2014-5-16 21:32
你的描述 [柱状几何体的方向是在transformModel 的局部坐标系下延Z轴向下]
-osg::Z_AXIS就是柱状几何体 ...

transformModel ->setMatrix( osg::Matrix::rotate(from,to))不能直接使柱状几何体指向原点吗?
为什么还要乘以osg::Matrix::translate(transformModel ->getMatrix()->getTrans())?
transformModel ->setMatrix( osg::Matrix::rotate(from,to)*osg::Matrix::translate(transformModel ->getMatrix()->getTrans()) );

该用户从未签到

发表于 2014-5-16 21:42:32 | 显示全部楼层
yuye30121 发表于 2014-5-16 21:38
transformModel ->setMatrix( osg::Matrix::rotate(from,to))不能直接使柱状几何体指向原点吗?
为什么 ...

transformModel ->setMatrix( osg::Matrix::rotate(from,to))这个只是算了方位,没有位置信息
osg::Matrix::translate(transformModel ->getMatrix()->getTrans()) //方位对了,还有把它放回原来的位置。

该用户从未签到

发表于 2014-5-16 21:43:56 | 显示全部楼层
cenfer 发表于 2014-5-16 21:42
transformModel ->setMatrix( osg::Matrix::rotate(from,to))这个只是算了方位,没有位置信息
osg::Matr ...

你要明白 这样的矩阵称为 位姿矩阵,包含 位置和姿态 两样信息

该用户从未签到

 楼主| 发表于 2014-5-16 21:50:08 | 显示全部楼层
cenfer 发表于 2014-5-16 21:43
你要明白 这样的矩阵称为 位姿矩阵,包含 位置和姿态 两样信息

弱弱地问句,能否给个QQ或者别的什么?

该用户从未签到

发表于 2014-5-16 21:58:19 | 显示全部楼层
如果不是同事!
不会再有比论坛更好的交流方式了!

该用户从未签到

 楼主| 发表于 2014-5-16 22:01:58 | 显示全部楼层
cenfer 发表于 2014-5-16 21:58
如果不是同事!
不会再有比论坛更好的交流方式了!

谢谢了!

该用户从未签到

发表于 2014-5-16 22:18:12 | 显示全部楼层
本帖最后由 VR_user_happy 于 2014-5-16 22:20 编辑

旋转要点:
  1. 先平移到旋转中心(既旋转轴所在的旋转基点)
  2.再进行旋转(局部坐标系的旋转中心,旋转轴)MT2
3. 再将局部坐标系下旋转好的移动到最终的目的地MT3

  叠加效果:
     setMatrix(MT1*MT2*MT3)

    比方说你要将一个站立的树放倒(树本中心身不一定在原点)
   那就先将树---》1中心移动回原点,---》2再绕X轴或Y轴旋转放倒,---》3再把树中心移动会原来放的位置,就实现了。

该用户从未签到

 楼主| 发表于 2014-5-17 16:00:53 | 显示全部楼层
VR_user_happy 发表于 2014-5-16 22:18
旋转要点:
  1. 先平移到旋转中心(既旋转轴所在的旋转基点)
  2.再进行旋转(局部坐标系的旋转中心, ...

旋转不是问题,问题是应该如何旋转,就算先移动到旋转中心,下来应该如何绕X,Y,Z旋转之后,能使柱状几何体指向它移动前的位置。问题主要在于绕X,Y,Z分别应该旋转的角度。

该用户从未签到

 楼主| 发表于 2014-5-17 16:04:09 | 显示全部楼层
cenfer 发表于 2014-5-16 20:44
osg::Vec3 from = -osg::Z_AXIS*transformModel ->getMatrix()->getRotate();  //当前方向
osg::Vec3 to=  ...

还有一个问题:为什么我的方法不对?感觉大概方向对,但就是不精确。
我通过
osg:uat HPRToQuat(double heading, double pitch, double roll)
{
osg::Quat q(
  roll,osg::Vec3d(0.0, 1.0, 0.0),
  pitch,osg::Vec3d(1.0, 0.0, 0.0),
  heading,osg::Vec3d(0.0, 0.0, 1.0));
return q;
}
// Quat to HPR,pitch范围:[-PI/2, PI/2]
void QuatToHPR(osg::Quat q, double& heading, double& pitch, double& roll)
{
        double test = q.y() * q.z() + q.x() * q.w();
        if (test > 0.4999)
        { // singularity at north pole
        heading = 2.0 * atan2(q.y(), q.w());
        pitch   = osg:I_2;
        roll    = 0.0;
        return;
        }
        if (test < -0.4999)
        { // singularity at south pole
        heading = 2.0 * atan2(q.y(), q.w());
        pitch   = -osg::PI_2;
        roll    = 0.0;
        return;
        }
        double sqx = q.x() * q.x();
        double sqy = q.y() * q.y();
        double sqz = q.z() * q.z();
        heading = atan2(2.0 * q.z() * q.w() - 2.0 * q.y() * q.x(), 1.0 - 2.0 * sqz - 2.0 * sqx);
        pitch   = asin(2.0 * test);
        roll    = atan2(2.0 * q.y() * q.w() - 2.0 * q.z() * q.x(), 1.0 - 2.0 * sqy - 2.0 * sqx);
}
得到的heading,pitch,roll具体分别是什么?
是绕heading 绕X轴、pitch 绕Y轴、roll绕Z轴吗?

该用户从未签到

发表于 2014-5-17 16:46:06 | 显示全部楼层
本帖最后由 VR_user_happy 于 2014-5-17 16:49 编辑

1.得到柱子包围求中心VP
2.得到柱子的放倒长度L
3.平移到Vp
4.绕Y轴旋转90度,放倒
5.再平移到(-0.5L,0.0,0.0)

该用户从未签到

发表于 2014-5-17 16:53:13 | 显示全部楼层
本帖最后由 cenfer 于 2014-5-17 16:58 编辑
yuye30121 发表于 2014-5-17 16:04
还有一个问题:为什么我的方法不对?感觉大概方向对,但就是不精确。
我通过
osg:uat HPRToQuat(doub ...


你的函数已经告诉你了,意思翻译下就很明了了
osg:uat HPRToQuat(double heading, double pitch, double roll)
{
osg:uat q(
  roll,osg::Vec3d(0.0, 1.0, 0.0),                  //横滚,翻滚,回转,绕前进方向的旋转,这里对应Y轴
  pitch,osg::Vec3d(1.0, 0.0, 0.0),               //俯仰,这里对应X轴
  heading,osg::Vec3d(0.0, 0.0, 1.0));         //航向,有的也用单词Yaw,这里对应Z轴
return q;
}
横滚、俯仰、航向对应的轴是可以自定义的,旋转顺序理论上是可以自定义。
这个链接很直观,这样的问题自己百度一下就能解决。
http://blog.csdn.net/pizi0475/article/details/6365927

该用户从未签到

发表于 2014-5-17 17:04:23 | 显示全部楼层
cenfer 发表于 2014-5-17 16:53
你的函数已经告诉你了,意思翻译下就很明了了
osg:uat HPRToQuat(double heading, double pitch, doub ...

还要补充一句
这对正反解的实现只对应这里定义的旋转轴和旋转顺序。
如果不一样的需求,需要重写实现

该用户从未签到

 楼主| 发表于 2014-5-17 17:35:07 | 显示全部楼层
VR_user_happy 发表于 2014-5-17 16:46
1.得到柱子包围求中心VP
2.得到柱子的放倒长度L
3.平移到Vp

为什么绕Y轴旋转90?

该用户从未签到

 楼主| 发表于 2014-5-19 09:04:06 | 显示全部楼层
cenfer 发表于 2014-5-16 20:44
osg::Vec3 from = -osg::Z_AXIS*transformModel ->getMatrix()->getRotate();  //当前方向
osg::Vec3 to=  ...

今天试了下,发现首先语法不对,osg::vec3怎么可以和四源数相乘?

该用户从未签到

发表于 2014-5-19 09:23:48 | 显示全部楼层
本帖最后由 cenfer 于 2014-5-19 09:26 编辑
yuye30121 发表于 2014-5-19 09:04
今天试了下,发现首先语法不对,osg::vec3怎么可以和四源数相乘?


这里写错了,四元数构造一个矩阵就可以乐
osg::Matrix(transformModel ->getMatrix()->getRotate())

谅解啊  直接在这上面写,有些目测不到

该用户从未签到

 楼主| 发表于 2014-5-19 09:34:18 | 显示全部楼层
cenfer 发表于 2014-5-19 09:23
这里写错了,四元数构造一个矩阵就可以乐
osg::Matrix(transformModel ->getMatrix()->getRotate())
...

我试试看

该用户从未签到

 楼主| 发表于 2014-5-19 09:36:46 | 显示全部楼层
cenfer 发表于 2014-5-19 09:23
这里写错了,四元数构造一个矩阵就可以乐
osg::Matrix(transformModel ->getMatrix()->getRotate())
...

from这个点怎么办?

该用户从未签到

 楼主| 发表于 2014-5-19 09:39:59 | 显示全部楼层
cenfer 发表于 2014-5-19 09:23
这里写错了,四元数构造一个矩阵就可以乐
osg::Matrix(transformModel ->getMatrix()->getRotate())
...

能不能代码贴全点,先谢谢了!

该用户从未签到

发表于 2014-5-19 12:38:07 | 显示全部楼层
本帖最后由 cenfer 于 2014-5-19 12:42 编辑
yuye30121 发表于 2014-5-19 09:39
能不能代码贴全点,先谢谢了!


我没有代码,只是根据你的描述现写的
全了就是这样!
osg::Vec3 from = -osg::Z_AXIS*osg::Matrix(transformModel ->getMatrix()->getRotate());  //当前方向
您需要登录后才可以回帖 登录 | 注册

本版积分规则

OSG中国官方论坛-有您OSG在中国才更好

网站简介:osgChina是国内首个三维相关技术开源社区,旨在为国内更多的技术开发人员提供最前沿的技术资讯,为更多的三维从业者提供一个学习、交流的技术平台。

联系我们

  • 工作时间:09:00--18:00
  • 反馈邮箱:1315785073@qq.com
快速回复 返回顶部 返回列表