У меня есть небольшая служебная программа Objective-C, которая отображает выпуклый корпус. (Это для устранения ошибки в другой программе, которая вычисляет выпуклый корпус при подготовке к пространственному статистическому анализу). Я пытаюсь визуализировать набор треугольников, каждый из которых имеет направленный наружу вектор. Я могу получить треугольники без проблем, но векторы сводят меня с ума.
Я бы хотел, чтобы векторы были простыми цилиндрами. Проблема в том, что я не могу просто объявить координаты, где верх и низ цилиндров принадлежат в 3D (например, как я могу для треугольников). Я должен сделать их, а затем повернуть и перевести их из положения по умолчанию вдоль оси Z. Я прочитал тонну об углах Эйлера, поворотах осей углов и кватернионах, большинство из которых относится к делу, но не направлено на то, что мне нужно: у большинства людей есть набор объектов, а затем необходимо повернуть объект в ответ на некоторый вклад. Мне нужно правильно разместить объект в трехмерной «сцене».
Я использую классы Cocoa3DTutorial , чтобы выручить меня, и, насколько я могу судить, они прекрасно работают, но бит вращения убивает меня.
Вот мои текущие усилия. Это дает мне цилиндры, которые расположены правильно, но все указывают вдоль оси z (как на этом изображении: . Мы смотрим в направлении -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)), а не набор из трех вращений. Мой код, вероятно, проблема, но я не вижу, как.