Ориентируйте вращение объекта в точку сплайна, касательную в THREE.JS

я используюSplineCurve3 чтобы построить линию только по осям X и Y, у меня есть куб, успешно анимирующий вдоль этой линии, используяspline.getPoint(t) где t 0-1 во времени. Я пытаюсь сориентировать куб на линию через вектор вверх, который является Y, используя скалярное произведение.

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

Вот моя функция рендеринга:

function render() {

    var updateMatrix = new THREE.Matrix4(); 
    updateMatrix.setPosition(spline.getPoint(t));

    var angle = new THREE.Vector3(0,1,0).dot(spline.getTangent(t).normalize());

    var quat = new THREE.Quaternion;
    quat.setFromAxisAngle(new THREE.Vector3(0,0,1), angle);
    updateMatrix.setRotationFromQuaternion(quat);

    marker.rotation.getRotationFromMatrix(updateMatrix);
    marker.matrixWorld = updateMatrix;

    t = (t >= 1) ? 0 : t += 0.002;

    renderer.render(scene, camera); 
}

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

Вы можете редактировать мой -пример jsfiddle

 manthrax08 сент. 2016 г., 09:45
Я знаю, что это старый пост, но хотел выкинуть уменьшенную версию, которую другие могут найти полезной:code obj.position.copy(spline.getPoint( t )); obj.lookAt(spline.getTangent( t ).add(obj.position));

Ответы на вопрос(1)

Решение Вопроса

object.matrix непосредственно, а вместо этого просто установить объектposition, rotation, а такжеscale, Позвольте библиотеке обрабатывать матричные манипуляции. Тебе нужно иметьmatrixAutoUpdate = true;.

Чтобы обработать вращающуюся часть, сначала получите касательную к кривой.

tangent = spline.getTangent( t ).normalize();

Вы хотите повернуть объект так, чтобы его вектор вверх (локальный вектор y) указывал в направлении вектора касательной кривой. Сначала рассчитайте ось вращения вокруг. Ось представляет собой вектор, перпендикулярный плоскости, определяемой вектором вверх и касательным вектором. Вы используете перекрестный продукт, чтобы получить этот вектор.

axis.crossVectors( up, tangent ).normalize();

Обратите внимание, что в вашем случае, поскольку сплайн лежит в плоскости, перпендикулярной оси z, только что вычисленная ось будет параллельна оси z. Однако он может указывать в направлении положительной оси z или отрицательной оси z - это зависит от направления касательного вектора.

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

radians = Math.acos( up.dot( tangent ) );

Теперь извлеки кватернион из оси и угла.

marker.quaternion.setFromAxisAngle( axis, radians );

РЕДАКТИРОВАТЬ: обновленная скрипка:http://jsfiddle.net/SCXNQ/891/ за тройку

 14 янв. 2015 г., 15:25
В последних версиях threejs вместо axis.cross следует изменить значение axis.crossVectors. (Я внес изменения ...) Могут быть и другие незначительные изменения?
 Neil25 окт. 2012 г., 10:32
отредактированный ответ со ссылкой на демонстрацию с использованием r52, теперь использует setEulerFromRotationMatrix (r50) вместо getRotationFromMatrix (r49).

Ваш ответ на вопрос