Не удается правильно повернуть цилиндр в openGL в нужное положение - PullRequest
0 голосов
/ 07 сентября 2010

У меня есть небольшая служебная программа Objective-C, которая отображает выпуклый корпус. (Это для устранения ошибки в другой программе, которая вычисляет выпуклый корпус при подготовке к пространственному статистическому анализу). Я пытаюсь визуализировать набор треугольников, каждый из которых имеет направленный наружу вектор. Я могу получить треугольники без проблем, но векторы сводят меня с ума.

Я бы хотел, чтобы векторы были простыми цилиндрами. Проблема в том, что я не могу просто объявить координаты, где верх и низ цилиндров принадлежат в 3D (например, как я могу для треугольников). Я должен сделать их, а затем повернуть и перевести их из положения по умолчанию вдоль оси Z. Я прочитал тонну об углах Эйлера, поворотах осей углов и кватернионах, большинство из которых относится к делу, но не направлено на то, что мне нужно: у большинства людей есть набор объектов, а затем необходимо повернуть объект в ответ на некоторый вклад. Мне нужно правильно разместить объект в трехмерной «сцене».

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

Вот мои текущие усилия. Это дает мне цилиндры, которые расположены правильно, но все указывают вдоль оси z (как на этом изображении: alt text. Мы смотрим в направлении -z. Выступающий сзади треугольник не является частью корпуса; для тестирования / отладка. Ортогональные цилиндры - это более или менее координатные оси, и сферы должны гарантировать, что оси расположены правильно, так как я должен использовать вращение, чтобы правильно расположить эти цилиндры. И кстати, когда я использую этот алгоритм, -векторы тоже терпят неудачу, хотя и по-другому, выходя нормально к плоскостям, но все они указывают на + z вместо некоторого в -z)

от Render3DDocument.m:

// Make the out-pointing vector
C3DTCylinder  *outVectTube;
C3DTEntity    *outVectEntity;
Point3DFloat  *sideCtr = [thisSide centerOfMass];
outVectTube = [C3DTCylinder cylinderWithBase: tubeRadius top: tubeRadius height: tubeRadius*10 slices: 16 stacks: 16];
outVectEntity = [C3DTEntity entityWithStyle:triColor
                   geometry:outVectTube];
Point3DFloat *outVect = [[thisSide inVect] opposite];
Point3DFloat *unitZ = [Point3DFloat pointWithX:0 Y:0 Z:1.0f];
Point3DFloat *rotAxis = [outVect crossWith:unitZ];
double rotAngle = [outVect angleWith:unitZ];
[outVectEntity setRotationX: rotAxis.x
              Y: rotAxis.y
              Z: rotAxis.z
              W: rotAngle];
[outVectEntity setTranslationX:sideCtr.x - ctrX  
              Y:sideCtr.y - ctrY
              Z:sideCtr.z - ctrZ];
[aScene addChild:outVectEntity];

(Обратите внимание, что Point3DFloat - это в основном векторный класс, и что Side (как thisSide) - это набор из четырех Point3DFloat, по одному для каждой вершины и один для вектора, который указывает на центр корпуса) .

от C3DTEntity.m:

if (_hasTransform) {
    glPushMatrix();

    // Translation
    if ((_translation.x != 0.0) || (_translation.y != 0.0) || (_translation.z != 0.0)) {
        glTranslatef(_translation.x, _translation.y, _translation.z);
    }

    // Scaling
    if ((_scaling.x != 1.0) || (_scaling.y != 1.0) || (_scaling.z != 1.0)) {
        glScalef(_scaling.x, _scaling.y, _scaling.z);
    }

    // Rotation
    glTranslatef(-_rotationCenter.x, -_rotationCenter.y, -_rotationCenter.z);

    if (_rotation.w != 0.0) {
        glRotatef(_rotation.w, _rotation.x, _rotation.y, _rotation.z);
    } else {
        if (_rotation.x != 0.0)
            glRotatef(_rotation.x, 1.0f, 0.0f, 0.0f);
        if (_rotation.y != 0.0)
            glRotatef(_rotation.y, 0.0f, 1.0f, 0.0f);
        if (_rotation.z != 0.0)
            glRotatef(_rotation.z, 0.0f, 0.0f, 1.0f);
    }

    glTranslatef(_rotationCenter.x, _rotationCenter.y, _rotationCenter.z);
}

Я добавил бит в приведенный выше код, который использует один поворот вокруг оси (бит if (_rotation.w! = 0.0)), а не набор из трех вращений. Мой код, вероятно, проблема, но я не вижу, как.

Ответы [ 2 ]

0 голосов
/ 07 сентября 2010

Кажется, проблема в том, что glrotatef () ожидает градусы, а я дал ей радианы. Кроме того, вращение по часовой стрелке считается положительным, и поэтому знак вращения был неправильным. Это исправленный код:

double rotAngle = -[outVect angleWith:unitZ];   // radians
[outVectEntity setRotationX: rotAxis.x
                          Y: rotAxis.y
                          Z: rotAxis.z
                          W: rotAngle * 180.0 / M_PI ];

Теперь я вижу, что в моей другой программе неправильно заданы inVects (приведенные ниже outVects проскакивают через корпус, а не указывают на каждую грань), и теперь я могу отследить эту ошибку в другой программе ... завтра alt text

0 голосов
/ 07 сентября 2010

Если ваши внешние объекты не все указывают на правильное направление, вам, возможно, придется проверить намотку ваших треугольников - все ли они ориентированы одинаково?

Кроме того, может быть полезно провести линиюдля каждого outvec (используйте среднее из трех вершин вашего треугольника в качестве источника и нарисуйте линию длиной в несколько единиц (в зависимости от масштаба вашей сцены) в направлении outvect. Таким образом, вы можете быть уверены, что всеваши векторы ориентированы правильно.

Как вы рассчитываете свои выбросы?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...