2016-09-30 253 views
0

我的目标是让用户上传的3D模型,并使用他们的网络浏览器放置它们。为此,我使用BabylonJS - &其工作正常。之后,我希望我的用户能够在原生应用程序中查看与使用网络浏览器设置相同位置的相同模型。我用于本地应用程序的框架是OpenSceneGraph(OSG)。我遇到的问题是我无法正确地使旋转工作,以至于OpenSceneGraph正确地反映了BabylonJS中正在发生的事情。转换欧拉角度的旋转,以轴+角

我在BabylonJS中使用欧拉角 - 因为它们很容易让网站用户理解(例如,围绕X轴旋转90度,绕Y轴旋转180度,围绕Z轴旋转0度;例如模型。 rotation = new BABYLON.Vec3(90,180,0))。然而,OSG使用OpenGL glrotate()函数,该函数需要旋转轴和旋转角度。为此,我使用BabylonJS从欧拉角度创建一个四元数;然后用我写的基于关闭Java示例此页面上的功能:

http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToAngle/index.htm

function getAxisAngle(){ 
    var q = BABYLON.Quaternion.RotationYawPitchRoll(m.rotation.y,  m.rotation.x, m.rotation.z),s,r={}; 
    /*Convert quaternion to axis+angle*/ 
    if(q.w > 1){ 
     q = q.normalise(); 
    } 
    r.angle = BABYLON.Tools.ToDegrees(2 * Math.acos(q.w)); 
    s = Math.sqrt(1-q.w*q.w); 
    if(s < 0.001){ 
     r.ax = q.x; 
     r.ay = q.y; 
     r.az = q.z; 
    }else{ 
     r.ax = q.x/s; 
     r.ay = q.y/s; 
     r.az = q.z/s; 
    } 
    return r; 
} 

我意识到BJS和OSG之间的根本区别在于BJS是左手坐标系; OSG是右撇子;所以我通过将面部绕线设置为顺时针将OSG制成左手;并将我的模型的z轴缩放-1。

它在一个基本水平工作,如果我隔离在时间1轴;例如如果我只围绕y轴旋转;并且不要围绕任何其他轴旋转 - 它看起来很好。但是,如果我尝试同时结合两个或三个欧拉角度,我无法让它在OSG中看起来一样。

我读过,欧拉角不推荐;部分原因是旋转施加到每个轴的顺序很重要。这是一个可能的原因吗?

+0

我猜,因为你正在使用一端四元,并使用欧拉角度上,你所熟悉的使用四元对欧拉之间的优势差异的另一端,由于万向锁角度。如果您的应用程序使用欧拉角来旋转多个旋转轴并发生万向节锁定,那么您的旋转将停止工作。如果您更愿意继续使用欧拉角度来旋转轴线,那么您需要将它们限制在一起,以防止万向节锁定,例如[-89.99,89.99]。 (...续) –

+0

(...续)万向锁定的原因是由于90度或PI/4是直角或正交。正弦(90)或正弦(PI/4)= 1,余弦(90)或余弦(PI/4)= 0,因为切线=正弦/余弦这里您的正切是未定义的,因为除以0的所以当旋转的一种物体在X轴上90°,然后由Y或Z旋转90°或-90,会发生什么情况是这两个轴会互锁,并且当您再次从两个锁定轴中的任何一个旋转时,该功能无法确定要旋转哪个轴。 (...继续) –

+0

(...继续)你可以查看这个视频了解四元数,也许不是数学上的,而是至少在视觉上。 https://www.youtube.com/watch?v=zc8b2Jo7mno –

回答

0

在我看来,不要试图让OSG左撇子,而翻译你的旋转角度的“逻辑”的含义,并应用它们来OSG是指所使用的方式。

将您的加载模型放置在osg :: PositionAttitudeTransform(或MatrixTransform)下,然后通过连接2个四元数来计算正确的旋转(姿态)以适用于您公开给用户的2个旋转角度。
举例来说,如果你认为“推销”围绕X轴旋转,和“标题”绕Y,做这样的事情:

osg::Quat attitude = osg::Quat(pitchAngle, osg::X_AXIS) * osg::Quat(headAngle, osg::Y_AXIS); 
transform->setAttitude(attitude); 

您可能需要反转角度符号来得到正确的结果(从左到右传递)。

+0

感谢您的建议将尝试并报告回! – Reece