Преобразование из кватерниона физики пули в угол для использования с CATransform3DMakeRotation - PullRequest
0 голосов
/ 04 марта 2012

Я построил трехмерную кость с шестью гранями, используя CATransformLayer, используя его в качестве слоя контейнера, в котором 6 преобразованных слоев превращаются в трехмерный объект, который может вращаться в пространстве. Я получил идею отсюда . Это работает хорошо, и я могу вращать «кости», вызывая CATransform3DMakeRotation на верхнем слое, кости вращается и работает хорошо.

Следующим шагом было вставить «физику пули» в программу. У меня это работает, но я застрял, потому что я не знаю, как преобразовать «кватернионную ориентацию пули» кости в ее физическом мире в углы поворота, которые я могу передать моему методу контейнера CALayer.

Вот что я делаю:

1) Призыв к «физике пуль» для получения ориентации костей:

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

2) Преобразовать кватернион в эйлер (много времени, пытаясь найти ответ, нашел метод, скопированный ниже для этого) qW = quatO.getW (); qX = quatO.getX (); qY = quatO.getY (); qZ = quatO.getZ (); [self quaternionToEuler];

3) Применить новые углы Эйлера к моему CALayer (sCtrl)

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

Примечание 1: этот метод используется для поворота моего калибра

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

Заранее большое спасибо,

Луис

1 Ответ

1 голос
/ 05 марта 2012

Это ужасный подход. Вы начинаете с матрицы, превращаете ее в кватернион, превращаете ее в углы Эйлера, а затем превращаете в матрицу.

Вместо getOrientation(), позвоните getCenterOfMassTransform().getBasis(), чтобы получить btMatrix3x3. Упакуйте это в верхнем левом углу CATransform3D и заполните остальные нулями (кроме m44, который должен быть 1).

...