Я пытаюсь сделать круг (фактически плоский цилиндр) вращаться так, чтобы край пересекал две точки в мировом положении. Эти две точки могут находиться где угодно на сфере. Сфера имеет тот же радиус и положение, что и цилиндр. происхождение обоих составляет [0,0,0].
Это немного сложно объяснить, поэтому я включил три фотографии, которые, я надеюсь, иллюстрируют то, что я пытаюсь выполнить.
Здесь вы видите, что я пытаюсь выполнить. Желтый круг представляет одну из точек вдоль сферы, а красный круг представляет другую точку. Синяя линия - фактически плоский цилиндр, проходящий через сферу, и вращается так, что он проходит через обе точки.
Вот еще одна подобная картина, но с точками в разных местах.
На этом снимке цилиндр можно увидеть полностью, поскольку сфера скрыта.
Теперь, я действительно ужасен в математике, поэтому мне действительно понравился бы ответ, составленный из псевдокода или языка программирования. И если мне так повезет, что я. Вращение кругов может быть представлено либо кватернионом, либо матрицей
Пока что я попытался, вращает цилиндр с вектором вверх в одну из точек и передний вектор по направлению к другой точке. Но я не могу заставить его работать. Я также пробовал другие решения, большинство из которых связаны с двумя поворотами (по одному для каждой точки), но в итоге у меня возникают проблемы при объединении поворотов.
Вот мой текущий нерабочий код:
Этот код заставляет круг проходить через первую точку, а затем поворачивает его с помощью "вектора вверх" в одну и ту же точку, это второе вращение изменяется в зависимости от положения первой точки и отслежено по всему месту.
//calculate direction vector between the two points
point1point2dir.set(point1Pos);
//subtract point two position
point1point2dir.sub(point2Pos);
//normalize
point1point2dir.nor();
//make two quaternions for rotation
Quaternion rot1=new Quaternion();
Quaternion rot2=new Quaternion();
//set first rotation two a rotation between X-axis and point1 position. Vector3.X = (1,0,0)
rot1.set(m.quatUtils.getRot(Vector3.X, point1Pos));
//crossmuliply direction vector between the two points with X-axis
point1point2dir.crs(Vector3.X);
//set the second rotation to a rotation between Z-Axis and the crossmultiplied direction vector
rot2.set(m.quatUtils.getRot(Vector3.Z, point1point2dir));
//multiply the two rotations
rot1.mul(rot2);
//apply the rotation to the cylinders matrix
cylinderMatrix.rotate(rot1);
//the function that gets the quaternion rotation between two vectors
Quaternion getRot(Vector3 pStart, Vector3 pDest) {
start.set(pStart);
dest.set(pDest);
start.nor();
dest.nor();
cosTheta = Vector3.dot(start.x, start.y, start.z, dest.x, dest.y,
dest.z);
rotationAxis.set(0.0f, 0.0f, 0.0f);
if (cosTheta < -1.0f + 0.001f) {
rotationAxis.set(Z_AXIS);
rotationAxis.crs(start);
if (rotationAxis.len2() < 0.01f) {
rotationAxis.set(X_AXIS);
rotationAxis.crs(start);
}
rotationAxis.nor();
resultQuat.set(rotationAxis, 180.0f);
return resultQuat;
}
rotationAxis.set(start);
rotationAxis.crs(dest);
s = (float) Math.sqrt((1 + cosTheta) * 2);
invs = 1.0f / s;
resultQuat.set(rotationAxis.x * invs, rotationAxis.y * invs,
rotationAxis.z * invs, s * 0.5f);
return resultQuat;
}
Я понял решение! Это было действительно просто. Я не знаю, как мне удалось свести математику так же сильно, как и раньше. Я на самом деле потратил много времени на это> :)
Извините, если я потратил впустую время anybodys!
Решение:
Вот рабочий код (yay):
//the rotation
Quaternion rot=new Quaternion();
//the direction from point1 to point 2 (the point positions are in this case also the direction vectors from center)
point1point2dir.set(point1Pos);
point1point2dir.sub(point2Pos);
point1point2dir.nor();
//crossmultiplied with point2
point1point2dir.crs(point2Pos);
//set the rotation to the rotation between Z-axis and the crossmultiplied direction between point 1 and 2
rot.set(m.quatUtils.getRot(Vector3.Z, point1point2dir));
//apply rotation
ekvatorMatrix.rotate(rot);
И вот код для функции, возвращающий кватернион между двумя векторами:
Quaternion getRot(Vector3 pStart, Vector3 pDest) {
start.set(pStart);
dest.set(pDest);
start.nor();
dest.nor();
cosTheta = Vector3.dot(start.x, start.y, start.z, dest.x, dest.y,
dest.z);
rotationAxis.set(0.0f, 0.0f, 0.0f);
if (cosTheta < -1.0f + 0.001f) {
rotationAxis.set(Z_AXIS);
rotationAxis.crs(start);
if (rotationAxis.len2() < 0.01f) {
rotationAxis.set(X_AXIS);
rotationAxis.crs(start);
}
rotationAxis.nor();
resultQuat.set(rotationAxis, 180.0f);
return resultQuat;
}
rotationAxis.set(start);
rotationAxis.crs(dest);
s = (float) Math.sqrt((1 + cosTheta) * 2);
invs = 1.0f / s;
resultQuat.set(rotationAxis.x * invs, rotationAxis.y * invs,
rotationAxis.z * invs, s * 0.5f);
return resultQuat;
}
Я бы предложил это решение:
Вычислите v1 и v2 как векторы от центра сферы к каждой точке, которую вы хотите, чтобы цилиндр проходил через корыто.
Переверните произведение v1 и v2, чтобы получить вектор вверх по цилиндру, назовем его n.
Расположите центр цилиндра в центре сферы.
Поверните цилиндр, используя n как вектор вверх.
Предполагая, что начальный цилиндр ориентирован по оси с концами "круга" в положительном и отрицательном направлении X, и если предположить, что цилиндр и сфера первоначально имеют размер единицы (радиус = 1,0), я бы сделал следующее:
Преобразуйте представление координат мира из красных и "желтых" точек (пусть просто для удовольствия назовите их A и B мы должны) до нормализованных векторов, указывающих из центра [0,0,0] (отныне называемого C)
Вычислите угол между CA и CB (который действительно находится только между A и B). Позвольте называть этот угол W
Вычислите вектор, перпендикулярный как A, так и B, выполнив кросс-произведение. Позволяет называть этот новый вектор D.
Найдите матрицу вращения, которая вращается от [0,0,1] до B. Позволяет вызвать этот M1. Это можно сделать так же, как в пункте 3 (создать перпендикулярный вектор и повернуть вокруг него единичную матрицу с углом между нормализованными векторами).
Найдите матрицу вращения, вращающую W вокруг D. Позвольте называть это M2
Объединить M1 + M2 в M3
Вы получаете M3
Это не было проверено, и поэтому я не знаю, работает ли это.