如何使对象跟随 3D 图形中的轨迹
How to make an object follow a track in 3D graphics
我设法让我的物体沿着轨道移动,当它从左向右移动时它也面向移动方向,但是在轨道的后半部分,物体向右移动离开它颠倒了,我不知道为什么。
您可以通过克隆 this GitHub repo 并在浏览器中打开 ./samples/truck-on-track.html
文件来查看实际效果。无需安装任何东西或 运行 任何东西,这是一个静态 html 页面。
代码的重要部分是:
const track = [
0, -50, 0,
40, -65, 10,
90, -35, 60,
10, -15, 250,
-60, -40, 130,
-120, -35, 30,
-20, -57, 5
];
const actions = [];
const invLinearVelocity = 3;
const invAngularVelocity = 30;
const position = truck.getPosition();
const truckPosition = [0, 15, 0];
for (let iThis = 0; iThis < track.length; iThis += 3) {
const iNext = iThis + 3 >= track.length ? 0 : iThis + 3;
const thisTrackLocation = Vector.extract3D(track, iThis);
const nextTracklocation = Vector.extract3D(track, iNext);
const vector = Vector.sub(nextTracklocation, thisTrackLocation);
const angleY = Math.atan2(vector[2], vector[0]);
const angleZ = Math.atan2(vector[1], vector[0]);
const nextAngle = [0, angleY, angleZ];
actions.push(frag.PositionAnimationAction(position)
.rotateTo(nextAngle, invAngularVelocity));
actions.push(frag.PositionAnimationAction(position)
.moveTo(Vector.add(nextTracklocation, truckPosition), invLinearVelocity));
}
frag.Animation().sequence(actions, true).start();
我的数学有问题。经过一番研究,我写了这个函数,解决了这个问题。查看 this GitHub repo 以获得完整的解决方案。关键函数是:
eulerAngles: function(directionVector, upVector) {
const Vector = window.frag.Vector;
if (!upVector) upVector = [0, 1, 0];
const dir = Vector.normalize(directionVector);
const up = Vector.normalize(upVector);
const pitch = Math.asin(dir[1]);
const yaw = Math.atan2(dir[0], dir[2]);
const wingDir = [-dir[2], 0, dir[0]];
const vertical = Vector.cross(wingDir, dir);
const roll = Math.atan2(Vector.dot(wingDir, up), Vector.dot(vertical, up));
return [roll, yaw, pitch];
}
我设法让我的物体沿着轨道移动,当它从左向右移动时它也面向移动方向,但是在轨道的后半部分,物体向右移动离开它颠倒了,我不知道为什么。
您可以通过克隆 this GitHub repo 并在浏览器中打开 ./samples/truck-on-track.html
文件来查看实际效果。无需安装任何东西或 运行 任何东西,这是一个静态 html 页面。
代码的重要部分是:
const track = [
0, -50, 0,
40, -65, 10,
90, -35, 60,
10, -15, 250,
-60, -40, 130,
-120, -35, 30,
-20, -57, 5
];
const actions = [];
const invLinearVelocity = 3;
const invAngularVelocity = 30;
const position = truck.getPosition();
const truckPosition = [0, 15, 0];
for (let iThis = 0; iThis < track.length; iThis += 3) {
const iNext = iThis + 3 >= track.length ? 0 : iThis + 3;
const thisTrackLocation = Vector.extract3D(track, iThis);
const nextTracklocation = Vector.extract3D(track, iNext);
const vector = Vector.sub(nextTracklocation, thisTrackLocation);
const angleY = Math.atan2(vector[2], vector[0]);
const angleZ = Math.atan2(vector[1], vector[0]);
const nextAngle = [0, angleY, angleZ];
actions.push(frag.PositionAnimationAction(position)
.rotateTo(nextAngle, invAngularVelocity));
actions.push(frag.PositionAnimationAction(position)
.moveTo(Vector.add(nextTracklocation, truckPosition), invLinearVelocity));
}
frag.Animation().sequence(actions, true).start();
我的数学有问题。经过一番研究,我写了这个函数,解决了这个问题。查看 this GitHub repo 以获得完整的解决方案。关键函数是:
eulerAngles: function(directionVector, upVector) {
const Vector = window.frag.Vector;
if (!upVector) upVector = [0, 1, 0];
const dir = Vector.normalize(directionVector);
const up = Vector.normalize(upVector);
const pitch = Math.asin(dir[1]);
const yaw = Math.atan2(dir[0], dir[2]);
const wingDir = [-dir[2], 0, dir[0]];
const vertical = Vector.cross(wingDir, dir);
const roll = Math.atan2(Vector.dot(wingDir, up), Vector.dot(vertical, up));
return [roll, yaw, pitch];
}