【问题标题】:Convert from bullet physics quaternion to angle to use with CATransform3DMakeRotation从子弹物理四元数转换为角度以与 CATransform3DMakeRotation 一起使用
【发布时间】:2012-03-04 19:10:57
【问题描述】:

我使用 CATransformLayer 构建了一个 6 面的 3D 骰子,将其用作容器层,将 6 个变换层夹入一个可以在空间中旋转的 3D 对象。 I got the idea from here。它运行良好,我可以在顶层旋转调用 CATransform3DMakeRotation 的“骰子”,骰子旋转并且运行良好。

下一步是在程序中插入“子弹物理”。我已经工作了,但是我被卡住了,因为我不知道如何将其物理世界中骰子的“子弹物理‘四元数’方向”转换为我可以传递给我的容器 CALayer 方法的旋转角度。

这是我正在做的:

1) 调用“子弹物理”来获取骰子的方向:

// QUATERNION: Get the orientation
btQuaternion quatO = TObject->getOrientation();

2)将四元数转换为欧拉(很多时间谷歌搜索答案发现下面复制的方法) qW = quatO.getW(); qX = quatO.getX(); qY = quatO.getY(); qZ = quatO.getZ(); [自四元数ToEuler];

3) 将新的欧拉角应用到我的 CALayer (sCtrl)

[sCtrl rotaX:eX rotaY:eY rotaZ:eZ];

注意 1:这是我用来旋转我的 calayer 的方法

- (CATransform3D) rotaX:(CGFloat) anguloX  rotaY:(CGFloat) anguloY rotaZ:(CGFloat) anguloZ
{         
    CATransform3D rX;
    CATransform3D rY;
    CATransform3D rZ;
    CATransform3D ret;

    // Apply all the rotations in order (x, y, z)
    rX = CATransform3DMakeRotation([self gradosARadianes:(anguloX)], 1.0f, 0.0f, 0.0f);
    ret = CATransform3DConcat(baseTransform, rX);
    rY = CATransform3DMakeRotation([self gradosARadianes:(anguloY)], 0.0f, 1.0f, 0.0f);
    ret = CATransform3DConcat(rX, rY);
    rZ = CATransform3DMakeRotation([self gradosARadianes:(anguloZ)], 0.0f, 0.0f, 1.0f);
    ret = CATransform3DConcat(rY, rZ);


    // Store finished result for next time start from there... 
    baseTransform = ret;

    return ret;
}

注意2:这是我发现的将四元数转换为欧拉的方法。

-(void) quaternionToEuler
{
    float matrix[3][3];
    float cx,sx;
    float cy,sy,yr;
    float cz,sz;
    matrix[0][0] = 1.0f - 2.0f * (qY * qY + qZ * qZ);
    matrix[0][1] = (2.0f * qX * qY) - (2.0f * qW * qZ);
    matrix[1][0] = 2.0f * (qX * qY + qW * qZ);
    matrix[1][1] = 1.0f - (2.0f * qX * qX) - (2.0f * qZ * qZ);
    matrix[2][0] = 2.0f * (qX * qZ - qW * qY);
    matrix[2][1] = 2.0f * (qY * qZ + qW * qX);
    matrix[2][2] = 1.0f - 2.0f * (qX * qX - qY * qY);


    sy = -matrix[2][0];
    cy = sqrt(1 - (sy * sy));
    yr = (float)atan2(sy,cy);
    eY = (yr * 180.0f) / (float)M_PI;

    if (sy != 1.0f && sy != -1.0f)   
    {
        cx = matrix[2][2] / cy;
        sx = matrix[2][1] / cy;
        eX = ((float)atan2(sx,cx) * 180.0f) / (float)M_PI;   // RAD TO DEG

        cz = matrix[0][0] / cy;
        sz = matrix[1][0] / cy;
        eZ = ((float)atan2(sz,cz) * 180.0f) / (float)M_PI;   // RAD TO DEG
    }
    else
    {
        cx = matrix[1][1];
        sx = -matrix[1][2];
        eX = ((float)atan2(sx,cx) * 180.0f) / (float)M_PI;   // RAD TO DEG

        cz = 1.0f;
        sz = 0.0f;
        eZ = ((float)atan2(sz,cz) * 180.0f) / (float)M_PI;   // RAD TO DEG
    }    
}

总之,我的目标是:在我的程序中使用 CALayer(不是 OpenGL)代表一个“子弹物理”框(骰子)。为了做到这一点,我使用 CATransformLayer 作为 6 个转换层到 3D 对象的容器。

-- 我现在得到的结果并不好,图形骰子旋转但显然不正确......所以我在这里做的事情完全错误......

问题是:鉴于我可以在子弹物理世界中获得 BOX 的“方向或旋转”,我如何将返回的四元数转换为可用于 CATransform3DMakeRotation 的东西(角度)。

非常感谢,

路易斯

【问题讨论】:

    标签: objective-c cocoa 3d quaternions catransform3d


    【解决方案1】:

    这是一种糟糕的方法。你从一个矩阵开始,把它变成一个四元数,把它变成欧拉角,然后把它们变成一个矩阵。

    请致电getCenterOfMassTransform().getBasis() 以获取btMatrix3x3,而不是getOrientation()。将其打包到CATransform3D 的左上角,其余部分用零填写(m44 除外,应为 1)。

    【讨论】:

    • 嗯,非常感谢您的澄清。我会更深入地研究这一切,显然会尝试你的建议。我会返回并发布结果。再次感谢,路易斯
    • 嗨@Ahruman,我正在创建一个评论你的答案,我需要发布新代码。
    猜你喜欢
    • 2011-04-19
    • 2020-02-26
    • 1970-01-01
    • 2012-03-14
    • 2021-01-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多