Как получить" стандартные " вращения из трех.js при использовании кватернионов?
Новичок участник stackoverflow, новичок 3D программист, и далеко от математики wiz... поэтому я постараюсь сформулировать этот вопрос как можно яснее, надеясь, что он имеет смысл, и надеясь на ответ, который не будет в миле над моей головой.
Я написал очень классное приложение, используя три.js, который позволяет пользователю летать через 3D-пространство и исследовать Солнечную систему. Модель полета свободно основана на Fly.Пример контроллера/расширение в трех.пакет js, который научил меня использовать кватернионы для сохраняя все вращения осей относительно друг друга. Летающая часть все работает отлично.
вот моя дилемма: при использовании кватернионов, как я могу вывести "нормальные" (я не знаю, как еще это назвать) значения вращения, чтобы определить, в каком направлении я смотрю? При использовании кватернионов структура "вращения" внутри объекта камеры остается на уровне 0,0,0. Поэтому, хотя я могу свободно летать в пространстве под любым углом, я не могу понять, как определить, в каком направлении я на самом деле смотрю. Есть встроенный в три.функция js или другой простой способ конвертировать это?
Я нашел несколько похожих, запутанных указателей в интернете, но ничего не могу расшифровать и использовать в трех.js. Спасибо.
2 ответов
Это хороший вопрос.
когда объект находится в ориентации по умолчанию, его можно считать смотрящим в направлении его внутренней, положительной оси Z. (Исключение составляет камера, который смотрит в направлении своего внутреннего отрицательный ось z.)
таким образом, когда объект поворачивается, вы можете получить направление объекта, применяя кватернион объекта к единичному вектору, указывающему в направлении положительной оси z (отрицательная ось z для камеры).
var zVec = new THREE.Vector3( 0, 0, 1 );
zVec.applyQuaternion( object.quaternion );
это вернет единичный вектор, указывающий в направлении, в котором объект "обращен".
Если объект является дочерним объектом другого повернутого объекта, то ситуация более сложная.
EDIT: обновлено для r.58. Спасибо @цзяньшуй.
// Pass the obj.quaternion that you want to convert here:
//*********************************************************
function quatToEuler (q1) {
var pitchYawRoll = new THREE.Vector3();
sqw = q1.w*q1.w;
sqx = q1.x*q1.x;
sqy = q1.y*q1.y;
sqz = q1.z*q1.z;
unit = sqx + sqy + sqz + sqw; // if normalised is one, otherwise is correction factor
test = q1.x*q1.y + q1.z*q1.w;
if (test > 0.499*unit) { // singularity at north pole
heading = 2 * Math.atan2(q1.x,q1.w);
attitude = Math.PI/2;
bank = 0;
return;
}
if (test < -0.499*unit) { // singularity at south pole
heading = -2 * Math.atan2(q1.x,q1.w);
attitude = -Math.PI/2;
bank = 0;
return;
}
else {
heading = Math.atan2(2*q1.y*q1.w-2*q1.x*q1.z , sqx - sqy - sqz + sqw);
attitude = Math.asin(2*test/unit);
bank = Math.atan2(2*q1.x*q1.w-2*q1.y*q1.z , -sqx + sqy - sqz + sqw)
}
pitchYawRoll.z = Math.floor(attitude * 1000) / 1000;
pitchYawRoll.y = Math.floor(heading * 1000) / 1000;
pitchYawRoll.x = Math.floor(bank * 1000) / 1000;
return pitchYawRoll;
}
// Then, if I want the specific yaw (rotation around y), I pass the results of
// pitchYawRoll.y into the following to get back the angle in radians which is
// what can be set to the object's rotation.
//*********************************************************
function eulerToAngle(rot) {
var ca = 0;
if (rot > 0)
{ ca = (Math.PI*2) - rot; }
else
{ ca = -rot }
return (ca / ((Math.PI*2)/360)); // camera angle radians converted to degrees
}