【问题标题】:Rotating Ellipse Curve in Three.jsThree.js 中的旋转椭圆曲线
【发布时间】:2026-01-22 19:30:01
【问题描述】:

目标

我正在尝试创建一个相机应该在其上移动的 EllipseCurve (https://threejs.org/docs/#api/en/extras/curves/EllipseCurve)。

我为实现目标做了什么?

到目前为止,这是椭圆的代码。

var curve = new THREE.EllipseCurve(
    0,0,
    1, 1,
    0, 2 * Math.PI,
    false,
    1.57
)

const points = curve.getPoints( 50 );
const geometry = new THREE.BufferGeometry().setFromPoints( points );


var material = new THREE.LineBasicMaterial( { color : 0xffffff } );

// Create the final object to add to the scene
var curveObject = new THREE.Line( geometry, material );

scene.add(curveObject);

我可以在这样的场景中看到它:

问题

我尝试将椭圆曲线绕 x 轴顺时针旋转 90 度。正如我从文档中了解到的,定义函数的最后一个参数应该旋转它。

const curve = new THREE.EllipseCurve(
    0,  0,            // ax, aY
    10, 10,           // xRadius, yRadius
    0,  2 * Math.PI,  // aStartAngle, aEndAngle
    false,            // aClockwise
    0                 // aRotation
);

提前感谢您的回答。我对 Three.js 很陌生,如果这个问题可能很愚蠢,我很抱歉:D

【问题讨论】:

  • 最后一个参数是围绕Z轴旋转曲线,因此曲线本身在XY平面上。

标签: javascript three.js 3d


【解决方案1】:

aRotation,角度旋转,将影响该曲线其他角度设置的局部原点。它不是整个椭圆旋转,而是相对于默认值的任何偏移的方向。不同的起点。它会将吃豆人的嘴变成 +/- 180 度的向后吃豆人的嘴。要在世界空间中旋转整个曲线,请使用可用的各种方法之一,例如curve.rotation.set(0,1,0) 或rotation.y += 1。有关旋转的特定变体,请参阅文档。

【讨论】:

    【解决方案2】:

    获取曲线上的一个点并对其应用矩阵4。

    这是一个关于如何做到这一点的概念(请参阅动画循环中带有cam 的行,最好使用“整页”观看):

    body{
      overflow: hidden;
      margin: 0;
    }
    <script type="module">
    import * as THREE from "https://cdn.skypack.dev/three@0.134.0";
    import {
      OrbitControls
    } from "https://cdn.skypack.dev/three@0.134.0/examples/jsm/controls/OrbitControls.js";
    
    let scene = new THREE.Scene();
    let camera = new THREE.PerspectiveCamera(60, innerWidth / innerHeight, 1, 1000);
    camera.position.set(-10, 10, 10);
    let renderer = new THREE.WebGLRenderer({
      antialias: true
    });
    renderer.setSize(innerWidth, innerHeight);
    renderer.autoClear = false;
    document.body.appendChild(renderer.domElement);
    window.addEventListener("resize", () => {
      camera.aspect = innerWidth / innerHeight;
      camera.updateProjectionMatrix();
      renderer.setSize(innerWidth, innerHeight);
    })
    
    let controls = new OrbitControls(camera, renderer.domElement);
    
    let light = new THREE.DirectionalLight(0xffffff, 1);
    light.position.setScalar(1);
    scene.add(light, new THREE.AmbientLight(0xffffff, 0.5));
    
    let grid = new THREE.GridHelper();
    grid.position.y = -5;
    scene.add(grid);
    
    let obj = new THREE.Mesh(new THREE.IcosahedronGeometry(1, 0), new THREE.MeshLambertMaterial({
      color: "aqua"
    }));
    scene.add(obj);
    
    let curve = new THREE.EllipseCurve(0, 0, 10, 5);
    
    let line = new THREE.Line(new THREE.BufferGeometry().setFromPoints(curve.getSpacedPoints(100)), new THREE.LineBasicMaterial({
      color: "yellow"
    }));
    line.rotation.x = -Math.PI * 0.25;
    line.rotation.z = Math.PI * 0.125;
    line.position.x = 5;
    scene.add(line);
    
    let cam = new THREE.PerspectiveCamera(25, 1, 1.5, 25);
    let camHelper = new THREE.CameraHelper(cam);
    scene.add(camHelper);
    
    let clock = new THREE.Clock();
    let v = new THREE.Vector3();
    
    renderer.setAnimationLoop(() => {
    
      let t = (clock.getElapsedTime() * 0.05) % 1;
      
      // magic is in these lines //////////////////
      cam.position.copy(curve.getPointAt(t, v));
      cam.position.applyMatrix4(line.matrixWorld);
      cam.lookAt(obj.position);
      /////////////////////////////////////////////
    
      renderer.clear();
      renderer.setViewport(0, 0, innerWidth, innerHeight);
      renderer.render(scene, camera);
      renderer.setViewport(0, innerHeight - 256, 256, 256);
      renderer.render(scene, cam);
    })
    
    </script>

    【讨论】: