Поверните геометрию так, чтобы она была параллельна определенной линии - PullRequest
0 голосов
/ 22 сентября 2018

У меня есть эталонный тест line, например:

QVector3D line = QVector3D(38.0572, 29.2247, 35.3996);

Я создаю конус с помощью Qt3D следующим образом:

Qt3DCore::QEntity *newEntity = new Qt3DCore::QEntity();

Qt3DExtras::QConeMesh *mesh = new Qt3DExtras::QConeMesh();
mesh->setTopRadius(0.2);
mesh->setBottomRadius(1.0);
mesh->setLength(2.0);
for(int i = 0; i < mesh->geometry()->attributes().size(); ++i) {
    mesh->geometry()->attributes().at(i)->buffer()->setSyncData(true);
}

newEntity->addComponent(mesh);

Насколько я проверяю,ось конуса по умолчанию QVector3D(0, 1, 0):

Cone


Теперь я хочу повернуть / преобразовать мой конус так, чтобы ось моего конуса была параллельнак моей отметке line.Это можно сделать с помощью Qt3DCore::QTransform:

// ... previous code lines

Qt3DCore::QTransform *transform = new Qt3DCore::QTransform();
transform->setRotationX(?);
transform->setRotationY(?);
transform->setRotationZ(?);
transform->setRotation(?);
transform->setTranslation(?);
transform->setMatrix(?);

newEntity->addComponent(transform);

Я не знаю, как собрать компонент преобразования таким образом, чтобы ось моего конуса была параллельна эталону line.


Я изучил их, но пока не повезло:

https://en.wikipedia.org/wiki/Rotation_%28mathematics%29

https://en.wikipedia.org/wiki/Change_of_basis

1 Ответ

0 голосов
/ 23 сентября 2018

С помощью @FlorianBlume и его предложения q & a проблема была решена.Вот код матрицы преобразования:

Qt3DCore::QEntity *newEntity = new Qt3DCore::QEntity();

Qt3DExtras::QConeMesh *mesh = new Qt3DExtras::QConeMesh();
mesh->setTopRadius(0.2);
mesh->setBottomRadius(1.0);
mesh->setLength(2.0);
for(int i = 0; i < mesh->geometry()->attributes().size(); ++i) {
    mesh->geometry()->attributes().at(i)->buffer()->setSyncData(true);
}

newEntity->addComponent(mesh);

/* 
 * Now transform the cone to change its default axis:
 */

QVector3D k = QVector3D(0, 1, 0);   // Current cone axis
QVector3D n = QVector3D(38.0572, 29.2247, 35.3996); // To-be cone axis
n *= -1; // Inverse cone direction
n.normalize();
float teta = qAcos(QVector3D::dotProduct( k, n ));
QVector3D b = QVector3D::crossProduct( k , n );
b.normalize();

float q0 = qCos( teta / 2.0 );
float q1 = qSin( teta / 2.0 ) * b.x();
float q2 = qSin( teta / 2.0 ) * b.y();
float q3 = qSin( teta / 2.0 ) * b.z();

QMatrix4x4 Q = QMatrix4x4(
            qPow(q0, 2) + qPow(q1, 2) - qPow(q2, 2) - qPow(q3, 2), 2 * ( q1 * q2 - q0 * q3 )                            , 2 * ( q1 * q3 + q0 * q2 )                            , 0,
            2 * ( q2 * q1 + q0 * q3 )                            , qPow(q0, 2) - qPow(q1, 2) + qPow(q2, 2) - qPow(q3, 2), 2 * ( q2 * q3 - q0 * q1 )                            , 0,
            2 * ( q3 * q1 - q0 * q2 )                            , 2 * ( q3 * q2 + q0 * q1 )                            , qPow(q0, 2) - qPow(q1, 2) - qPow(q2, 2) + qPow(q3, 2), 0,
            0                                                    , 0                                                    , 0                                                    , 0
            );

Q.transposed(); // Transpose is needed to be able to employ "Q" matrix with Qt3DCore::QTransform

Q.setColumn(3, QVector4D(QVector3D(18.2066, 38.2821, 42.5333), 1)); // Set translation/move to be equal to QVector3D(18.2066, 38.2821, 42.5333)
                                                         // In addition to rotation, we want to move/translate our cone too!
                                                         // https://www.euclideanspace.com/maths/geometry/affine/matrix4x4/index.htm

Qt3DCore::QTransform *transform = new Qt3DCore::QTransform();
transform->setMatrix(Q);
newEntity->addComponent(transform);

Исходный конус с его осью по умолчанию и преобразованный конус с новой осью показаны ниже:

Original cone and transformed cone

...