模型按照路径行驶

309 阅读2分钟

模型按照路径行驶

实现思路:

  • 绘制固定路径。
  • 在循环渲染函数中,改变模型的位置实现移动。

绘制固定路径

  • 使用.SplineCurve()创建一个平滑的二维样条曲线。
// 绘制移动路径
const curve = new THREE.SplineCurve([
    new THREE.Vector2(-10, 20),
    new THREE.Vector2(-5, 5),
    new THREE.Vector2(0, 0),
    new THREE.Vector2(5, -5),
    new THREE.Vector2(10, 0),
    new THREE.Vector2(5, 10),
    new THREE.Vector2(-5, 10),
    new THREE.Vector2(-10, -10),
    new THREE.Vector2(-15, -8),
    new THREE.Vector2(-10, 20),
]);
// 绘制路线
const points = curve.getPoints(50);
const geometry = new THREE.BufferGeometry().setFromPoints(points);
const material = new THREE.LineBasicMaterial({ color: 0xff0000 });
const splineObject = new THREE.Line(geometry, material);
splineObject.rotation.x = Math.PI * 0.5;
splineObject.position.y = 0.05;
scene.add(splineObject);
  • 使用.CatmullRomCurve3()创建一条平滑的三维样条曲线。
// 绘制移动路径
const curve = new THREE.CatmullRomCurve3(
    [
        new THREE.Vector3(86, 0, 115),
        new THREE.Vector3(86, 0, -115),
        new THREE.Vector3(37, 0, -115),
        new THREE.Vector3(37, 0, 115),
        new THREE.Vector3(-15, 0, 115),
        new THREE.Vector3(-15, 0, -115),
        new THREE.Vector3(-86, 0, -115),
        new THREE.Vector3(-86, 0, 115),
        new THREE.Vector3(-15, 0, 115),
        new THREE.Vector3(-15, 0, -115),
        new THREE.Vector3(37, 0, -115),
        new THREE.Vector3(37, 0, 115),
    ],
    true,
    'catmullrom',
    0.15
);
// 绘制路线
let geometry = new THREE.BufferGeometry();
geometry.setFromPoints(curve.getPoints(10000));
let material = new THREE.LineDashedMaterial({ color: 0x4488ff });
scene.add(new THREE.Line(geometry, material));
  • 使用.CurvePath()创建组合曲线。
// 创建组合曲线对象CurvePath
const curve = new THREE.CurvePath();
curve.autoClose = true;
// 把多个线条插入到CurvePath中
curve.curves.push(
    new THREE.LineCurve(new THREE.Vector2(87, 102), new THREE.Vector2(87, -102)),
    new THREE.ArcCurve(62, -102, 25, 0, Math.PI, true),
    new THREE.LineCurve(new THREE.Vector2(37, -102), new THREE.Vector2(37, 100)),
    new THREE.ArcCurve(11, 100, 26, 0, Math.PI, false),
    new THREE.LineCurve(new THREE.Vector2(-15, 100), new THREE.Vector2(-15, -90)),
    new THREE.ArcCurve(-50.5, -90, 35.5, 0, Math.PI, true),
    new THREE.LineCurve(new THREE.Vector2(-86, -90), new THREE.Vector2(-86, 90)),
    new THREE.ArcCurve(-50.5, 90, 35.5, Math.PI, 2 * Math.PI, true),
    new THREE.LineCurve(new THREE.Vector2(-15, 90), new THREE.Vector2(-15, -100)),
    new THREE.ArcCurve(11, -100, 26, Math.PI, 2 * Math.PI, false),
    new THREE.LineCurve(new THREE.Vector2(37, -100), new THREE.Vector2(37, 102)),
    new THREE.ArcCurve(62, 102, 25, Math.PI, 2 * Math.PI, true)
);
// 绘制路线
const points = curve.getPoints(200);
const geometry = new THREE.BufferGeometry().setFromPoints(points);
const material = new THREE.LineBasicMaterial({ color: 0xff0000 });
const splineObject = new THREE.Line(geometry, material);
splineObject.rotation.x = Math.PI * 0.5;
scene.add(splineObject);

改变模型的位置实现移动

  • 二维样条曲线
let progress = 0;
function render() {
    requestAnimationFrameIndex = requestAnimationFrame(render);
    // 巡检车辆移动
    progress += 0.0002;
    if (progress > 1) progress = 0;
    //取路径上当前点的坐标
    const { x, y } = curve.getPointAt(progress);
    const { x: x2, y: y2 } = curve.getPointAt(progress + 0.0001);
    //设置车模型坐标为在相机路径上当前点的位置
    modelCar?.position?.set(x, 0, y);
    // 转向
    modelCar.lookAt(x2, 0, y2);
    renderer?.render(scene, camera);
}
  • 三维样条曲线
let progress = 0;
function render() {
    requestAnimationFrameIndex = requestAnimationFrame(render);
    // 巡检车辆移动
    progress += 0.0002;
    if (progress > 1) progress = 0;
    //取路径上当前点的坐标
    const { x, y, z } = curve.getPointAt(progress);
    const { x: x2, y: y2 } = curve.getPointAt(progress + 0.0001);
    //设置车模型坐标为在相机路径上当前点的位置
    modelCar?.position?.set(x, y, z);
    // 转向
    modelCar.lookAt(x2, y2, z2);
}